简体   繁体   中英

Calling PHP class from inside another class?

Im building small MVC, and have some doubts that would like to sort out.

I have dispatcher class, and that class needs HTTP Request, HTTP Response and Router classes.

I could do this using Dependency Injection like:

$dispatcher = new Dispatcher($request, $response, $router);

Now lets say I dont like this approach and would like to use classes inside Dispatcher class like this:

class Dispatcher()
{
    protected $request;
    protected $response;
    protected $router;

    public function __construct()
    {
        $this->request = new Request();
        $this->response = new Response();
        $this->router = new Router();
    }
}

Is there something wrong with 2 approach? Am I braking some OOP principles? Or is it just fine to use it this way?

It's hard to say that there is anything wrong with one approach or the other. It's only wrong if it does not fulfill required specifications.

The reason that the first approach is preferred over the second is because it allows you flexibility on what you can inject. For example:

class Dispatcher {
   private $req;
   public function __construct(IRequest $req) {
      $this->req = $req;
   }
}
interface IRequest {}
class Request implements IRequest {}
class MockRequest implements IRequest {}

//PRODUCTION
new Dispatcher(new Request);
//TESTING
new Dispatcher(new MockRequest);

There's a reason you should use DI that you're glancing over: Dependency injection removes the dependencies from your code and abstracts them to the caller. This makes it easier to unit test your code as well, since the code doesn't inherently require an external dependency to function.

This is best demonstrated in an example. Imagine if your class required a database connection:

class Dispatcher()
{
    protected $db

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

Now, you just forced everyone to use a MySQL database. But, had you used DI, you can abstract the details of the database away, and just rely on some class that represents a database object:

class Dispatcher()
{
    protected $db

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

And then, you define some objects that represent different database connections:

interface Database {
    public function query( $sql);
}

class MySQLDB implements Database {
    public function query( $sql) { // Stuff for MySQL 
    }
}

class OracleDB implements Database {
    public function query( $sql) { // Stuff for Oracle 
    }
}

Now, whether your users do:

$dispatcher = new Dispatcher( new MysqlDB());

Or:

$dispatcher = new Dispatcher( new OracleDB());

It doesn't matter - The same class can be reused for both databases.

The second example cause tight coupling between the Dispatcher class and all the 3 that it uses. If you are looking for a specific law or principle, that is violated by this, it would be open/closed principle .

PS: are you sure taht you are using event-driven architecture? Because that is the only context in which i found Dispatcher mentioned.

Second example should be called with a Factory suffix, since it creates other objects.

In both examples, you end up with a high coupled Dispatcher object ( Dependancy inversion )

Dispatcher should be able to just ask for interfaces or service, that the other objects implement/ are registered to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM