寻找处理/接近PHP OOP网站的方法

Ore*_*ton 5 php oop

我根本不是PHP或编程的新手.但最近我在思考PHP中的网站编程以及在OOP之前它是多么容易.无论如何,我更喜欢OOP而不是旧的程序风格.我想实现一个网站,但似乎我总是要使用全局变量或静态变量.我开始怀疑,没有那些我怎么能这样做?

无论如何,我所说的是为网站的每个"组件"准备一个课程.例如,如果它是一个url shortener网站,它将是:链接,成员,数据库.

我所说的更复杂,至少有8个班级.无论如何,我目前的做法如下:

$database = new Database(...);
$links = new Links($db);
$users = new Users($db);
Run Code Online (Sandbox Code Playgroud)

无论如何,例如,我想获得用户通过其ID发布的所有链接,我需要使用链接和两个用户组件.

有没有其他方法可以做到这一点?还有其他方法吗?除了将它们作为构造函数参数传递

dec*_*eze 7

您应该具有以下组件:

  1. 业务对象,在您的应用中建模并表达一个特定的"事物":

    class Link { ... }
    class User { ... }
    
    Run Code Online (Sandbox Code Playgroud)

    这些不会"做"任何事情,它们只是在那里形式化您的数据结构.这些对象具有getter和setter方法来获取和设置各个属性,这些属性也在那里得到验证:

    public function setUrl($url) {
        if (!/* validate the URL here*/) {
            throw new InvalidArgumentException("$url is not a valid URL");
        }
        $this->url = $url;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    所需的最低数据是构造函数的一部分.这可确保您的数据完整性在整个应用程 它允许您声明当您有一个实例时Link,由它表示的数据是链接的最小有效数据.

  2. 数据库链接.只有连接到数据库的必要的东西,仅此而已.原始PDOmysqli对象会做得很好.

  3. 一个数据对象映射器,它接受数据库链接并知道如何在数据库中存储业务对象以及如何检索它们:

    class LinkStorage {
    
        protected $db;
    
        public function __construct(PDO $db) {
            $this->db = $db;
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)

    该类具有如何从数据库中检索内容的各种方法:

    public function getById($id) {
        $stmt = $this->db->prepare('SELECT ... FROM ... WHERE id = :id');
        $stmt->execute(compact('id'));
    
        if (!$data = $stmt->fetch()) {
            throw new RuntimeException("Record with id $id does not exist");
        }
    
        return new Link($data['url']);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    您可以通过这种方式封装各种不同的查询,例如:

    /**
     * Returns all links by a particular user.
     * @param User $user
     * @return Link[]
     */
    public function getAllFromUser(User $user) {
        ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

用法很简单:

$db          = new PDO(...);
$linkStorage = new LinkStorage($db);
$userStorage = new UserStorage($db);

$user  = $userStorage->getById($id);
$links = $linkStorage->getAllFromUser($user);
Run Code Online (Sandbox Code Playgroud)

然后将这种代码封装在服务类中,该服务类包含您可以在应用程序中执行的所有可能的"操作".registerUser(array $data),getLinksOfUser($id),newLinkFromPostData(array $data)等.

我刚才描述的基本上是MVC风格应用程序的模型部分.另外两个部分是调用服务方法的控制器,以及从服务方法中检索输出数据的视图.这种方法可以将职责分开并隔离,并允许您将更高级别的逻辑和功能放在一起,就像构建块一样.业务对象是最低的构建块,它们的结构需要牢固且定义良好,以便其余的工作.数据对象映射器只关心将这些对象放入数据库并再次将它们取回.然后,服务以各种复杂的方式将所有这些组合在一起并使事情发生.

你不应该对此有任何循环依赖,因为责任是完全分开的.您的个人依赖关系可能仍然有些复杂.如果实例化类变得太麻烦,你会想看看工厂:

$factory = new Factory;
$userStorage = $factory->newUserStorage();
Run Code Online (Sandbox Code Playgroud)

实例化的所有复杂性都封装在这个工厂中.更进一步的是依赖注入容器,您可以在其中配置,例如,XML文件以指定哪个类依赖于什么,然后DI容器将为您处理它.