I've been using Symfony for a while and I see that Doctrine, the preferred way to handle MySQL databases, makes use of annotations (see annotations reference). My question is: why do the exist? I find them hard to read and to debug. What is the advantage of such a programming language?
The performance of all three drivers are the same, because they are cached after the first read. There is very little objective advantage, if any, the only one I can think of is with XML you can statically validate your mapping (with an XSD), which is not possible with annotations, or YML, or the "native PHP" implementation.
With that said, some people prefer annotations, because it keeps the mapping configuration closer to the entities, instead of placing them in a separate file. When you have to change the entity, it's easier to change the mapping, because you don't have to look in a separate file. That's all.
I am looking into using Doctrine2 with my Zend Framework setup. I really like the datamapper pattern, mainly because it seperates my domain models with my database.
My question is what is the best practice for using Doctrine and DQL with my controllers?
controllers uses Doctrine
DQL/EntityManager directly for
saving/loading my domain models?
create my own classes in the
datamapper pattern for
saving/loading my domain models, and
then use Doctrine internally in
my own classes?
The pros. for #1 is of course that I don't need to create my own datamapper models, but again, with #2 I can later replace Doctrine (in theory)
What would you do?
Regarding your abstraction question, I'd say it really depends on the lifetime of this project and how portable your code needs to be. If it's a one-off website that will need minimal maintenance, it would probably save you some time to forego the additional abstraction layer and just write Doctrine code in your controllers. However, if you're planning to reuse this code, move it to different platforms, or maintain it for a long period of time, I'd take the time to add that abstraction because it will give you a lot more flexibility.
If you're still researching frameworks, take a look at Kohana. It's basically a lightweight rewrite of CodeIgniter written for PHP5.
I second the advice from pix0r. The additional abstraction is only worth it if it is a larger project with a potentially long lifetime and maybe with many developers on it. This is pretty much the guideline I follow, too, be it in php with doctrine2 or in java with jpa (since doctrine2 heavily resembles jpa).
If you want the additional abstraction, doctrine2 already ships with the possibility to use repositories (repositories are very similar or even equal to DAOs, maybe with a stronger focus on the business terms and logic). There is a base class Doctrine\ORM\EntityRepository. Whenever you call EntityManager#getRepository($entityName) Doctrine will look whether you configured a custom repository class for that entity. If not, it instantiates a Doctrine\ORM\EntityRepository. You can configure a custom repository class for an entity in the metadata, for example in docblock annotations: #Entity(..., repositoryClass="My\Project\Domain\UserRepository"). Such a custom class should inherit from EntityRepository and call the parent constructor appropriately. The base class already contains some basic find* functionality.
Roman
Also consider Symfony in your research. It will let you use ORM(propel/doctrine) or you may write your own data model. You can also bypass the data relationship and use direct SQL if needed.
To address your concern on 1 or 2, I personally go with ORM in my projects and bypass it if need arises. And better yet with symfony, you may switch between doctrine and propel or your own classes if you ever need to.
Pros:
1) faster development. easier to maintain. generally more secure and consistent. easy to switch databases should you ever need to.(from MySQL to Oracle, etc).
2) Faster runtime. Less dependency.
Cons:
1) Slower runtime and larger memory footprint. Dependency on other projects.
2) (reverse the pros for #1)
My thoughts are similar to pix0r's response. However, if your project is small enough that you could use the EntityManager/DQL directly in controllers then Doctrine 2 is possibly overkill for your project and maybe you should consider a smaller/simpler system.
In my experience writing persistence layer logic in the controller has always come back to haunt me in the form of technical debt. This seemingly small decision now will likely cause unavoidable and potentially large scale re-factoring in the future even on small projects. Ideally we would love to be able to copy and paste extremely thin controllers reconfigured with the appropriate models to prevent us from having to repeatedly create CRUD controllers over and over, but to allow also for customization of these controllers. In my opinion this can only be accomplished by being disciplined and keeping the persistence layer abstracted away from our application as much as possible. Since the overhead of doing that especially on a clean room controller is minimal, I can't see any good reason to advice you not to.
I'm thinking of implementing a Domain Driven Design approach (similar to the one described here), but want to integrate it with the Doctrine ORM. Has anyone had any success doing anything like this?
My initial instinct was to use Doctrine as the DAO layer, but it seems a a bit convoluted for Doctrine to map my database fields, and my entity objects map to (essentially) the same set of fields on the Doctrine object.
My original goal was to separate all my DQL/query logic from my domain Entities, but now I'm feeling a little lost in design-pattern land at the moment.
I know Doctrine 2 is supposed to provide a much more friendly approach to DDD techniques, but I'm not sure I want to wait that long. Does what I want to do make sense, or should I find another approach?
Thanks.
Doctrine is, in my opinion, imperfect for DDD because of the lack of a Repository class. Doctrine supports patterns such as Table Data Gateway and Active Record which, whilst good patterns for certain problems, aren't necessarily the best choice for 'classic' DDD. You can, however, work around these deficiencies.
One option is to derive from Doctrine_Table and use that as a poor man's repository. For example, if you have a class called 'BlogPost', you might have a table class 'BlogPostTable', inheriting from Doctrine_Table. You can then add methods such as 'findByCategory' to the BlogPostTable class, keeping such logic separate from your domain objects (which inherit from Doctrine_Record). It's not exactly the same as the patterns advocated by 'pure' DDD, but it's close enough.
Even without the exact same design patterns, you can still use the central insights of DDD. The main one is the Ubiquitous Language, the concept of trying to describe your domain using precise language that is readable by domain experts and developers alike.
I'm building an app in PHP and I'm using the data mapper pattern for my DB access. I was considering using the Observer pattern to have all my mappers observe the entities they create, so that they can automatically save any changes back to the database without me having to parse them back manually.
I was just wondering if this was a good idea, or if it's bad practice etc.?
I'm typically working with a few objects that are linked together in a hierarchy, and at the moment having to parse each object to it's mapper manually, which is fairly tedious, so just trying to come up with a better solution.
Thanks,
Jack
Definitely sounds like a good idea to me. What you're doing is similar to the Unit Of Work pattern intended to keep track of the changes you've made to mapped objects and commit (usually as a single transaction) once you're done.
I believe that projects like Outlet and Repose provide this for you in PHP as well as alleviating some of the mapping pain, but I haven't personally used them.
As an aside, it sounds like your object hierarchies may benefit from being viewed as Aggregates if you wish to go down the Domain Driven Design path and benefit from the clean isolation it brings.
--
Edit: it also looks like eZ Components has a fairly full featured PHP ORM solution, and Doctrine 2.0 is shaping up this way too.
--
Edit 2: I wouldn't look at Propel or Creole for the problem you are discussing. Creole is not an ORM, but more of a DB abstraction layer akin to PDO - and the project is now officially "Dead". Propel uses the ActiveRecord pattern, not the DataMapper pattern, so your domain objects end up with a lot more persistence responsibility and AFAIK it does not include a Unit Of Work facility.
If you are looking into ORM's check out Propel and Creole.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What's your experience with doctrine?
I've never been much of an ORM kind of guy, I mostlymanaged with just some basic db abstraction layer like adodb.
But I understood all the concepts and benifits of it. So when a project came along that needed an ORM I thought that I'd give one of the ORM framework a try.
I've to decide between doctrine and propel so I choose doctrine because I didn't want to handle the phing requirement.
I don't know what I did wrong. I came in with the right mindset. And I am by no means a 'junior' php kiddie. But I've been fighting the system each step of the way. There's a lot of documentation but it all feels a little disorganize. And simple stuff like YAML to db table creation just wouldn;t work and just bork out without even an error or anything. A lot of other stuff works a little funky require just that extra bit of tweaking before working.
Maybe I made some soft of stupid newbie assumption here that once I found out what it is I'll have the aha moment. But now I'm totally hating the system.
Is there maybe some tips anyone can give or maybe point me to a good resource on the subject or some authoritative site/person about this? Or maybe just recommend another ORM framework that 'just works"?
I have mixed feelings. I am a master at SQL only because it is so easy to verify. You can test SELECT statements quickly until you get the results right. And to refactor is a snap.
In Doctorine, or any ORM, there are so many layers of abstraction it almost seems OCD (obsessive/compulsive). In my latest project, in which I tried out Doctrine, I hit several walls. It took me days to figure out a solution for something that I knew I could have written in SQL in a matter of minutes. That is soooo frustrating.
I'm being grumpy. The community for SQL is HUGE. The community/support for Doctrine is minuscule. Sure you could look at the source and try to figure it out ... and those are the issues that take days to figure out.
Bottom line: don't try out Doctrine, or any ORM, without planning in a lot of time for grokking on your own.
I think mtbikemike sums it up perfectly: "It took me days to figure out a solution for something that I knew I could have written in SQL in a matter of minutes." That was also my experience. SAD (Slow Application Development) is guaranteed. Not to mention ugly code and limitations around every corner. Things that should take minutes take days and things that would normally be more complicated and take hours or days are just not doable (or not worth the time). The resulting code is much more verbose and cryptic (because we really need another query language, DQL, to make things even less readable). Strange bugs are all around and most of the time is spent hunting them down and running into limitations and problems. Doctrine (I only used v2.x) is akin to an exercise in futility and has absolutely no benefits. It's by far the most hated component of my current system and really the only one with huge problems. Coming into a new system, I'm always going back and forth from the db to the entity classes trying to figure out which name is proper in different places in the code. A total nightmare.
I don't see a single pro to Doctrine, only cons. I don't know why it exists, and every day I wish it didn't (at least in my projects).
we have been using Propel with Symfony for 2 years and Doctrine with Symfony for more than 1 year. I can say that moving to ORM with MVC framework was the best step we've made. I would recommend sticking with Doctrine eventhough it takes some time to learn how to work with it. In the end you'll find your code more readable and flexible.
If you're searching for some place where to start, I would recommend Symfony Jobeet tutorial http://www.symfony-project.org/jobeet/1_4/Doctrine/en/ (chapters 3, 6 covers the basics) and of course Doctrine documentation.
As I wrote above we have been using Doctrine for some time now. To make our work more comfortable we developed a tool called ORM Designer (www.orm-designer.com) where you can define DB model in a graphical user interface (no more YAML files :-), which aren't btw bad at all). You can find there also some helpful tutorials.
My experiences sound similar to yours. I've only just started using doctrine, and have never used Propel. However I am very disapointed in Doctrine. It's documentation is terrible. Poorly organised, and quite incomplete.
Propel and Doctrine uses PDO. PDO has a lot of open bugs with the Oracle Database. All of them related with CLOB fields. Please keep this in mind before starting a new project if you are working with Oracle. The bugs are open since years ago. Doctrine and PDO will crash working with Oracle and CLOBs
I'm using Doctrine in a medium sized project where I had to work from pre-existing databases I don't own. It gives you alot of built in features, but I have one major complaint.
Since I had to generate my models from the databases and not vice-versa, my models are too close to the database: the fields have very similar names to the database columns, to get objects you have to query in what is essential sql (where do I put that code, and how do I test it?), etc.
In the end I had to write a complex wrapper for doctrine that makes me question if it wouldn't have been easier to just use the old dao/model approach and leave doctrine out of the picture. The jury is still out on that. Good luck!
Using Doctrine 2.5 in 2015. It was seemingly going well. Until I wanted to use two entities (in a JOIN). [it's better now after I got a hang of DQL]
Good:
generating SQL for me
use of Foreign Keys and Referential Integrity
InnoDB generation by default
updates made to SQL with doctrine command line tool
Okay:
being hyper-aware of naming and mapping and how to name and how to map entities to actual tables
The Bad
takes a lot of time - learning custom API of query builder. Or figuring out how to do a simple JOIN, wondering if better techniques are out there.. Simple JOINs seem to require writing custom functions if you want to do object oriented queries.
[update on first impression above] -- I chose to use DQL as it is most similar to SQL
It seems to me that the tool is great in concept but its proper execution desires much of developer's time to get onboard. I am tempted to use it for entity SQL generation but then use PDO for actual Input/Output. Only because I didn't learn yet how to do Foreign Key and Referential Integrity with SQL. But learning those seems to be much easier task than learning Doctrine ins and outs even with simple stuff like a entity equivalent of a JOIN.
Doctrine in Existing Projects
I (am just starting to) use Doctrine to develop new features on an existing project. So instead of adding new mysql table for example for the feature, I have added entities (which created the tables for me using Doctrine schema generation). I reserve not using Doctrine for existing tables until I get to know it better.
If I were to use it on existing tables, I would first ... clean the tables up, which includes:
adding id column which is a primary/surrogate key
using InnoDb/transaction-capable table
map it appropriately to an entity
run Doctrine validate tool (doctrine orm:validate-schema)
This is because Doctrine makes certain assumptions about your tables. And because you are essentially going to drive your tables via code. So your code and your tables have to be in as much as 1:1 agreement as possible. As such, Doctrine is not suitable for just any "free-form" tables in general.
But then, you might be able to, with some care and in some cases, get away with little things like an extra columns not being accounted for in your entities (I do not think that Doctrine checks unless you ask it to). You will have to construct your queries knowing what you are getting away with. i.e. when you request an "entity" as a whole, Doctrine requests all fields of the entity specifically by column name. If your actual schema contains more column names, I don't think Doctrine will mind (It does not, as I have verified by creating an extra column in my schema).
So yes it is possible to use Doctrine but I'd start small and with care. You will most likely have to convert your tables to support transactions and to have the surrogate index (primary key), to start with. For things like Foreign Keys, and Referential Integrity, you'll have to work with Doctrine on polishing your entities and matching them up perfectly. You may have to let Doctrine re-build your schema to use its own index names so that it can use FK and RI properly. You are essentially giving up some control of your tables to Doctrine, so I believe it has to know the schema in its own way (like being able to use its own index names, etc).
A little late for the party, but let me throw my two cents here. I will make connections with Laravel, because that is the framework I use.
Active Record vs. Data Mapping vs. Proper OOP
Laravel and many other frameworks love Active Record. It might be great for simple applications, and it saves you time for trivial DB management. However, from the OOP perspective it is a pure anti-pattern. SoC (Separation of Concerns) just got killed. It creates a coupling between the model attributes and SQL column names. Terrible for extensions and future updates.
As your project growths (and yes, it will!), ActiveRecord will be more and more of pain. Don't even think of updating SQL structure easily. Remember, you have the column names all over your PHP code.
I was hired for a project that aims to be quite big down the road. I saw the limits of ActiveRecord. I sat back for 3 weeks and rewrote everything using a Data Mapper, which separates DB from the layers above.
Now, back to the Data Mapper and why I didn't choose Doctrine.
The main idea of Data Mapper is, that it separates your database from your code. And that is the correct approach from the OOP perspective. SoC rules! I reviewed Doctrine in detail, and I immediately didn't like several aspects.
The mapping. Why in a world would anyone use comments as commands? I consider this to be an extremely bad practise. Why not just use a PHP Class to store the mapping relations?
Yaml or XML for the map. Again, Why?? Why wasting time parsing text files, when a regular PHP Class can be used. Plus, a class can be extended, inhereted, can contain methods, not just data. Etc.
If we have a mapper and a model carrying data, then it should be the mapper storing the model. Methods such as $product->save() ar just not good. Model handles data, it should not care about storing anything to the DB. It is a very tight coupling. If we spend time building a mapper, then why not having $mapper->save($product). By definition, it shall be the mapper knowing how to save the data.
Tools such as Doctrine or Eloquent save time at the beginning, no doubt about it. But here is the tricky question for everyone individually. What is the right compromise between /development time/future updates/price/simplicity/following OOP principles/? In the end, it is up to you to answer and decide properly.
My own DataMapper instead of Doctrine
I ended up developing my own DataMapper and I have already used it for several of my small projects. It works very nicely, easy to extend and reuse. Most of the time we just set up parameters and no new code is required.
Here are the key principles:
Model carries data, similar to Laravel's model. Example variable $model for the following examples.
ModelMap contains a field that maps the attributes of the Model to the columns of the table in the SQL database. ModelMaps knows the table name, id, etc. It knows which attributes should be tranfromed to json, which attributes should be hidden (e.g. deleted_at). This ModelMap contains aliases for columns with the same name (connected tables). Example variable: $modelMap.
ModelDataMapper is a class that accepts Model and ModelMap in the controller and provides the store/getById/deleteById functionalities. You simply call $modelMapper->store($model) and that's all.
The base DataMapper also handles pagination, search ability, converting arrays to json, it adds time stamps, it checks for soft deletes, etc. For simple usages, the base DataMapper is enough. For anything more complex, it is easy to extend it using inheritance.
Using Doctrine ORM in 2016 with Approx experience ~2 - 2.5 years.
Inherent Inconsistency
SELECT i, p
FROM \Entity\Item i
JOIN i.product p
WHERE ...
Assume entities are Item and Product. They are connected via Item.product_id to Product.id, and Product contains Product.model that we want to display along with Item.
Here is retrieval of same "product.model" from database, using the above SQL but varying SQL parameters:
//SELECT i, p
$ret[0]->getProduct()->getModel();
//SELECT i as item, p as product
$ret[0]['item']->getProduct()->getModel();
//SELECT i as item, p.model as model
$ret[0]['model'];
Point I am making is this:
Output ResultSet structure can change drastically depending on how you write your DQL/ORM SELECT statement.
From array of objects to array of associative array of objects, to array of associative array, depending on how you want to SELECT. Imagine you have to make a change to your SQL, then imagine having to go back to your code and re-do all the code associated with reading data from the result set. Ouch! Ouch! Ouch! Even if it's a few lines of code, you depend on the structure of result set, there is no full decoupling/common standard.
What Doctrine is good at
In some ways it removes dealing with SQL, crafting and maintaining your own tables. It's not perfect. Sometimes it fails and you have to go to MySQL command line and type SQL to adjust things to the point where Doctrine and you are happy, to where Doctrine sees column types as valid and to where you are happy with column types. You don't have to define your own foreign keys or indices, it is done for you auto-magically.
What Doctrine is bad at
Whenever you need to translate any significantly advanced SQL to DQL/ORM, you may struggle. Separately from that, you may also deal with inconsistencies like one above.
Final thoughts
I love Doctrine for creating/modifying tables for me and for converting table data to Objects, and persisting them back, and for using prepared statements and other checks and balances, making my data safer.
I love the feeling of persistent storage being taken care of by Doctrine from within the object oriented interface of PHP. I get that tingly feeling that I can think of my data as being part of my code, and ORM takes care of the dirty stuff of interacting with the database. Database feels more like a local variable and I have gained an appreciation that if you take care of your data, it will love you back.
I hate Doctrine for its inconsistencies and tough learning curve, and having to look up proprietary syntax for DQL when I know how to write stuff in SQL. SQL knowledge is readily available, DQL does not have that many experts out in the wild, nor an accumulated body of knowledge (compared to SQL) to help you when you get stuck.
I'm not an expert with Doctrine - just started using it myself and I have to admit it is a bit of a mixed experience. It does a lot for you, but it's not always immediately obvious how to tell it to do this or that.
For example when trying to use YAML files with the automatic relationship discovery the many-to-many relationship did not translate correctly into the php model definition. No errors as you mention, because it just did not treat it as many-to-many at all.
I would say that you probably need time to get your head around this or that way of doing things and how the elements interact together. And having the time to do things one step at a time would be a good thing and deal with the issues one at a time in a sort of isolation. Trying to do too much at once can be overwhelming and might make it harder to actually find the place something is going wrong.
After some research into the various ORM libraries for PHP, I decided on PHP ActiveRecord (see phpactiverecord). My decision came down to the little-to-no configuration, light-weight nature of the library, and the lack of code generation. Doctrine is simply too powerful for what I need; what PHP ActiveRecord doesn't do I can implement in my wrapper layer. I would suggest taking a moment and examining what your requirements are in an ORM and see if either a simple one like PHP ActiveRecord offers what you need or if a home-rolled active record implementation would be better.
For now I'm using Symfony framework with Doctrine ORM,
how about using Doctrine together with plain queries?
For e.g. from knpuniversity, I can create custom repository method like:
public function countNumberPrintedForCategory(Category $category)
{
$conn = $this->getEntityManager()
->getConnection();
$sql = '
SELECT SUM(fc.numberPrinted) as fortunesPrinted, AVG(fc.numberPrinted) as fortunesAverage, cat.name
FROM fortune_cookie fc
INNER JOIN category cat ON cat.id = fc.category_id
WHERE fc.category_id = :category
';
$stmt = $conn->prepare($sql);
$stmt->execute(array('category' => $category->getId()));
return $stmt->fetch();
... lines 30 - 37
}
I'm just use Doctrine Entities for e.g. creating an processing forms,
When I need more complex query I just make plain statement and take values I need, from this example I can also pass Entity as variable and take it values for making query. I think this solution is easy understand and it takes less time for building forms, passing data for them and writing complex queries is not as hard as writing them with Doctrine.