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
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();
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();
Related
I apologize for not framing the question title correctly.
I am working on skeleton Application of zf3 to implement acl.I couldn't figure how to retrieve the row of corresponding email address.I have two controllers AlbumController.php and LoginController.php
AlbumController.php
private $table;
public function __construct(AlbumTable $table)
{
$this->table = $table;
}
public function deleteAction()
{
$user_session=new Container('user');
if(isset($user_session->email))
{
$row=$this->loginTable->getRow($user_session->email);//*Here is the problem*
if($row['role']=='admin')
{
$acl=new Acl();
if($acl->isAllowed('admin','AlbumController','delete'))
{
$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('album');
}
$request = $this->getRequest();
if ($request->isPost()) {
$del = $request->getPost('del', 'No');
if ($del == 'Yes') {
$id = (int) $request->getPost('id');
$this->table->deleteAlbum($id);
}
return $this->redirect()->toRoute('album');
}
return [
'id' => $id,
'album' => $this->table->getAlbum($id),
];
}
}
return $this->redirect()->toRoute('login');
}
}
LoginController.php
public $user_session;
public $loginTable;
public function __construct(LoginTable $loginTable)
{
$this->loginTable = $loginTable;
}
I am calling getRow() method of LoginTable.php present in Model
LoginTable.php. But it is throwing an error Call to a member function getRow() on a non-object
LoginTable.php
class LoginTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function getRow($mail)
{
$email = $mail;
$rowset = $this->tableGateway->select(array('email' => $email));
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not find row $email");
}
return $row;
}
You are calling $this->loginTable->getRow() in your AlbumController class, but you didn't define loginTable in this controller. You did it in your LoginController class, but this is not the same objects.
Inject a LoginTable instance in your AlbumController:
AlbumController.php
....
private $albumTable;
private $loginTable;
public function __construct(AlbumTable $albumTable, LoginTable $loginTable)
{
$this->albumTable= $albumTable;
$this->loginTable= $loginTable;
}
....
AlbumControllerFactory.php (adapt to your code):
class AlbumControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new AlbumController(
$container->get(AlbumTable::class),
$container->get(LoginTable::class)
);
}
}
I am in the process of building an object-oriented forms system. I am putting together a User class which contains about eight functions. Each function contains a MySQL query for which an object of the Query class must be instantiated.
Is there any way to keep from having to declare a new object every single time? It occurs to me that might bog down the server at some point.
The role of the User class is to extract information about the user from the database (name, email, etc). That data is then used throughout the system including to authenticate roles. Here is the User class:
class User{
protected $user_id;
protected $session_hash;
protected $user_username;
protected $user_email;
protected $user_role_id;
protected $user_role_name;
protected $user_first_name;
protected $user_last_name;
public function __construct($user_id, $session_hash){
$this->user_id = $user_id;
$this->session_hash = $session_hash;
}
public function __get($name){
return $this->name;
}
public function __set($name, $value){
$this->$name = $value;
}
public function getLoggedUserInfo(){
global $db;
$query = new Query($db->link);
if($user_matches = $query->select("SELECT name, mail FROM ".TABLE_PREFIX.".d7_users WHERE uid = '".$this->user_id."'")){
$this->user_username = $user_matches[0]['name'];
$this->user_email = $user_matches[0]['mail'];
$this->user_role_id = $this->getLoggedUserRoleId($this->user_id);
$this->user_role_name = $this->getLoggedUserRoleName($this->user_role_id);
$this->user_first_name = $this->getLoggedUserFirstName($this->user_id);
$this->user_last_name = $this->getLoggedUserLastName($this->user_id);
$user_information_arr = array(
'user_id' => $this->user_id,
'user_username' => $this->user_username,
'user_first_name' => $this->user_first_name,
'user_last_name' => $this->user_last_name,
'user_email' => $this->user_email,
'user_role_id' => $this->user_role_id,
'user_role_name' => $this->user_role_name,
);
return $user_information_arr;
}
return false;
}
private function getLoggedUserRoleId($user_id){
global $db;
$query = new Query($db->link);
if($role_id_matches = $query->select("SELECT rid FROM ".TABLE_PREFIX.".d7_users_roles WHERE uid= '".$user_id."'")){
$this->user_role_id = $role_id_matches[0]['rid'];
return $this->user_role_id;
}
return false;
}
private function getLoggedUserRoleName($role_id){
global $db;
$query = new Query($db->link);
if($role_name_matches = $query->select("SELECT name FROM ".TABLE_PREFIX.".d7_role WHERE rid = '".$role_id."'")){
return $role_name_matches[0]['name'];
}
return false;
}
private function getLoggedUserFirstName($user_id){
global $db;
$query = new Query($db->link);
if($first_name_matches = $query->select("SELECT field_first_name_value FROM ".TABLE_PREFIX.".d7_field_revision_field_first_name WHERE entity_id='".$user_id."'")){
return $first_name_matches[0]['field_first_name_value'];
}
return false;
}
private function getLoggedUserLastName($user_id){
global $db;
$query = new Query($db->link);
if($last_name_matches = $query->select("SELECT field_last_name_value FROM ".TABLE_PREFIX.".d7_field_revision_field_last_name WHERE entity_id='".$user_id."'")){
return $last_name_matches[0]['field_last_name_value'];
}
return false;
}
}
Pass the query object from an existing instance into the constructor of the User class.
protected $queryObject;
public function __construct($user_id, $session_hash, Query $query = NULL){
$this->user_id = $user_id;
$this->session_hash = $session_hash;
$this->queryObject = $query;
}
I have a question about Dependency Injection in PHP.
I currently have this 3 classes:
Staff.php
<?php
class Staff
{
public function name($id)
{
return 'returning staff with id ' . $id;
}
}
Projects.php
<?php
class Projects
{
..... projects related functions
}
ProjectsManager.php
<?php
class ProjectsManager
{
private $staff = null;
private $projects = null;
public function __construct(Staff $staff, Projects $projects)
{
$this->staff = $staff;
$this->projects = $projects;
}
public function staff()
{
return $this->staff;
}
public function projects()
{
return $this->projects;
}
}
Those classes are instantiated like this:
$staff = new Staff;
$projects = new Projects;
$app = new ProjectsManager($staff, $projects);
echo $app->staff()->name(5);
The above is working, but what I would like to do is something like this:
$employee = $app->staff(5);
echo $employee->name();
echo $employee->position();
echo $employee->email();
How can I handle the dependency to achieve this?
You can simply add the set function in Staff class and call it in ProjectsManager:
<?php
class Staff
{
private $id = null;
public function name()
{
return 'returning staff with id ' . $this->id;
}
public function setId($id)
{
$this->id = $id;
}
}
class Projects
{
//..... projects related functions
}
class ProjectsManager
{
private $staff = null;
private $projects = null;
public function __construct(Staff $staff, Projects $projects)
{
$this->staff = $staff;
$this->projects = $projects;
}
public function staff($id = null)
{
$this->staff->setId($id);
return $this->staff;
}
public function projects($val = null)
{
return $this->projects;
}
}
$staff = new Staff;
$projects = new Projects;
$app = new ProjectsManager($staff, $projects);
$employee = $app->staff(5);
echo $employee->name();
$employee = $app->staff()->name(5);
//$app is the ProjectsManager
//$app->staff() returns it's Staff object
//staff()->name(5) Invokes the Staff object's name function
//Returns 'Returning staff with id 5'
echo $employee->name();
echo $employee->position();
echo $employee->email();
To avoid confusion, I would also suggest prefix some of those functions with get (eg. $app->getStaff()->getFromId(#))
Also, be sure to modify staff()->name(#) to actually return an object and not a string.
I'm having problems with accessing variables from my classes...
class getuser {
public function __construct($id) {
$userquery = "SELECT * FROM users WHERE id = ".$id."";
$userresult = mysql_query($userquery);
$this->user = array();
$idx = 0;
while($user = mysql_fetch_object($userresult)){
$this->user[$idx] = $user;
++$idx;
}
}
}
I'm setting this class in a global 'classes' file, and later on I pass through a user id into the following script:
$u = new getuser($userid);
foreach($u->user as $user){
echo $user->username;
}
I'm hoping that this will give me the name of the user but it's not, where am I going wrong?!
Thanks
please define your users member as public in your class like this
class getuser {
public $user = null;
//...
}
in order to access a class property, you have to declare it public or implement getters and setters (second solution is preferable)
class A {
public $foo;
//class methods
}
$a = new A();
$a->foo = 'whatever';
with getters and setters, one per property
class B {
private $foo2;
public function getFoo2() {
return $this->foo2;
}
public function setFoo2($value) {
$this->foo2 = $value;
}
}
$b = new B();
$b->setFoo2('whatever');
echo $b->getFoo2();
in your example:
class getuser {
private $user;
public function __construct($id) {
$userquery = "SELECT * FROM users WHERE id = ".$id."";
$userresult = mysql_query($userquery);
$this->user = array();
$idx = 0;
while($user = mysql_fetch_object($userresult)){
$this->user[$idx] = $user;
++$idx;
}
}
/* returns the property value */
public function getUser() {
return $this->user;
}
/* sets the property value */
public function setUser($value) {
$this->user = $value;
}
}
$u = new getuser($userid);
$users_list = $u->getUser();
foreach($users_list as $user) {
echo $user->username;
}
i've a little problem with the proper design for some simple database models. Lets say i have an User Object with getter/setters and an read method. Read querys the database and sets the properties.
class User extends MyDbBaseClass
{
protected $_id;
protected $_name;
public function setId($id)
{
$this->_id = $id;
}
public function setName($name)
{
$this->_name = $name;
}
public function getId()
{
return (int) $this->_id;
}
public function getName()
{
return (string) $this->_name;
}
public function read($id)
{
// fetch ONE record from Database
$this->_id = $this->setId($sqlResult['id');
$this->_name = $this->setName($sqlResult['name']);
}
public function save()
{
// do some sql stuff to save user to database
}
}
My Problem is, how to return multiple users?
public function getCollection()
{
// fetch all user records from database
forearch ($sqlResult as $result) {
// ... no idea..
}
}
Goal:
// works
$u = new User();
$u->read(1);
echo $u->getName();
// dont know the best way
$u = new User();
$uC = $u->getCollection();
foreach ($uC as $u)
{
echo $u->getName();
}
Any best practices for this?
You could just return an array with users
public function getCollection()
{
// fetch all user records from database
$users = array();
forearch ($sqlResult as $result) {
// ... no idea..
$user = new User();
$user->_name = $result->name; // just an example
$user[] = $users;
}
return $users;
}