I'm comparing Doctrine 2 and Propel 1.5/1.6, and I'm looking in to some of the patterns they use. Doctrine uses the DataMapper pattern, while Propel uses the ActiveRecord pattern. While I can see that DataMapper is considerably more complicated, I'd assume some design flexibility comes from this complication. So far, the only legitimate reason I've found to use DataMapper over ActiveRecord is that DataMapper is better in terms of the single responsibility principle -- because the database rows are not the actual objects being persisted, but with Propel that doesn't really concern me because it's generated code anyway.
So -- what makes DataMapper more flexible?
I've worked with both, new Propel and Doctrine2. What DataMapper (and I mean Doctrine2) makes adorable is that your domain objects are clean and simple, they don't extend irrelevant classes which add many irrelevant methods to your classes (violating SRP as you said). They're just simple entities with a few properties and a few methods that are a part of your business layer. And that, of course, lets you write unit tests for them and reuse them in the future.
I wouldn't say DataMapper considerably more complicated. It is complicated if you write your own implementation of DataMapper, but Doctrine2 is way easier to use than propel (maybe except for setting it up, we do that only once anyway). It has an entity manager that manipulates any entities. You may have entity repositories for complex queries. And that's it.
And an entity is as simple as:
/**
* Question
*
* #Entity
*/
class Question
{
/**
* #Column(type="string")
*/
private $title;
public function getTitle() { return $this->title; }
public function setTitle($title) { $this->title = $title; }
}
In Propel we would have 6 classes for that entity which would contain a lot of generated and often unused code.
What makes DataMapper more flexible? Simplicity that it provides.
ActiveRecord makes a data type do two things -- own responsibility for persisting data to a database, and own responsibility for storing the data for general calculations. This means that if you want to change the data store to which data is persisted in the future, code which generally doesn't have to care about database behavior is exposed to the change.
DataMapper completely decouples a given database implementation from a set of in-memory working objects, meaning the same internal working data type can be persisted to multiple databases, without modifying code that otherwise uses the working type.
For example, with DataMapper patterns, if tomorrow you want to add XML export for your data, you implement one new data mapper, the "MyDataToXmlDataMapper" or similar, that adds the new persistence format, and no other code has to change. With ActiveRecord adding such functionality requires changing the interface of the working data type.
Related
I've got an entity with a lot of linked properties, when I'm handling a CSV import, I don't want to create $em->getReference() calls for all the linked fields (mainly because i want to keep it as abstract as possible and don't want to hard code all the possible references).
I rather want to do this in the Entity setter method for the given properties. However that would require me to access doctrine from within the Model which in its turn is a bad practice.
Should i access the entity's Metadata and go from there or is there a better approach to this, which I haven't yet mentioned?
Doing it in the setter, really messes up the whole SOA thing. If you care about the code being decoupled and abstract you can use Dependency Inversion.
Let's say you have entity A that has associations to entity B and C, then for getting the references to correct B and C instances from the raw data you get from the CSV, you would define two interfaces e.g: BRepositoryInterface and CRepositoryInterface, they both might contain a single method find($id), but they still have to be distinct. Now make your Doctrine Repositories for the respective entities implement these interfaces and inject them into the service where create entity A.
If you really wanna make some good code, then you should create separate classes implementing each of these interfaces, and then inject your Doctrine Repositories into them, these classes then act as wrappers for those repositories, this way you have a distinct layer between your DataMapper layer and your business logic layer, which gives you the abstraction you want.
This is what I've learned in my recent studies on good code, DDD and Design patterns. It is no where near perfect(not that there is such a thing). Any Ideas/Comments would be appreciated.
Update: In regards to your comment:
One of the main things that good design strives for is "capturing the language of domain experts", (see this source item no.4 for a description of these legendary beings).i.e: What is your code in plain English?
What your code says is basically find the Objects with these given ids from the repositories of the Entities that have an association to A.This looks pretty good since you have no explicit dependencies on what A has associations to.But looking at it closer, you'll see that you do have dependencies on actual B and C Objects and their repositories, since when you provide an id for some Object, you're not just providing an id, but you're also implicitly stating what that object is, otherwise an id would have no meaning other than it's scalar Value.However that approach definitely has it's use cases both in Semantics of the Design, and RAD.But there is still the issue of Law of Demeter, but it can be solved, see below:
Either way I think you should definitely have a factory for A objects that looks something like this.
class AFactory{
protected $br;
protected $cr;
public function __construct(BRepositoryInterface $br, CrepositoryInterface $cr){
$this->br = $br;
$this->cr = $cr;
}
public function create($atr1, $atr2, $bId, $cId){
$b = $this->br->find($bId);
$c = $this->cr->find($cId);
return new A($atr1, $atr2, $bId, $cId);
}
}
Now you can actually create this factory using the design you stated by having another factory for this factory, this will also solve the issue with Law of Demeter.That Factory will have the Entity Manager as it's dependency, it will read A's metadata, and fetch the Repositories of the related objects based on that metadata, and create a new AFactory Instance from those repositories, now if you implement those interfaces (BRepositoryInterface and CRepositoryInterface) in your actual Doctrine Repositories, the AFactory instance will be successfully created.
The last few days, I have extensively read books and web pages about OOP and MVC in PHP, so that I can become a better programmer. I've come upon a little problem in my understanding of MVC:
Where do I put a mysql_query?
Should I put it in the controller and call a method on a model that returns data based on the provided query? Or should I put it in the model itself? Are both of the options I'm providing total garbage?
Materials on the subject of MVC
You could have listed the books you were reading, because most (if not all) php books, which touch on MVC, are wrong.
If you want to become a better developer, i would recommend for you to start with article by Marting Fowler - GUI Architectures. Followed by book from same author - "Patterns of Enterprise Application Architecture". Then the next step would be for you to research SOLID principles and understand how to write code which follows Law of Demeter. This should cover the basics =]
Can I use MVC with PHP ?
Not really. At least not the classical MVC as it was defined for Smalltalk.
Instead in PHP you have 4 other patterns which aim for the same goal: MVC Model2, MVP, MVVM and HMVC. Again, I am too lazy to write about differences one more time, so I'll just link to an old comment of mine.
What is Model ?
First thing you must understand is that Model in MVC is not a class or an object. It is a layer which contains multitude of classes. Basically model layer is all of the layers combined (though, the second layer there should be called "Domain Object Layer", because it contains "Domain Model Objects"). If you care to read quick summary on what is contained in each part of Model layer, you can try reading this old comment (skip to "side note" section).
The image is taken from Service Layer article on Fowler's site.
What does the Controllers do ?
Controller has one major responsibilities in MVC (I'm gonna talk about Model2 implementation here):
Execute commands on structures from model layer (services or domain objects), which change the state of said structures.
It usually have a secondary responsibility: to bind (or otherwise pass) structures from Model layer to the View, but it becomes a questionable practice, if you follow SRP
Where do I put SQL related code ?
The storage and retrieval of information is handled at the Data Source Layer, and is usually implemented as DataMapper (do not confuse with ORMs, which abuse that name).
Here is how a simplified use of it would look like:
$mapper = $this->mapperFactory->build(Model\Mappers\User::class);
$user = $this->entityFactory->build(Model\Entities\User::class);
$user->setId(42);
$mapper->fetch($user);
if ($user->isBanned() && $user->hasBannExpired()){
$user->setStatus(Model\Mappers\User::STATUS_ACTIVE);
}
$mapper->store($user);
As you see, at no point the Domain Object is even aware, that the information from it was stored. And neither it cases about where you put the data. It could be stored in MySQL or PostgreSQL or some noSQL database. Or maybe pushed to remote REST API. Or maybe the mapper was a mock for testing. All you would need to do, to replace the mapper, is provide this method with different factory.
Also, please see these related posts:
understanding MVC Views in PHP
testable Controllers with dependencies
how should services communicate between each other?
MVC for advanced PHP developers
Model and Entity Classes represents the data and the logic of an application, what many calls business logic. Usually, it’s responsible for:
Storing, deleting, updating the application data. Generally it includes the database operations, but implementing the same operations invoking external web services or APIs is not an unusual at all.
encapsulating the application logic. This is the layer that
should implement all the logic of the application
Here is the MVC Sequence Diagram which shows the flow during a http request:
In this case Model is the best place to implement the code realted to access database.
The model contains the domain objects or data structures that represent the application's state. [wikipedia]. So the model would be the place to make the database call.
In the 'classic' (lack of a better word atm) MVC pattern the view would get the current state from the model.
Don't make the mistake by saying that the model is for accessing the database. It's more than just accessing the database.
For one, don't use mysql_query() and family; they're being deprecated, so consider also learning about PDO and/or mysqli.
The model takes care of data handling; it provides an interface to the controller by which it retrieves and/or stores information. So this would be a primary place where database actions take place.
Update
To answer a question asked by the OP in the comments: "one generic model for the whole db or a model for each table/action?"
Models are meant to abstract away individual tables (although there are models that exclusively handle a single table); for instance, instead of asking for all articles and then query the usernames for the authors you would have one function like this:
function getArticles()
{
// query article table and join with user table to get username
}
How many models you will create largely depends on how big the project is and how inter-related the data is. If you can identify independent groups of data, it's likely that you'd create a model for each group; but this is no hard & fast rule.
Data manipulation can be part of the same model, unless you want a clear separation between read-only and write-only models (I wouldn't know of a situation that warrants this, but who knows).
To go even further, your model should not contain the database access code. This belongs to another layer outside the Model/View/Controller: this is called the persistence layer, which can be implemented using an Object-Relational Mapper such as the popular Doctrine 2 for PHP.
This way, you never touch any (my)SQL code. The persistence layer takes care of this for you.
I really advise you to have a look at a Doctrine tutorial, this is a really professional way to create your applications.
Instead of working with raw data loaded from the database, you create objects that hold your data, and the behavior associated with it.
For example, you might have a User class, such as:
class User
{
protected $id;
protected $name;
protected $privileges;
public function setName($name) { ... }
public function getName() { ... }
public function addPrivilege(Privilege $privilege) { ... }
public function getPrivileges() { ... }
}
You controller will only interact with objects:
class UserController
{
public function testAction()
{
// ...
$user = $em->getRepository('User')->find(123); // load User with id 123
$user->setName('John'); // work with your objects,
echo $user->getName(); // and don't worry about the db!
$em->flush(); // persist your changes
}
}
Behind the scenes, the ORM takes care of all the low-level work of issuing a SELECT query, instantiating your object, detecting modifications to your object, and issuing the necessary UPDATE statement!
I need to figure out a best practice for utilizing models efficiently in Zend Framework.
Currently, I have classes extending Zend_Db_Table_Abstract which handle my queries to each class' respective table.
When I need to access say 5 of those tables from a controller, I find myself creating 5 new instances of each specific Zend_Db_Table object. This is really ineffective.
I've thought about implementing a Factory pattern to create new instances (or provide existing static copy) but am not sure. Is this the best way to go about it?
What is the correct way to handle models ensuring speed without consuming excessive resources? Should lazy loading come into play here?
[EDIT]
As an example, I have a class I use to handle getting details about a location from a raw search query and need these objects in order to parse the query:
// Initialize database object
$this->dbLocations = new Model_Locations;
$this->dbStates = new Model_States;
$this->dbZipcodes = new Model_Zipcodes;
$this->dbLookup = new Model_Lookup;
In another class, I may need to access those models again so I repeat the above code. Essentially reinitializing objects that could be static/singleton.
I tend to work at the DbTable like you do. I've found it effective when I need to query multiple tables in a single action to create another layer of model above the dbTable. Similar to a service or domain layer. This way I only have to call a single model but I still have the functionality I need.
Here is a simple example that may eventually interact with 5 DbTable classes and most likely a couple of Row classes as well:
<?php
class Application_Model_TrackInfo
{
protected $_track;
protected $_bidLocation;
protected $_weekend;
protected $_shift;
protected $_station;
public function __construct() {
//assign DbTable models to properties for convience
$this->_track = new Application_Model_DbTable_Track();
}
/**
*
* #param type $trackId
* #return type object
*/
public function getByTrackId($trackId) {
$trackData = $this->_track->fetchRow($trackId);
//getAllInfo() Application_Model_Row_TRack
$result = $trackData->getAllInfo();
//returns std object reflecting data from 3 DbTable classes
return $result;
}
/**
*Get Station from trackid through bidlocationid
*
* #param type $trackId
* #return type object
*/
public function getStation($trackId){
$data = $this->_track->fetchRow($trackId);
//This a Application_Model_Row_Track method
$result= $data->getStationFromBidLocation();
return $result;
}
}
I hope this helps.
[EDIT]
Since I wrote this answer I have learned the benefits of Domain Models and Data Mappers. Wow what a difference in my app. Not a magic bullet, but a huge improvement.
Thanks to
Alejandro Gervasio over at PHPMaster.com
Rob Allen at Akrabat.com
and
Pádraic Brady at Surviving The Deepend
for all their help in understanding this pattern.
You seem to be in a possition where you require efficient data management with features that the current Zend framework does not come with. Zend does not have a built in engine for working with databases of any sort, it simply has a wrapper classes which help you write your queries.
What you need is an object relational model (ORM) which is a must-have in a professional framework. As I understand it, ORM is a framework by itself, it has patterns and strongly defined ways of "doing things", supports lazy loading (it takes the most of it) and optimizes your queries to the fullest. When you use ORM you don't even write SQL, instead you need to change your interpretation of data storage, you need to forget about tables and focus on Objects. In Doctrine for example each type (table) is specified by a Class and each record (row) as a class instance where you have access to different methods and properties. It supports event listeners and crazy cascading rellations.
No more need to extract rows from related tables when you delete records (it is automatic), no more need to write complex and chaotic scripts to ensure filesystem synchronisation, you can migrate to almost any db engine at any time (mysql, postgresql, simplesql..) and more..
I've been using Doctrine 2 in conjunction with Symfony 2 framework and I have to say I wouldn't go back to Zend for anything. Yes, it is complex and heavy, but really the ultimate solution. When you come to a moment when you need to manage hundreds of tables with millions of records total - then you will see the difference.
So, final summation:
ORM is what you need, there are many solutions, I know of two really good: Doctrine 1 or 2 and Propel.
P.S.: ORM is an independant part of your system, so you don't really need to use a specific framework, Zend can be configured to work with Doctrine wonderfully :)
I'm working on a large project at the moment and am just wondering which is best practice, to model entities and sets of entities seperately or in one class?
Currently I am implementing two classes for each entity (for example an 'author' and 'authors' class) where the plural class contains methods like 'fetch authors' (using Zend_Db_Table_Abstract for plural and Zend_Db_Table_Row_Abstract for singular).
However I realised that I've often seen methods like 'fetch/list' functions in a single entity's object, which seems quite neat in terms of the fact that I won't have to have as many files.
I know there are no hard-and-fast rules for data modelling but before I continue too far I'd be interested in learning what the general consensus on best-practice for this is (along with supporting arguments of course!).
Answers [opinions] gratefully received!
Rob Ganly
Personally, I prefer a model called Person to actually represent a single person and a model like PersonCollection to represent a collection of persons. In neither case, would I have methods for fetch/get on these objects. Rather, I would put those methods on a PersonRepository or a PersonMapper class.
That's really my biggest area of discomfort with ActiveRecord as a pattern for modeling. By having methods like find() and save(), it opens the door to methods like getPersonByName(), getPersonsWithMinimumAge(), etc. These methods are great, nothing wrong with them, but I think that semantically, they work better on a mapper or a repository class. Let the Model actually model, leave persistence and retrieval to mappers and repositories.
So, to more directly address your question, I see potentially three classes per "entity type":
Person - actually models a person
PersonCollection - extends some Abstract Collection class, each item of class Person
PersonMapper - persistence and retrieval of Person objects and PersonCollections
Controllers would use the mapper to persist and retrieve models and collections.
It's probably no surprise that I'm drawn to Doctrine2. The EntityManager there functions as a single point of contact for persistence and retrieval. I can then create repositories and services that use the EntityManager for custom functionality. And I can then layer on action helpers or factories or dependency injection containers to make it easy to get/create those repositories and services.
But I know that the standard ActiveRecord approach is quite common, well-understood, and very mainstream. You can get good results using it and can find many developers who immediately understand it and can work well with it.
As in most things, YMMV.
I've been using Zend's MVC structure for a while now, but so far my models have been restricted to just reflecting my individual database tables. I'm not sure where to go from here when it comes to writing models to reflect more complicated structures (eg many to many relational database). Does anyone know of any good resources/tutorials (preferably online, but book recommendations appreciated too) on how to approach designing more complex models?
Sounds like you're ready for another layer of abstraction. Here's a 3-tier system:
Data Layer: actually touches db
Business Logic Layer: just operates on data, interchanges to/from 1) and 3)
Application / Controller Layer: accepts input, asks Business Logic when doing anything, never touches the "unsanitized" Data Layer directly.
Note that this tiered architecture is aside from the rest of your presentation framework. You should still have a template system and your application layer will implement that; the business and data layers are dealing with data only. This technique centralizes business logic and allows you to swap out other layers with as little effort as possible. (Not meaning easy, but just easy-er.)
See here for a bit of information about extending just a little beyond your current approach. And, see here for a bit of strategy about a business logic layer. They don't talk about a separate data layer, but that's still what I am advising.
To elaborate on the net effect of increased code maintainability, with this system then you could actually change out the db (MySQL to Postgre would still be PAINFUL, but possible) and only need to change one layer of code. Furthermore, this technique is how applications such as PHPBB are able to support multiple database engines, but using as much of the same logic and presentation code as possible. It would also allow you to swap out the UI and create another one that interacts with the business objects which implement all business logic, separate from the controller logic behind a view.
Despite MVC is a very spread development pattern on web, when getting to complex structures as you said we inccur in a design problem named impedance.
Impedance is the overhead that appears when you use different capability models. For example, OOP programming is far less restrictive than plain structures used in databases - you can compose and aggregate objects. For doing that on database, you'll need a N:N relation table.
The current solutions in most frameworks is to use the has_many and belongs_to properties in models. That solves he problem, but the overhead shows up (lots of objects, tons of simple queries...).
It could sound crazy for many developers but: rewrite your models.
Do that for make the composition/aggregation work turns easier. As PHP 5.2+ supports some type casting (objects and arrays), you can use that to write models:
<?php
class Photo extends Model {
private $id;
private $src;
private $description;
}
class Employee extends Model {
private $id
private $name;
private $age;
private Photo $photo;
}
$x = new Employee(123);
echo $x->photo->description;
?>