Home » Php » php – Public __construct , retrieve user information class

php – Public __construct , retrieve user information class

Posted by: admin February 25, 2020 Leave a comment

Questions:

I am looking to create a class and retrieve the account information in private and then make a public Getters
do you have any advice to improve this code?

    private $db;
    private $get;

    public function __construct($db = null)
    {
        $this->db = new Database();
    }

    private function get($information = 0, $userid = null)
    {
        if ($userid === null) 
        {
            //if ($this->isOnline()) {
                $token = $_COOKIE['session'];

                $req = $this->db->query('SELECT user_id FROM cms_sessions WHERE token = :token',
                array(
                "token" => $token
                ));

                $userid = $req[0]['user_id'];
            //}
        }

        $req = $this->db->query('SELECT '. $information .' FROM users INNER JOIN users_info ON users.id = users_info.user_id WHERE users.id = :userid',
        array(
        "userid" => $userid
        ));

        return (count($req) > 0) ? htmlspecialchars($req[0][$information]) : "Erreur";
    }

    public function getId() 
    {
        $req = $this->db->query('SELECT user_id FROM cms_sessions WHERE token = :token',
        array(
        "token" => @$_COOKIE['session']
        ));

        return (count($req) > 0) ? intval($req[0]['user_id']) : "0";
    }

    public function getIP() 
    {
        return $this->get('last_ip');
    }


    public function getGender() 
    {
        return $this->get('gender');
    }

}

but this gives me ‘0’ once I try to retrieve user information
Thank you for your response! cordially

How to&Answers:

If you want to follow SOLID design principles to have decoupled code, then here is another way of achieving the required results

Lets define a contract which is responsible for returning a user

 interface Extractable 
 {
    public function user($db=null, $userId=null);
 }

Lets define a User extractor class to get the user from database or session and will return the user to us

 class UserExtractor implements Extractable
    {

      public function user($db=null, $userId=null)
      {
         return $this->retrieve($db,$userId);
      }
      protected function retrieve($db, $userId)
      {

        $db = $db ?? new Database();

        // This logic can further be extracted to its own method to get rid of
        // ugly conditional
         if($userid ) {

           $user = $db->query('SELECT * FROM users INNER JOIN users_info ON users.id = users_info.user_id WHERE users.id = :userid',
              array(
                    "userid" => $userid
               ));

            } else {

                // I believe you have this method defined so you can
                // bring it in this class

                if($this->existValue('session')) {
                    $user = $this->getValue('session');
                }
            }

           return $user;

      }

    }

Now we can define the User class which will depend on contract and will give us the required info

    class Users extends Session 
    {

        protected $extractable;

        // Ok lets work with interface and not the concrete class
        public function __construct(Extractable $extractable) 
        { 
          $this->extractable = $extractable

        }

        public function getId() 
        {
            return (int) $this->extractable->user['id'];
        }

        public function getTokenTimes() 
        {
          return (int) $this->extractable->user['token_times'];
        }
    }

You can now use them as follow;

 $extractedUser = new UserExtractor($db, 5); // whatever the params are

    $user = new Users($extractedUser);

    $user->getId();
    $user->getTokenTimes();

Answer:

Welcome to stackoverflow!

“Improvement” is a really subjective topic. If I understand your code correctly then I would personally decouple the logic a little bit. In your concrete case I would use a Repository which accesses the database and return a Model and which will have your public getters.

class User
{

    private $attributes = [];

    public function __construct(array $attributes)
    {
        $this->attributes = $attributes;
    }

    public function getId()
    {
        return $this->attributes['id'];
    }


    public function getIP() 
    {
        return $this->attributes['last_ip'];
    }


    public function getGender() 
    {
        return $this->attributes['gender'];
    }

}
class UserRepository
{
    private $db;

    public function __construct(Database $db)
    {
        $this->db = $db;
    }

    public function getById($id)
    {
        $result = $this->db->query('SELECT * FROM ... WHERE userid = :userid', ['userid' => $id]);
        return new User($result);
    }

    public function getByToken($token)
    {
        $result = $this->db->query('SELECT * FROM ... WHERE token = :token', ['token' => $token]);
        return new User($result);
    }
}

And finally you could use it like this:

$repository = new UserRepository(new Database());

if (!empty($_COOKIE['session'])) {
    $user = $repository->getByToken($_COOKIE['session']);

} else if ($userid > 0) {
    $user = $repository->getById($userid);

} else {
  // Pseudo exit here. You should handle this accordingly.
  exit('User does not exist / not logged in');
}

echo $user->getId(); 
echo $user->getIP();
echo $user->getGender();