PHP: Accessing Other Classes Properties and Methods

We can access other classes properties (variables) and methods (functions) by injecting the class object in the class that needs it.

4835 views
d

By. Jacob

Edited: 2020-09-06 10:02

PHP article image.

In object orientated PHP (OOP), it may sometimes be desired to access methods from another classes, In this article we will discuss two ways to solve this problem.

Problem: A common beginner problem in OOP is how to access properties (variables) and methods (functions) from other classes without extending them. We actually have a few ways we can deal with this problem. The first, and recommended solution, is to use a technique called Dependency injection (DI), this technique allows us to split up our code and organize it in separate classes, which can then be independently instantiated.

See also: One Big Class vs Multiple Classes

When using DI we will usually be instantiating a class once in our composition root (I.e.: index.php), and then pass it on to subsequent classes that depend on it. Here is an example of how this technique may be used:

$db = new db_client();
$handle_users = new handle_users($db);

In this example, db_client() is an independent class shared by two or more objects. It should not be extended. Instead of extending it, we inject it in the classes that needs database access.

Inside handle_users(), the database object will be available in the __construct() magic method:

class handle_users {
  private $db;

  public function __construct($db){
   $this->db = $db;
  }
   
   public function login_check() {
    //  $db->query('');
    // ...
   }
}

Dependency injection in OOP

A recommended way to make one class depend on another, is by using constructor injection. The solution we discuss in this section will work in most situations. Let us start by imagining an independent class that is shared by multiple objects:

class db_client {
  public $db_link;

  private $db_host = "localhost";
  private $db_user = "Username";
  private $db_pw = "Password";
  private $db_name = "Database";

  public function __construct() {
    $this->db_link = @new mysqli($this->db_host, $this->db_user, $this->db_pw, $this->db_name);
  }
}

Think of the db_client() class as a client to handle all the database stuff. Since it may be shared by many different projects or objects, we should try to make it an independent class.

We should not extend the db_client from the handle_users class, as it would make it too tightly coupled with the users-code, and ruin the portability of the db_client() class. Instead, we should use DI to provide the database object as a dependency for the user handler class upon instantiation.

Now, imagine we also make a handle_users class that deals with everything user related, such as creation of new users, logging in and out, etc. The handle_users class needs the db_client(); class to access the database. To do this, we may pass the db_client as a parameter when initializing the handle_users class:

class handle_users {
  public $db;
    
  public function __construct($db) {
    $this->db = $db; // Make $db available via "$this->db->your_function()"
  }
  public function  {
    $this->db->db_link->query('SELECT * FROM....'); // The db_client object used inside handle_users.
  }
}

For this to work, we will need to first create an instance of the db_client class, and then pass it as a parameter when loading the handle_users class. I.e.:

require $_SERVER["DOCUMENT_ROOT"] . 'db_class.php'; // Handles the Database stuff
require $_SERVER["DOCUMENT_ROOT"] . 'handle_users.php'; // All user related stuff

$db = new db_client();
$handle_users = new handle_users($db);

__construct(); is a magic method that is automatically executed when you create an instance of your class. The $db object automatically becomes available inside the __construct method where we may assign it to a property (variable).

Using singleton in PHP

Another way to access methods in another class, is to use singleton. This makes it possible to use methods without the need to first instantiate the class. The object is instead created inside the class itself.

Note. Using singleton in PHP is not recommended.

A database class in singleton looks like this:

class db_client {
  private static $instance = null;

  // Credentials
  private $db_host = "localhost";
  private $db_user = "Username";
  private $db_pw = "Password";
  private $db_name = "Database";

  public static function getInstance() {
    if (self::$instance == null) {
      self::$instance = new Singleton();
    }
    return self::$instance;
  }
  public function getConnection() {
  	return $this->db_link;
  }

  private function __construct() {
    $this->db_link = @new mysqli($this->db_host, $this->db_user, $this->db_pw, $this->db_name);
  }
}

To perform a database query, simply do like this:

$db = db_client::getInstance();
$mysqli = $db->getConnection(); 
$result = $mysqli->query("SELECT foo FROM .....");

The __construct() method is declared private, which prevents creating an object from outside the class using the new operator. The object is instead created from within the getInstance() method.

Tell us what you think:

Oliver

So DI is a better (= modern) approach over passing other class objects (like $db) via

global $db;

into class methods. Would you agree?

  1. In this Tutorial, it is shown how to redirect all HTTP requests to a index.php file using htaccess or Apache configuration files.
  2. How to create a router in PHP to handle different request types, paths, and request parameters.
  3. Tutorial on how to use proxy servers with cURL and PHP
  4. When using file_get_contents to perform HTTP requests, the server response headers is stored in a reserved variable after each successful request; we can iterate over this when we need to access individual response headers.
  5. How to effectively use variables within strings to insert bits of data where needed.

More in: PHP Tutorials