PHP5 variable scope and class construction - php

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;
}

Related

Public __construct , retrieve user information class

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();

Codeigniter cannot redeclare class

Not: Its work just one time in loop. Its return this error for other time.
I have a usermodel.php in models. When i use it like
$this->load->model("Usermodel");
$user = $this->Usermodel->quer(1);
it throw "Message: Undefined property: CI_Loader::$Usermodel"
When i use
$this->load->model("Usermodel");
$user = new Usermodel();
it throw "Message: Cannot redeclare class Users"
user class has construct and desturct functions. I call it in Usermodel.php file. And usermodel has construct and destruct functions.
<?php
class User {
public function __construct(){
parent::__construct();
}
private $id;
private $email;
private $name;
private $profilPic;
private $topPic;
private $gender;
private $birthday;
private function setid($id){
$this->id = $id;
}
private function getid(){
return $this->id;
}
private function setemail($email){
$this->email = $email;
}
private function getemail(){
return $this->email;
}
private function setname($name){
$this->name = $name;
}
private function getname(){
return $this->name;
}
private function setprofilPic($profilPic){
$this->profilPic = $profilPic;
}
private function getprofilPic(){
return $this->profilPic;
}
private function settopPic($topPic){
$this->topPic = $topPic;
}
private function gettopPic(){
return $this->topPic;
}
private function setgender($gender){
$this->gender = $gender;
}
private function getgender(){
return $this->gender;
}
private function setbirthday($birthday){
$this->birthday= $birthday;
}
private function getbirhday(){
return $this->birthday;
}
public function __set($name, $value){
$functionname = 'set'.$name;
return $this->$functionname($value);
}
public function __get($name){
$functionname = 'get'.$name;
return $this->$functionname();
}
public function __destruct(){}
}
?>
This is usermodel
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Usermodel extends CI_Model {
public function __construct(){
parent::__construct();
$this->load->view("Users.php");
$this->load->model("Dbmodel");
}
public function quer($id){
$uqcont = array("id" => $id);
$uiqcont = array("userID", $id);
$uq = $this->Dbmodel->control("user", $uqcont);
$uiq = $this->Dbmodel->control("userinfo", $uiqcont, $limit=1, 'userID');
$user = new Users();
if($uq->num_rows()==1){
$uq = $uq->result();
$user->id=$id;
$user->name=$uq[0]->name;
$user->email=$uq[0]->email;
$user->profilPic="girlprofil.png";
$user->topPic="arka.jpg";
}
if($uiq->num_rows()==1){
$uiq=$uiq->result();
if($uiq[0]->profilPic){
$user->profilPic = $uiq[0]->profilPic;
}
if($uiq[0]->topPic){
$user->topPic = $uiq[0]->topPic;
}
}
return $user;
}
public function __destruct(){}
}
?>
This is a part of my view.php
foreach($query->result() as $row){
$cont = array("id" => $row->userID);
$query = $this->Dbmodel->control("user", $cont);
$this->load->model("Usermodel");
$user = new Usermodel();
$user = $user->quer($row->userID);
$date = new datetime($row->date);
$date = $date->format("d.m.Y H:i:s");
//$query = $query->result();
//foreach($query as $qur){
echo '$user->name.'<br>'.$row->comment;
//}
//unset($user);
}
Please look to my error and help me to solve it.
the class User is being declared more than once, probably in the loop you were referring to.
is this line in the loop?
$this->load->model("Usermodel");
if so try moving it out of the loop.
The error is due to loading the model several times in the foreach loop. Load it only once then create instances of the class as many times as you wish
$this->load->model("usermodel");
foreach($query->result() as $row){
$cont = array("id" => $row->userID);
$query = $this->Dbmodel->control("user", $cont);
$user = new Usermodel();
$user = $user->quer($row->userID);
$date = new datetime($row->date);
$date = $date->format("d.m.Y H:i:s");
}
Then consider using small caps in your load->model().
I advise loading the data in the controller then passing the data to the view. Let the controller have most of the logic.For example in the controller
$this->load->model('usermodel');
$data['users'] = $this->usermodel->quer($id)->result();
$this->load->view('users_view', $data);
In the view its as simple as
foreach ($users as $user)
{
//logic e.g. echo $user->name;
}
$this->load->model("X") is doing something like following;
Check models directory if X.php exists and if it exists
it creates the class with the given name in our case "X", [ $this->X = new X(); ]
you can also pass the alternative name to the load->model method like
$this->load->model("X","my_x_model"), in that case the loader module will create
$this->my_x_model = new X();
It was just to give some information about "what happens when you trying to load a model"
You're getting an Undefined property because
$this->load->model("usermodel");
has to be in lowercase.
https://www.codeigniter.com/userguide3/general/models.html#loading-a-model
I change this "class Users" to "class users extends CI_Model" and i move "$this->load->model("usermodel") on over of loop. Then the problem is solved. Thank you for help.

