【问题标题】:Looking for a way to handle/approach PHP OOP websites寻找一种处理/接近 PHP OOP 网站的方法
【发布时间】:2014-07-22 11:31:28
【问题描述】:

我对 PHP 或编程一点也不陌生。但最近我正在考虑用 PHP 进行网站编程,以及在 OOP 之前它是多么容易。无论如何,我更喜欢 OOP 而不是旧的程序风格。 我想实现一个网站,但似乎我总是必须使用全局或静态变量。我开始怀疑,没有这些我怎么能做到?

无论如何,我所说的是为网站的每个“组件”设置一个类。 例如,如果它是一个 url 缩短网站,它将是:链接、成员、数据库。

我所说的要复杂得多,至少有 8 个类。 无论如何,我目前的方法如下:

$database = new Database(...);
$links = new Links($db);
$users = new Users($db);

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

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

【问题讨论】:

  • 我觉得这样也行。如果你这样使用它有什么困扰?
  • 如果您不想将它们作为构造函数参数传递,您可以简单地在类 Link 的所需函数中声明一个 User 类型的对象。然后在那里使用 User 对象。
  • 虽然有很多类,假设 8 我需要始终按特定顺序设置它们,例如用户可以进入链接,但之后我想使用让我们说用户中的链接这真的是毁灭性的。 (希望你能理解)
  • 是的,我明白你的意思。我也是这样做的。这也让我很沮丧。但我认为,除了顺序,技术上没什么好担心的。
  • 如果我要创建一个数组并在他内部创建所有这些对象,然后将数组传递给每个对象,这可能吗?

标签: php oop


【解决方案1】:

您应该具有以下组件:

  1. 业务对象,在您的应用中建模和表达一种特定的“事物”:

    class Link { ... }
    class User { ... }
    

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

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

    最少需要的数据是构造函数的一部分。这可确保您的应用程序范围内的数据完整性。它允许你断言当你有一个Link 的实例时,它表示的数据是链接的最小有效数据。

  2. 数据库链接。只有连接到数据库的最基本的东西,仅此而已。一个原始的 PDOmysqli 对象就可以了。

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

    class LinkStorage {
    
        protected $db;
    
        public function __construct(PDO $db) {
            $this->db = $db;
        }
    
    }
    

    这个类有各种各样的方法来从你的数据库中检索东西:

    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']);
    }
    

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

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

那么用法就很简单了:

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

$user  = $userStorage->getById($id);
$links = $linkStorage->getAllFromUser($user);

然后,此类代码将被封装在一个服务类中,该类包含您可以在应用程序中执行的所有可能的“操作”。 registerUser(array $data)getLinksOfUser($id)newLinkFromPostData(array $data)

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

你不应该对此有任何循环依赖,因为职责是分开的。您的个人依赖关系可能仍然有些复杂。如果实例化类变得太麻烦,您将需要研究工厂:

$factory = new Factory;
$userStorage = $factory->newUserStorage();

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

【讨论】:

  • 我真的很喜欢这个想法,也很喜欢你为写下这一切所付出的努力。无论如何,当您说“服务”类时,您是什么意思?可以举个例子吗?
  • 我做到了。服务类具有类似LinksService::createFromArrayForUser($userId, array $linkData) 的方法。这是与数据库对话的下一个复杂步骤。业务对象不任何事情,数据对象映射器只在业务对象和数据库之间进行协商,然后服务是接收某种形式的数据并利用它发生某些事情的地方。服务是你的“行动”。它包含诸如注册新用户和发送确认电子邮件之类的代码。这是一个由多个单独步骤组成的复杂操作。
  • 好的,您的方法是否以静态方式访问服务? (就像你刚才说的例子)
  • 不,(实际上)没有任何东西是静态访问的。 :) 那只是一个符号约定。
  • 好的,非常感谢您提供的方法,非常完美。最后一件事,关于使用 XML 文件的注入,你能举个例子吗?
【解决方案2】:

我正在考虑使用 PHP 进行网站编程以及它是多么容易 在 OOP 之前

那么,坚持程序。如果以程序或功能方式编写一个编写良好的网站更容易,那么与面向对象的方式相反。坚持你习惯的。 OO 并不比功能更好。这只是一种不同的方法。

php 中的 public void main()

在 Java 语言中,我们编写的每个软件都有一个入口点。 public void main() 方法。此方法启动整个应用程序并传入启动时提供的参数。它也是应用程序中唯一的退出点。应用程序以此方法结束(除非它崩溃)。

在 php 中,没有单一的入口点。我们有一堆文件运行一些脚本来做更多的事情,然后在某个地方,另一个脚本决定返回东西并 die();

依赖注入以及 IoC 库如何提供帮助

当使用依赖注入时,在创建对象和传递一个类的正确实例时,它变成了一个真正的痛苦。我们开始用丑陋的解决方案来解决这个问题:单例、全局、静态......让我们的软件越来越紧密地耦合,越来越难维护。

控制反转在这里可以提供帮助。 webz 上有一些非常棒的articles

【讨论】:

  • PHP 确实只有一个入口点:您执行的文件中的第一行。从那里开始,它只是包含和自动加载,与 Java 并没有太大区别。
  • 它实际上是用户询问的文件的第一行(除非您使用 mod_Rewrite 或 ... 重写所有文件)。在 Java 中,您不能只从所需文件的开头开始
  • 我的主要编程语言是Java,这就是我想坚持OOP的原因,我喜欢数据结构。无论如何,谢谢你的文章。
  • 如果您只是公开公开任意库文件,那不是 PHP 的错。 :)“用户”不应该简单地请求他们不允许请求的任意文件。是的,PHP 的默认结构使这很容易……但如果我愿意,我也可以简单地“执行”任意 Java 类。 (不是说这通常会做任何有用的事情,但这与 PHP 中的相同。)
  • 您可以允许用户请求不同的文件。没有错。例如 index.php 和 admin.php。不,你不能随便执行任何 Java 类(如果你有代码就可以,但如果给你一个 Java 应用程序就不行)。
【解决方案3】:

您可以在 PHP 中使用自动加载以获得更好的解决方案:

http://php.net/manual/en/language.oop5.autoload.php

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多