简体   繁体   English

从另一个类内部调用PHP类?

[英]Calling PHP class from inside another class?

Im building small MVC, and have some doubts that would like to sort out. 我正在建立小型MVC,并希望解决一些疑问。

I have dispatcher class, and that class needs HTTP Request, HTTP Response and Router classes. 我有调度程序类,该类需要HTTP请求,HTTP响应和路由器类。

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: 现在说我不喜欢这种方法,并且想在Dispatcher类中使用这样的类:

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? 2方法有问题吗? Am I braking some OOP principles? 我是否违反了一些OOP原则? 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. 您应该浏览一下DI是有原因的:依赖关系注入从代码中删除依赖关系,并将其抽象给调用方。 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. 现在,您只是强迫所有人使用MySQL数据库。 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: 但是,如果您使用了DI,则可以抽象出数据库的详细信息,而仅依赖于代表数据库对象的某个类:

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. 第二个示例导致Dispatcher类与其使用的所有3类之间的紧密耦合。 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? PS:确定要使用事件驱动的体系结构吗? Because that is the only context in which i found Dispatcher mentioned. 因为那是我发现Dispatcher提到的唯一上下文

Second example should be called with a Factory suffix, since it creates other objects. 第二个示例应该以Factory后缀调用,因为它创建了其他对象。

In both examples, you end up with a high coupled Dispatcher object ( Dependancy inversion ) 在两个示例中,您最终都将获得一个高耦合的Dispatcher对象( Dependency inversion

Dispatcher should be able to just ask for interfaces or service, that the other objects implement/ are registered to. 分派器应该只能够询问其他对象实现/注册到的接口或服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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