tags:

views:

207

answers:

4

I have a class called "Layout" for the layout of the page, another class called "User" for the user.

Every page I create, I instantiate a new Layout.

When a user logs in, there is a new User instantiated.

How do I get an instance of the layout class to know about the instantiated user? I could also save the entire instance of the User in a session variable. I assume that's a bad idea though. What are the best practices for this?

class User
{
  var $userid;
  var $email;
  var $username;

  function User($user)
  {
     $this->userid = $this->getUid($user);
     $this->email = $this->getEmail($user);
     $this->username = $user;
  }
  function getUid($u)
  {
     ...
  }

  function getEmail($u)
  {
     ...
  }
}

class Layout
{

    var $var1;
    var $var2;
    var $var3;

    function Layout()
    {
        //defaults...
    } 


    function function1()
    {
        echo "something";
    }


   function function2()
   {
        echo "some other stuff";
   }

   function function3()
   {
      echo "something else";
   }

}

so in index.php, for example, i would do the following:

include "user.php"
include "layout.php"

$homelayout = new Layout();
$homelayout->function1();
$homelayout->function2();
$homelayout->function3();

now let's say that in login.php someone logged in:

include "layout.php"
include "user.php"

if(userAuthSuccess)
{
    $currentUser = new User($_POST['username']);
}

what is the best way to gain access to $currentUser and it's member variables such as $currentUser->email, etc. from all php files from here on out, as long as the user hasn't logged out?

A: 

"Globalizing" something by putting it in a session variable or cookie for the sole purpose of globalizing it is a very bad habit to get into, and it leads to tightly coupled libraries that rely on an arbitrary variable being set outside the class. Session variables in general are good to stay away from for other reasons, too.

The best way to get a variable into any class is to pass it as an argument. Do you have a method in your Layout class that renders (outputs) it? You may want to add a $data argument to that method that takes an associative array of data usable in the layout.

Daniel
+1  A: 

Since there will be only one User for every request and thus for every run of your program, this would be a case to make "User" a Singleton class as described here:

http://php.net/manual/en/language.oop5.patterns.php

That would provide the one way for other classes to refer to the current user without the chance of accessing the wrong instance since there is only one.

DISCLAIMER: Yes, I know that Singeltons are often used at the wrong places for the wrong purpose and some people tend to blame this problem on the pattern instead of the people who misused it for some smelly code. This however is a perfectly good use case for the Singelton pattern.

Techpriester
i have edited my post to show some code. let's assume i made the User class a singleton class...do I pass the instance of User to each of the other instances of the classes? If not, could you show some code to explain please.
Sev
If you User class is a singleton, you access it's only existing instance with User::singleton(), assuming the method names from the PHP manual page. That method will then always return the exact same instance of User and no other way of accessing it must be allowed.
Techpriester
A: 

I'd personally use a registry class (Singleton) and register the user there for the Layout to access. That way, you only need to pass an instance of the registry to the Layout. The User class is not integral to the Layout's construction - since it should only be concerned with the Layout, so I wouldn't pass that in the constructor.

Another method would be to use a Controller to orchestrate these interactions between Views and Models. Whenever a new Controller is created, buffer it's output. Then, at render time, unbuffer the contents and assign them to properties (or a property array) of the view, which can then render them. You probably don't need an actual Model class to be passed to the View/Layout - just it's output.

sunwukung
A: 

Use a registry pattern. No need to make it a singleton, everyone is throwing that word around.

include "layout.php"
include "user.php"

if(userAuthSuccess)
{
    $data['currentUser'] = new User($_POST['username']);
}

$data['nav'] = new nav('home'); 

$homelayout = new Layout( $data );

Now $homelayout can access $data (which contains all the variables you put into it) via the data array.

Galen
in the case of a User class (where there is only 1 user per session), or a Database class (assuming there is only 1 connection necessary throughout), why would you suggest against a singleton class for both these cases?
Sev
whats the point? are you afraid you'll create more than one user on accident?
Galen
so to use your method, i would need to have a global variable to hold the status of whether the user is logged in or not, correct?
Sev
also, i would need to create a new User from every page
Sev
its one extra line of code. also makes it more readable for other people reading your code.
Galen