By business model, or business objects, I mean plain old objects like a "User" with all their properties name, adress, ...; in addition to all the user properties let's say each user would have an "AppointmentBook" object, each book has a set of "TimeSlot" objects, etc. The business model has objects with references between them, at least that's how I code a business model in Java. Here comes the question:
所谓业务模型或业务对象,我指的是普通的旧对象,比如具有所有属性名称的“User”,adress…;除了所有的用户属性(假设每个用户都有一个“AppointmentBook”对象)之外,每本书都有一组“TimeSlot”对象,等等。来了一个问题:
To intialize my business objects, in Java, I would
用Java来实现我的业务对象,我愿意。
- fetch all of the data from DB only once during application initialization,
- 在应用程序初始化期间,只从DB中获取一次所有数据,
- map data from my DB to my business objects
- 将数据从DB映射到业务对象
- store in memory (maps) and they would be shared across all the requests.
- 存储在内存(映射)中,它们将在所有请求之间共享。
PHP's Share-Nothing-Architecture is confusing me for proper OO programming: If I use the same logic, I would have to fetch all the objects from DB, for every request (I know I could still cache, but you don't cache all of your DB, it's not a question about caching but rather about the way of programming in PHP and its architecture).
PHP的Share-Nothing-Architecture是困惑我适当的OO编程:如果我使用相同的逻辑,我不得不从DB获取所有对象,为每个请求(我知道我仍然可以缓存,但是你不缓存所有的DB,这不是一个关于缓存的问题而是用PHP编程的方法及其体系结构)。
So let's say that for one HTTP request, I just need the User properties and I don't need to access his appointment book. It would be a pitty to fetch all the data from the DB for all the objects the User makes reference to, as I just need his properties. This means that I will initialize PHP objects from my model with a lot of NULL values (NULL because of the objects contained in User that I won't load) which can later on lead to errors.
假设对于一个HTTP请求,我只需要用户属性,不需要访问他的预约簿。从DB中获取用户所引用的所有对象的所有数据是一件很可惜的事情,因为我只需要他的属性。这意味着我将用很多空值(NULL值,因为用户中包含的对象我不会加载)从我的模型中初始化PHP对象,这些空值会导致错误。
I was wondering how professional PHP developers usually use their business objects? (I'm coming from Java)
我想知道专业的PHP开发人员通常如何使用他们的业务对象?(我来自Java)
UPDATE: It was kind of stupid to say that I would load the whole database into memory during application init in Java. What I rather meant is that, if I need to fetch a specific user, I could just load all of its data and that would be accessible through all the requests.
更新:在Java的应用程序init中,说要将整个数据库加载到内存中,这有点愚蠢。我的意思是,如果我需要获取一个特定的用户,我只需要加载它的所有数据就可以通过所有请求访问它。
3 个解决方案
#1
2
In PHP you do not keep all the data of your domain business model in the memory. Instead you only request from DB ( though cache, if needed ), the data you want.
在PHP中,您不会将域业务模型的所有数据保存在内存中。相反,您只请求DB(如果需要的话,通过缓存)您想要的数据。
Model layer in php should be built from multiple domain object and data mappers ( i assume, that part is not so different from Java ). If you need User
details, then you fetch only that information from database/cache. You most likely will have a separate mapper just for dealing with user(s).
php中的模型层应该由多个域对象和数据映射器构建(我假设这部分与Java没有太大区别)。如果需要用户详细信息,那么只能从数据库/缓存中获取该信息。您很可能只有一个单独的映射器来处理用户。
You display the information about that user, and forget about the query. Next request (when and if it comes) will require different information. Maybe you will want ContactList
for that User
... then you really do not need user itself, only his user_id
. Again, you let you mapper to fetch data into the domain object responsible for handling contact list, and if contact list contains User
instances, then just create them, but leave in "unfetched" state (object knows only own user_id). Fetch them only if you really need to, and only the parts which you will use ins that "view".
您将显示关于该用户的信息,而忘记查询。下一个请求(如果它来了)将需要不同的信息。也许你会想要那个用户的联系人列表……那么实际上不需要user本身,只需要他的user_id。同样,您可以让mapper将数据提取到负责处理联系人列表的域对象中,如果联系人列表包含用户实例,那么只需创建它们,但保留“unfetch”状态(对象只知道自己的user_id)。只有当你真正需要的时候才去取它们,而且只有那些你会用“view”的部分。
P.S. you might have notices, I told that model later should be segmented, but quite often php developers just create single class of each DB table (which implements ActiveRecord) and call it "model". This is a result caused by Ruby on Rails influence on php framework developers, which, IMHO, is one of the worst things that has happened to PHP in past 5 years.
您可能会注意到,我告诉模型稍后应该分段,但是通常php开发人员只创建每个DB表的单个类(实现ActiveRecord),并将其称为“模型”。这是Ruby on Rails对php框架开发人员的影响导致的结果,IMHO是php在过去5年中发生的最糟糕的事情之一。
#2
2
Your Java example implies your storing your entire databases content in memory. If your doing that, what's the point of the database? Why not just create all those object and memdump them for persistence.
Java示例意味着将整个数据库内容存储在内存中。如果这样做,数据库的意义是什么?为什么不创建所有这些对象并memdump它们以实现持久性呢?
If I use the same logic, I would have to fetch all the objects from DB, for every request
如果我使用相同的逻辑,我将不得不为每个请求从DB中获取所有的对象
That's simply madness, you don't need to fetch anything, you create new instances when you need them and destroy them when you no longer need them.
这简直太疯狂了,你不需要取回任何东西,你需要时就创建新的实例,不需要时就销毁它们。
So let's say that for one HTTP request, I just need the User properties and I don't need to access his appointment book.
假设对于一个HTTP请求,我只需要用户属性,不需要访问他的预约簿。
That's easy, redesign your user. Your user needs it's properties and a property called appointmentBook which is simply an array of appointment book ids.
这很简单,重新设计用户。您的用户需要它的属性和一个名为appointment mentbook的属性,它只是一个任命书id数组。
If you actually need those appointments you can fetch them from the database later.
如果您确实需要这些约会,您可以稍后从数据库中获取它们。
This means that I will initialize PHP objects from my model with a lot of NULL values (NULL because of the objects contained in User that I won't load) which can later on lead to errors.
这意味着我将用很多空值(NULL值,因为用户中包含的对象我不会加载)从我的模型中初始化PHP对象,这些空值会导致错误。
Not really, if this is the case your User object is too big. Make it smaller, you should load the entire user. Except of course the user has to be small enough for you to sensible load it.
如果这是你的用户对象太大的情况,那不是真的。使它更小,您应该加载整个用户。当然,用户必须足够小才能合理地加载它。
If you don't want that then you can always create a UserProperties class and let every User have one. When you load the User you load the properties, but you also have an option to create the properties seperately.
如果不需要,那么可以创建UserProperties类,并让每个用户都有一个。当您加载用户时,您将加载属性,但是您还有一个选项来分别创建属性。
#3
1
Even in Java you would not load all data from the database into memory. You can however - as you write - often load more compared to short Transaction Scripts you normally have in PHP.
即使在Java中,也不会将数据库中的所有数据加载到内存中。但是,您可以——正如您编写的那样——经常加载更多与您通常在PHP中使用的短事务脚本相比。
You models should be "clever" then to only load the data from the persistence storage that is needed to perform the requested action. This requires the object to be "clever" enough to lazy-load data probably.
然后,您的模型应该是“聪明的”,只从执行请求操作所需的持久性存储中加载数据。这就要求该对象“足够聪明”,可以延迟加载数据。
This can be achieved with a Domain Model that knows enough about itself and a Data Mapper that knows enough about the storage for example.
这可以通过一个对自身了解足够的域模型和一个对存储了解足够的数据映射器来实现。
There are other patterns as well which might suit your needs depending on the type of application, however a Domain Model together with Data Mapper is quite flexible.
根据应用程序的类型,也有其他模式可以满足您的需求,但是域模型和数据映射器是非常灵活的。
An exemplary data mapper in the PHP world is Doctrine.
PHP世界中一个典型的数据映射器是Doctrine。
#1
2
In PHP you do not keep all the data of your domain business model in the memory. Instead you only request from DB ( though cache, if needed ), the data you want.
在PHP中,您不会将域业务模型的所有数据保存在内存中。相反,您只请求DB(如果需要的话,通过缓存)您想要的数据。
Model layer in php should be built from multiple domain object and data mappers ( i assume, that part is not so different from Java ). If you need User
details, then you fetch only that information from database/cache. You most likely will have a separate mapper just for dealing with user(s).
php中的模型层应该由多个域对象和数据映射器构建(我假设这部分与Java没有太大区别)。如果需要用户详细信息,那么只能从数据库/缓存中获取该信息。您很可能只有一个单独的映射器来处理用户。
You display the information about that user, and forget about the query. Next request (when and if it comes) will require different information. Maybe you will want ContactList
for that User
... then you really do not need user itself, only his user_id
. Again, you let you mapper to fetch data into the domain object responsible for handling contact list, and if contact list contains User
instances, then just create them, but leave in "unfetched" state (object knows only own user_id). Fetch them only if you really need to, and only the parts which you will use ins that "view".
您将显示关于该用户的信息,而忘记查询。下一个请求(如果它来了)将需要不同的信息。也许你会想要那个用户的联系人列表……那么实际上不需要user本身,只需要他的user_id。同样,您可以让mapper将数据提取到负责处理联系人列表的域对象中,如果联系人列表包含用户实例,那么只需创建它们,但保留“unfetch”状态(对象只知道自己的user_id)。只有当你真正需要的时候才去取它们,而且只有那些你会用“view”的部分。
P.S. you might have notices, I told that model later should be segmented, but quite often php developers just create single class of each DB table (which implements ActiveRecord) and call it "model". This is a result caused by Ruby on Rails influence on php framework developers, which, IMHO, is one of the worst things that has happened to PHP in past 5 years.
您可能会注意到,我告诉模型稍后应该分段,但是通常php开发人员只创建每个DB表的单个类(实现ActiveRecord),并将其称为“模型”。这是Ruby on Rails对php框架开发人员的影响导致的结果,IMHO是php在过去5年中发生的最糟糕的事情之一。
#2
2
Your Java example implies your storing your entire databases content in memory. If your doing that, what's the point of the database? Why not just create all those object and memdump them for persistence.
Java示例意味着将整个数据库内容存储在内存中。如果这样做,数据库的意义是什么?为什么不创建所有这些对象并memdump它们以实现持久性呢?
If I use the same logic, I would have to fetch all the objects from DB, for every request
如果我使用相同的逻辑,我将不得不为每个请求从DB中获取所有的对象
That's simply madness, you don't need to fetch anything, you create new instances when you need them and destroy them when you no longer need them.
这简直太疯狂了,你不需要取回任何东西,你需要时就创建新的实例,不需要时就销毁它们。
So let's say that for one HTTP request, I just need the User properties and I don't need to access his appointment book.
假设对于一个HTTP请求,我只需要用户属性,不需要访问他的预约簿。
That's easy, redesign your user. Your user needs it's properties and a property called appointmentBook which is simply an array of appointment book ids.
这很简单,重新设计用户。您的用户需要它的属性和一个名为appointment mentbook的属性,它只是一个任命书id数组。
If you actually need those appointments you can fetch them from the database later.
如果您确实需要这些约会,您可以稍后从数据库中获取它们。
This means that I will initialize PHP objects from my model with a lot of NULL values (NULL because of the objects contained in User that I won't load) which can later on lead to errors.
这意味着我将用很多空值(NULL值,因为用户中包含的对象我不会加载)从我的模型中初始化PHP对象,这些空值会导致错误。
Not really, if this is the case your User object is too big. Make it smaller, you should load the entire user. Except of course the user has to be small enough for you to sensible load it.
如果这是你的用户对象太大的情况,那不是真的。使它更小,您应该加载整个用户。当然,用户必须足够小才能合理地加载它。
If you don't want that then you can always create a UserProperties class and let every User have one. When you load the User you load the properties, but you also have an option to create the properties seperately.
如果不需要,那么可以创建UserProperties类,并让每个用户都有一个。当您加载用户时,您将加载属性,但是您还有一个选项来分别创建属性。
#3
1
Even in Java you would not load all data from the database into memory. You can however - as you write - often load more compared to short Transaction Scripts you normally have in PHP.
即使在Java中,也不会将数据库中的所有数据加载到内存中。但是,您可以——正如您编写的那样——经常加载更多与您通常在PHP中使用的短事务脚本相比。
You models should be "clever" then to only load the data from the persistence storage that is needed to perform the requested action. This requires the object to be "clever" enough to lazy-load data probably.
然后,您的模型应该是“聪明的”,只从执行请求操作所需的持久性存储中加载数据。这就要求该对象“足够聪明”,可以延迟加载数据。
This can be achieved with a Domain Model that knows enough about itself and a Data Mapper that knows enough about the storage for example.
这可以通过一个对自身了解足够的域模型和一个对存储了解足够的数据映射器来实现。
There are other patterns as well which might suit your needs depending on the type of application, however a Domain Model together with Data Mapper is quite flexible.
根据应用程序的类型,也有其他模式可以满足您的需求,但是域模型和数据映射器是非常灵活的。
An exemplary data mapper in the PHP world is Doctrine.
PHP世界中一个典型的数据映射器是Doctrine。