Can be create constructor doble in a php class?

im work with php and mysql, sometimes i need instantiate my php class in data access layer for return objects, load list etc... but sometimes I use the class constructor and others do not.
Can i create doble constructor in a class?
example:
class Student {
private $id;
private $name;
private $course;
function __construct() {
}
//get set id and name
function setCourse($course) {
$this->course = $course;
}
function getCourse() {
$this->course = $course;
}
}
class Course {
private $id;
private $description;
function __construct($id) {
this->id = $id;
}
//get set, id, description
}
In my access layer sometime I use the constructor in different ways
for example:
$result = $stmt->fetchAll();
$listStudent = new ArrayObject();
if($result != null) {
foreach($result as $row) {
$student = new Student();
$student->setId($row['id']);
$student->setName($row['name']);
$student->setCourse(new Course($row['idcourse'])); //this works
$listStudent ->append($sol);
}
}
But sometimes I need to use the constructor in another way, for example
$result = $stmt->fetchAll();
$listCourses = new ArrayObject();
if($result != null) {
foreach($result as $row) {
$course = new Course(); //but here not work, becouse Class course receives a id
$course->setId($row['idcourse']);
$course->setDescription($row['description']);
$listCourses->append($sol);
}
}
My english is very bad,
i hope you understand me
Use default arguments:
class Course {
private $id;
private $description;
function __construct($id = 0) {
this->id = $id;
}
// getters and setters for id and description
}
Now, you can use it like that:
$course = new Course(12); // works with argument
or:
$course = new Course(); // works without argument
$course->setId(12);
class Course {
private $id;
private $description;
public function __construct() {
// allocate your stuff
}
public static function constructWithID( $id ) {
$instance = new self();
//do your stuffs here
return $instance;
}
call like Course:: constructWithID(..id) when you have to pass id otherwise make object (new Course()).

Dependency Injection and passing arguments

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.

PHP - Using classes to fetch user info

Assume the connection to the database and all references to tables and cells is correct... how could I get something like this working?
class User
{
private $_display;
private $_email;
public function __construct($username)
{
$fetch_user = mysql_query("SELECT * FROM `registered_users` WHERE `user_name`='$username'");
$fetch_user = mysql_fetch_array($fetch_user);
$this->_display = $fetch_user['user_display'];
$this->_email = $fetch_user['user_email'];
}
}
$person1 = new User('username');
echo "Information: " . print_r($person1, TRUE);
the problem is it returns nothing. Doesn't thrown an error or anything when debugged. Is it viable method though? :S
Here is roughly what I would do:
<?php
class User{
private $username;
private $data;
public function __construct($username){
$this->username = $username;
if($this->valid_username()){
$this->load();
}
}
private function load(){
// Let's pretend you have a global $db object.
global $db;
$this->data = $db->query('SELECT * FROM registered_users WHERE user_name=:username', array(':username'=>$this->username))->execute()->fetchAll();
}
public function save(){
// Save $this->data here.
}
/**
* PHP Magic Getter
*/
public function __get($var){
return $this->data[$var];
}
/**
* PHP Magic Setter
*/
public function __set($var, $val){
$this->data[$var] = $val;
}
private function valid_username(){
//check $this->username for validness.
}
// This lets you use the object as a string.
public function __toString(){
return $this->data['user_name'];
}
}
How to use:
<?php
$user = new User('donutdan');
echo $user->name; //will echo 'dan'
$user->name = 'bob';
$user->save(); // will save 'bob' to the database

Categories