问题描述
我对PHP或编程并不陌生.但是最近我在考虑用PHP进行网站编程以及在OOP之前它有多容易.无论如何,我比旧的程序风格更喜欢OOP.我想建立一个网站,但似乎总是必须使用全局变量或静态变量.我开始怀疑,如果没有这些,我该怎么办?
I'm not new to PHP or programming at all. But recently I was thinking about website programming in PHP and how easier it was before the OOP. Anyway, I prefer OOP than the old procedural style.I want to implement a website but it seems I always have to use a global or a static variables. And I'm starting to wonder, how can I do it without those?
无论如何,我所说的是为网站的每个组件"都提供一个类.例如,如果它是一个缩短网址的网站,它将是:链接,成员,数据库.
Anyway, what I'm talking about is having a class for each "component" of the website.For example if it was an url shortener website it would be: links, members, database.
我要说的是更复杂的方法,至少有8节课.无论如何,我目前的方法如下:
What I'm talking about is way more complicated, at least 8 classes.Anyway, my current approach is the following:
$database = new Database(...);
$links = new Links($db);
$users = new Users($db);
例如,无论如何,我想通过其ID获得用户发布的所有链接,我需要同时使用链接和用户两个组件.
Anyway, for example I want to get all the links a user posted by its ID, I need to use both links and both users components.
还有其他方法可以做到吗?还有其他方法吗?除了将它们作为构造函数参数传递之外.
Is there any other way I could do this? Any other approach? except passing them as constructor parameters.
推荐答案
您应该具有以下组件:
-
业务对象,它们在您的应用程序中建模并表达一种特定的事物":
Business objects, which model and express one particular "thing" in your app:
class Link { ... }
class User { ... }
这些都不做"任何事情,它们只是用于形式化您的数据结构.这些对象具有用于获取和设置各个属性的getter和setter方法,这些方法也在此处进行了验证:
These don't "do" anything, they're just there to formalise your data structures. These objects have getter and setter methods to get and set individual attributes, which are also validated there:
public function setUrl($url) {
if (!/* validate the URL here*/) {
throw new InvalidArgumentException("$url is not a valid URL");
}
$this->url = $url;
}
最少的必需数据是构造函数的一部分.这样可以确保您在整个应用程序中的数据完整性.它使您可以断言,当您拥有Link
的实例时,它表示的数据是链接的最小有效数据.
Minimum required data is part of the constructor. This ensures your data integrity application-wide. It allows you to assert that when you have an instance of Link
, the data expressed by it is minimum valid data for a link.
数据库链接.仅需连接数据库的最基本的东西,仅此而已.原始的PDO
或mysqli
对象就可以了.
A database link. Only the bare necessary thing to connect to a database, nothing more, nothing less. A raw PDO
or mysqli
object will do just fine.
数据对象映射器,它使用数据库链接并知道如何在数据库中存储业务对象以及如何检索它们:
A data-object mapper, which takes a database link and knows how to store business objects in the database and how to retrieve them:
class LinkStorage {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
}
该类具有如何从数据库中检索内容的所有各种方法:
This class has all the various methods of how to retrieve things from your database:
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']);
}
您可以通过这种方式封装各种不同的查询,例如:
You can have all sorts of different queries encapsulated this way, e.g.:
/**
* 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)
等
This kind of code would then be encapsulated in a service class, which holds all the possible "actions" you can do in your app. registerUser(array $data)
, getLinksOfUser($id)
, newLinkFromPostData(array $data)
etc.
我刚刚描述的基本上是MVC风格的应用程序的 model 部分.其他两个部分是控制器,它们调用服务方法,并查看输出从服务方法检索到的数据的视图.这种方法使职责分离和隔离,并允许您像构建模块一样将更高级别的逻辑和功能放在一起.业务对象是最低的构建基块,它们的结构必须牢固且定义明确,其余的才能正常工作.数据对象映射器只关心将这些对象放入数据库并再次将其取出.然后,服务会以各种复杂的方式将所有这些组合在一起,并使事情发生.
What I've just described is basically the model portion of an MVC-style application. The other two parts would be controllers which call the service methods, and views which output data retrieved from service methods. This approach keeps responsibilities separate and isolated and allows you to put higher-level logic and functionality together like building blocks. Business objects are the lowest building block, their structure needs to be solid and well defined for the rest to work. Data-object mappers just concern themselves with putting those objects into the database and getting them back out again. Services then put all this together in various complex ways and make things happen.
您不应该对此具有任何循环依赖关系,因为职责是完全分开的.您的个人依存关系可能仍然有些复杂.如果过于繁琐而无法实例化类,则需要研究工厂:
You shouldn't have any cyclic dependencies with this, as responsibilities are well separated. Your individual dependencies may still be somewhat complex. If it becomes too cumbersome to instantiate classes, you'll want to look into Factories:
$factory = new Factory;
$userStorage = $factory->newUserStorage();
所有实例化的复杂性都封装在该工厂中.进一步的步骤是依赖项注入容器,您可以在一个XML文件中对其进行配置,以指定哪个类取决于哪个类,然后DI容器将为您解决这个问题.
All the complexity of instantiation is encapsulated in this factory. One step further are dependency injection containers, who you can configure in, for example, an XML file to specify which class depends on what, and then the DI container will take care of it for you.
这篇关于寻找一种处理/接近PHP OOP网站的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!