tags:

views:

133

answers:

6

In this little example below in PHP what would be a good way to be able to create the variables in the user class and then be able to use them on any page where I create a user object?

<?PHP
//user.class.php file
class User
{

    function __construct()
    {
     global $session;
     if($session->get('auto_id') != ''){
      //set user vars on every page load
      $MY_userid = $session->get('auto_id'); //user id number
      $MY_name = $session->get('disp_name');
      $MY_pic_url = $session->get('pic_url');
      $MY_gender = $session->get('gender');
      $MY_user_role = $session->get('user_role');
      $MY_lat = $session->get('lat');
      $MY_long = $session->get('long');
      $MY_firstvisit = $session->get('newregister');
     }else{
      return false;
     }
    }
}
?>



<?PHP
// index.php file
require_once $_SERVER['DOCUMENT_ROOT'].'/classes/user.class.php';

$user = new User();

//how should I go about making the variables set in the user class available on any page where I initiate the user class?
// I know I can't use 
// echo $MY_pic_url;
// 1 way I can think of is to have the class return an array but is there another way?

?>
+3  A: 

Make them public members:

class user
{
  public $first_name;

function __construct()
{
$this->first_name = $_SESSION['first_name'];
}


}

$user = new user();

echo $user->first_name;
Lance Kidwell
Or better, create accessor methods for these (eg. getFirstName).
Adam Byrtek
Yes, that would be better. Interestingly, his $session object in the example seems to be using a magic getter.
Lance Kidwell
Writing $foo->get('baz') is not very magic. Writing $foo->baz, however, could be.
gnud
@Adam Byrtek and others, I am just learning to use classes and this is a great learning method for me trial and error and your guys responses really helps me to learn this, Why would accessor methods be good? They would just be more code to acheive the same result right or is there other benefits? Please share thanks
jasondavis
@gnud: Yeah, I was trying to figure out the word for "a method that get's various things" as opposed to an accessor method.@jasondavis: at the core, they're really about security and keeping specifics out of the hands of outside objects. Generally, you want to have all the members private and accessible by public methods that can determine how and if other objects and code can read or set that objects data. Also, the code that access the objects members doesn't need to know anything about them, like whether they've been set or are concatenated from two other values or have been sanitized, etc
Lance Kidwell
Or.. what fireeyedboy said in his answer - much more thorough and correct explanation.
Lance Kidwell
A: 
<?PHP
//user.class.php file
class User
{

    function __construct()
    {
        var $MY_userid;
        var $MY_name;
        var $MY_pic_url;
        var $MY_gender;
        var $MY_user_role;
        var $MY_lat;
        var $MY_long;
        var $MY_firstvisit;

        global $session;
        if($session->get('auto_id') != ''){
                //set user vars on every page load
                $this->MY_userid = $session->get('auto_id'); //user id number
                $this->MY_name = $session->get('disp_name');
                $this->MY_pic_url = $session->get('pic_url');
                $this->MY_gender = $session->get('gender');
                $this->MY_user_role = $session->get('user_role');
                $this->MY_lat = $session->get('lat');
                $this->MY_long = $session->get('long');
                $this->MY_firstvisit = $session->get('newregister');
        }else{
                return false;
        }
    }
}
?>



<?PHP
// index.php file
require_once $_SERVER['DOCUMENT_ROOT'].'/classes/user.class.php';

$user = new User();
print $user->MY_name;
?>
Dooltaz
'var' is sooooo PHP 4. PHP 5 uses access specifiers by now: public, protected, private.
fireeyedboy
And they're also in an odd place up there.
Lance Kidwell
@Lance: Ah yes, good point, didn't even notice that.
fireeyedboy
A: 

You can also save the user object in the $_SESSION variable after you have created it initially.

Davide Gualano
+1  A: 

Use attributes to store it.

<?PHP
//user.class.php file
class User
{

    public $MY_userid;
    public $MY_name;
    public $MY_pic_url;
    public $MY_gender;
    public $MY_user_role;
    public $MY_lat;
    public $MY_long;
    public $MY_firstvisit;

    function __construct()
    {
        global $session;
        if($session->get('auto_id') != ''){
                //set user vars on every page load
                $this->MY_userid = $session->get('auto_id'); //user id number
                $this->MY_name = $session->get('disp_name');
                $this->MY_pic_url = $session->get('pic_url');
                $this->MY_gender = $session->get('gender');
                $this->MY_user_role = $session->get('user_role');
                $this->MY_lat = $session->get('lat');
                $this->MY_long = $session->get('long');
                $this->MY_firstvisit = $session->get('newregister');
        }else{
                return false;
        }
    }
}
?>

NawaMan
+2  A: 

Sidenote: the constructor has no return value, i.e. return false does not have the effect you probably intended.

Either use public properties or protected properties+accessor methods.
Or store the $session in your object and then "delegate" each query for a property to that $session object.

class User
{
  protected $session;

  function __construct($session)
  {
    $this->session = $session;
  }

  function get($name) {
    if( ''==$this->session->get('auto_id')) {
      throw new Exception('...');
    }
    return $this->session->get($name);
  }
}
$user = new User($session);
echo $user->get('disp_name');

Or use the "magic" __get() method, e.g.

