0

I'm trying to access an object outside of a class. I already have a class called Database which has a series of functions in it.

$database = new Database($host,$user,$pass,$name);

class User {

    function view($username) {
        $user = $database->findFirst('User','username',$username);
    }
}

I cannot work out how to access the $database object and keep getting an error saying Undefined variable.

ablshd
  • 15
  • 4

3 Answers3

1

$database should be a class member. Try this:

$database = new Database($host,$user,$pass,$name);

class User {
    protected $db;
   public function __construct($database) {

        $this->db = $database;
    }
    public function view($username) {

        $user = $db->findFirst('User','username',$username);
    }
}
Codrutz Codrutz
  • 472
  • 5
  • 15
1

You could make use of dependnecy injection - constructor injection, e.g.

class User
{

    /**
     * @var Database
     */
    protected $db;

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

    public function view($username)
    {
        $user = $this->db->findFirst('User', 'username', $username);
    }
}


$database = new Database(/* ... */);
$user = new User($database);

Regarding the question in comment: Yes, this is possible. Let's think about some basic (abstract) class that could be used as a parent for all classes that should share the same basic logic (e.g. connecting to a DB, or at least injecting a DB connection).

Such abstract class could be:

class DBObject
{

    /**
     * @var Database
     */
    protected $db;

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

Then our User class can extend this abstract class in this way:

class User extends DBObject
{

    public function view($username)
    {
        $user = $this->db->findFirst('User', 'username', $username);
    }
}

Keep in mind that though the abstract class can implement __construct() function, it cannot be directly instantiated. Then somewhere in the code You can do the very same as in first example:

$database = new Database(/* ... */);
$user = new User($database);
$post = new Post($database);
shadyyx
  • 15,825
  • 6
  • 60
  • 95
  • Is there any way to do dependency injection to say, a Main class and then extend the User class from that? – ablshd Feb 21 '14 at 13:39
  • I am not sure I understand what You mean... Could you be more specific? – shadyyx Feb 21 '14 at 13:40
  • So for example say I have a user class, a posts class, a pages class etc that need to access the database class. Is there any way to make an "umbrella" class so that I can extend the other classes off of that so they have access to the database instead of constructing the database object in each one seperately? – ablshd Feb 21 '14 at 13:45
  • Thanks for your really quick responses. I've tried as you have explained, but for some reason I am still getting Fatal error: Using $this when not in object context. – ablshd Feb 21 '14 at 14:11
  • I should also point out that error is in regards to $this->db = $db in the DBObject class. – ablshd Feb 21 '14 at 14:24
  • Sorry, I made a mistake... In abstract class when in constructor You have no access to `$this`. I have changed the `abstract class` to just `class`. Also the `$db` property has to be decvlared as `protected`. – shadyyx Feb 21 '14 at 14:30
  • The same fatal error is coming up regarding calling $this->database from the User class. Very strange, as far as I can see everything seems correct. – ablshd Feb 21 '14 at 17:19
0

Simply define it as global variable within the function. Yet the proper way would be to make constructors or extend it with Database class.

 $database = new Database($host,$user,$pass,$name);

    class User {

        function view($username) {
            global $database;
            $user = $database->findFirst('User','username',$username);
        }
    }

P.S. Here is another post where you can see the same situation with this solution.

Community
  • 1
  • 1
richardev
  • 976
  • 1
  • 10
  • 33
  • Keyword `global` was introduced in PHP4 as should also stay only in PHP4. In PHP5 there are is much better OO implemented allowing also better OO approaches... – shadyyx Feb 21 '14 at 10:29
  • And what do you mean by *extend it with Database class*? Can you give some example? – shadyyx Feb 21 '14 at 10:31
  • True. I mentioned that the proper way would be to use constructors or extend class with Database class (or mysqli). I mean **class User extends Database{}** Sorry, english isn't my native language. – richardev Feb 21 '14 at 10:32
  • *class User extends Database* is indeed even bigger misunderstanding of OOP than using `global`... – shadyyx Feb 21 '14 at 10:35
  • As I said, using constructors (OOP way) is the proper way. These are options/examples how to include global $var inside the class. Or add $var that is outside the class. – richardev Feb 21 '14 at 10:37