class User
{
  protected static $names = array(
    'auto_id', 'disp_name', 'pic_url', 'gender',
    'user_role', 'lat', 'long', 'newregister'
  );
  protected $properties = array();
  function __construct()
  {
    global $session;
    if($session->get('auto_id') != '') {
      foreach(self::$names as $n) {
        $this->properties[$n] = $session->get($n);
      }
    }
    else {
      throw new Exception('...');
    }
  }

  function __get($name) {
    return isset($this->properties[$name]) ? $this->properties[$name] : null;
  }
}


$user = new User;
echo $user->disp_name;
VolkerK
Thanks I didn't know you could pass in an argument into a class like $user = new User($session); like you would a function
jasondavis
+2  A: 

To elaborate on Lance' answer; if the point of the class is to be nothing more than an container for the data, in stead of doing something with the data you're pretty safe. But a good principal of OOP is to stick to encapsulation. Encapsulation means, amongst other things, that you hide the inner details of your object from the outside and only let the outside access the fields through it's interface methods.

Let's say you don't want the fields in the User object to be altered from the outside, but only accessed, then you'ld be better of with something like the following:

class User
{

    private $_userId;
    // and a bunch of other fields

    public function __construct( $data )
    {
        // do something with the data
    }

    public function getUserId()
    {
        return $this->_userId;
    }
    // and a bunch of other getters to access the data

}

In all honesty, you could use magic methods like __set and __get to simulate what you want and catch any unwanted altering in the __set method.

Furthermore, I wouldn't use the session as a global variable. You should pass the session object as an argument to it's constructor (like I illustrated in the example). This enforces loose coupling. Because now your User objects are tied to the global session object, but with passing it to the constructor any data could be passed in. This makes the class more flexible.

Edit:
Here's an example of how you could pass an object (for instance your session object) to the constructor. One thing to keep in mind is that, the way your session object is designed, it still, somewhat, enforces tight coupling, because it mandates getting properties through the get() method.

class User
{
    public function __construct( $data )
    {
        $this->_id = $data->get( 'id' );
        $this->_firstname = $data->get( 'firstname' );
        // etc
    }
}

// usage
$session = new YourSessionObject();
$user = new User( $session );

You have a few options at hand to propagate loose coupling, and making you User object a little more flexible.

Mandate that the data for you User object is provided as:

distinct arguments

class User
{
    protected $_id;
    protected $_firstname;
    // etc;

    public function __construct( $id, $firstname, /* etc */ )
    {
        $this->_id = $id;
        $this->_firstname = $firstname;
        // etc
    }
}

// usage
$session = new YourSessionObject();
$user = new User( $session->get( 'id' ), $session->get( 'firstname' ), /* etc */ );

array

class User
{
    protected $_fields = array(
        'id' => null,
        'firstname' => null,
        // etc
    );

    // dictate (type hint) that the argument should be an array
    public function __construct( array $data )
    {
        foreach( $data as $field => $value )
        {
            if( array_key_exists( $field, $this->_fields )
            {
                $this->_fields[ $field ] = $value;
            }
        }
    }
}

// usage
$session = new YourSessionObject();
$array = /* fill this array with your session data */; 
$user = new User( $array );

implementing some interface

// objects that implement this interface need to implement the toArray() method
interface Arrayable
{
    public function toArray();
}

class User
{
    protected $_fields = array(
        'id' => null,
        'firstname' => null,
        // etc
    );

    // dictate (type hint) that the argument should implement Arrayable interface
    public function __construct( Arrayable $data )
    {
        // get the data by calling the toArray() method of the $data object
        $data = $data->toArray();
        foreach( $data as $field => $value )
        {
            if( array_key_exists( $field, $this->_fields )
            {
                $this->_fields[ $field ] = $value;
            }
        }
    }
}

class YourSessionObject implements Arrayable
{
    public function toArray()
    {
        /* this method should return an array of it's data */
    }
}

// usage
$session = new YourSessionObject();
$user = new User( $session );

etc

There are a few other options, but this should give you some ideas. Hope this helps.

fireeyedboy
thanks for the tips, as you probably noticed i'm new to using classes, could you possibly suppkly an example of using it where you pass the session into it?
jasondavis
See my additional examples in my edited message. Hopefully this clarifies things a bit more.
fireeyedboy
thanks this helps I am trying to learn more about using classes and this helps a lot to see actual code I am working on instead of some other non relevant examples. I wasn't aware that you could pass in arguments into a class like you can a function, my question about that, is a value is passed in through the class like that, is the value you pass in only available in the construct method or anywhere in the class? thanks for the help
jasondavis
@jasondavis: If your constructor takes an argument and you want to use it elsewhere in your class, just have your constructor store the argument in a private property of your class.
Daniel Pryden
@jasondavis: Like Daniel states, you could store the argument in a property of the class. But keep in mind that, if it's an object that you pass to the constructor (such as your session object) and store in an attribute, this could result in unexpected behaviour. Alterations of the session object outside the User object will result in alterations of the session object in the User object, since it's a reference. This could be considered a violation of the principals of encapsulation, unless you actually intend this behaviour. To circumvent this, you should clone the object in the constructor.
fireeyedboy