31

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"?

Dennis
  • 7,907
  • 11
  • 65
  • 115
paan
  • 7,054
  • 8
  • 38
  • 44
  • 13
    Holy cow! An ancient, thought-provoking question with thousands of views and a dozen answers that *HASN'T* been closed by the Not Productive Question crowd!! A++! – Theodore R. Smith Sep 03 '14 at 22:48
  • Welp, they did catch up to it eventually, just took them a while. – Dennis Feb 24 '20 at 15:17
  • @TheodoreR.Smith "thought-provoking question" and the title states "what's your experience" both entirely describe what is not desired here based on the Stack Overflow model. I agree it's interesting and nice to rake through, but it's not answerable without subjectivity, and as a result *potentially* poor advice. – James Nov 22 '21 at 06:58
  • It's often un/counter-intuitive to me, overly-complicated, and under-explained. I find that the documentation gives some basic explanation for simple usage, such as specifying vars in function usages without describing what those vars or their viable formats could be, and then leaves me to guess what I can do with it, even though it can be quite powerful and flexible. This means I'm having to trial-and-error or trace vendor code. Documentation shouldn't make me do either of those things, they should be completely optional and supplemental. Even then, it may not describe enough, and here I am. – SteveExdia Apr 04 '23 at 18:53

12 Answers12

48

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.

Michael Gorham
  • 1,234
  • 2
  • 16
  • 24
  • 1
    If you can do a particular thing faster in SQL then you can do so using Doctrine's Native SQL command http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html and keep Doctrine for the simple tasks – Craig Jan 24 '17 at 20:18
  • My experience with Doctrine has been the same over multiple major versions, however, it's been more difficult than most other ORMs I've used. It could have been written intuitively with adequate formatting specifications and examples, but it too often seems to be written as if I'm in the same frame of mind and reference as the writer. – SteveExdia Apr 04 '23 at 18:55
14

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).

lucian303
  • 3,483
  • 1
  • 17
  • 11
  • 1
    is this still your experience with Doctrine in 2015? – Dennis Oct 06 '15 at 18:57
  • pros - automatic conversion from `SELECT` to your `DomainObject`; automatic schema generation, validation, – Dennis Jun 09 '16 at 15:17
  • @Dennis I doubt it. If he still writes for every small task/website by hand - conversion from database to object or even works only with arrays... I really doubt it he does it like this. – idchlife Dec 20 '17 at 07:50
  • @Dennis validation in Doctrine? ò_O I think you are mixing up with Symfony? – Kamafeather Aug 02 '21 at 13:34
  • @Kamafeather, I meant validation in a different way, unofficially. I work a lot with legacy tables, and sometimes make table modifications using bare hand-coded SQL. I then run Doctrine schema tools to see if Doctrine suggests changing anything. If it doesn't, it gives me some validation that I coded things right. Alternatively, I make modifications in the entity and let Doctrine do the SQL work. That in a way skips validation, but at the same time gives me confidence that SQL will be done the right way – Dennis Aug 18 '21 at 16:04
  • Ah yes, this brings up my aggravation with the "magic" word transformations and "shortcuts" Doctrine likes to take with function calls, params, and DQL formatting. It'd be acceptable if it followed a consistent+intuitive formatting, but the different context handling is overly-disparate and unnecessary. Thankfully a smart IDE helps, but it's still hard to spot check, especially using it with Symfony which falls into its own similar context-inconsistency trap. There's just too much magical converting of names... KISS, as Fabien likes to say more than do. – SteveExdia Apr 04 '23 at 18:59
9

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.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • Awesome for orm-designer. I wish it would be free :D – knagode Apr 17 '13 at 10:25
  • 6
    This seems like a salesman answer. "Yes use doctrine2 and then use our own ORM Designer", yep not biased at all. – AntonioCS Feb 04 '15 at 03:41
  • I haven't checked your tool, but I totally think having a graphical user interface for your database doesn't force you to really know what you are doing. An UI is fine for simple tasks, like managing content on a cms. However, for complex things like databases learn the basics and apply them. SQL is so pure, easy and straightforward. Why using a middleware? It will at some point be less good than the original in one of the following points: documentation, features, speed, community. – agoldev Mar 23 '18 at 19:07
6

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.

Amandasaurus
  • 58,203
  • 71
  • 188
  • 248
  • 1
    Amen, The docs make me want to gouge my eyes out. And Freenode IRC community is not very helpful. I've found, inheriting projects that use Doctrine, it can be a weapon of mass destruction in the wrong hands. – ficuscr Oct 04 '13 at 16:30
6

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

antback
  • 61
  • 1
  • 2
5

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!

  • We have an existing database and some of us want to use doctrine in 2020 on mysql 5.6 and windows. What is your verdict today? – surfmuggle Feb 18 '20 at 05:07
5

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).

Dennis
  • 7,907
  • 11
  • 65
  • 115
  • Are you only using it to build new projects? I mean using Doctrine to create the database in the first place. I'm asking because actually I'm looking for opinions on using Doctrine on existing ("hand-made") databases that are not necessarily well-formed (tables without primary key, big tables that should be two tables actually, and the like). How suited is Doctrine for such a case? – Foo Bar Oct 07 '15 at 18:34
  • 1
    I've added my reply in answer – Dennis Oct 07 '15 at 19:35
  • Thanks. I'm in a situation where I can not change the tables, sadly (I have to migrate data from one given DB to another given DB, with different schemas). So I think Doctrine is the wrong tool then. And using Doctrine for just the DB connection but doing raw SQL then defeats the purpose of Doctrine. – Foo Bar Oct 09 '15 at 18:16
  • True. Except in place of raw SQL you will be doing raw DQL. (language that deals with entities and not column names) You could also use QueryBuilder to build your queries. But yes, you will run into multiple issues especially if your tables do not support transactions. I can see ability to use Doctrine for transaction-enabled tables where you use DQL or QueryBuilder and various facilities of Doctrine, like parametrized queries, and so on. But you may run into various little troubles along the way at every place in the process, such as inability to control the database in the first place. – Dennis Oct 09 '15 at 19:16
  • 1
    Thanks = +1 for pointing out to `run Doctrine validate tool (doctrine orm:validate-schema)` – surfmuggle Feb 18 '20 at 10:04
  • About the JOIN queries: by default, **Doctrine queries automatically to fetch eventually related entities** from other tables; but it does it lazily, querying only when the Entity object tries to access a property corresponding to a SQL column that contains Foreign Keys for another table (aka Doctrine *Association*). – This of course could be optimized adding a `JOIN` (via SQL or QueryBuilder) to perform only a single query to fetch from multiple tables altogether; but by default Doctrine does additional queries to other tables automatically when needed. – Kamafeather Aug 19 '21 at 07:55
  • [This behaviour can be configured of course](https://stackoverflow.com/questions/26891658/what-is-the-difference-between-fetch-eager-and-fetch-lazy-in-doctrine). – Kamafeather Aug 19 '21 at 07:57
4

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.

Dennis
  • 7,907
  • 11
  • 65
  • 115
  • 1
    sadly I haven't been using Doctrine much in 2017, although it is still in the codebase. Mostly because my benchmarks showed me that MySQLi is *fast* and Doctrine was *slow*. My current codebase is mostly written using some 1200 pure SQL statements and now some 55 Doctrine statements. Doctrine does remove complexity in certain use-cases, like I do not have to keep track of what changed in my entities when I update them, Doctrine takes care of that when I use `flush`. – Dennis Aug 09 '17 at 14:42
  • 1
    I have crafted MySQL access to be like Doctrine so it almost doesn't matter which one I use, since syntax is pretty similar and I can use SQL easily. So I have been using `mysqli` with my own wrapper over it. – Dennis Aug 09 '17 at 14:42
  • 1
    Also most of my SQL has 2 to 6 JOIN clauses, and weird edge cases and I don't wish to deal with those in Doctrine. Doing them in Doctrine is "one more thing to learn and maintain" and it's not an easy one at that. – Dennis Aug 09 '17 at 14:46
  • 2
    mostly avoiding use of Doctrine in 2019/2020, using MySQLi. I still have Doctrine-related code that I use in some repository classes that's still there, but no new Doctrine has been written lately. – Dennis Feb 19 '20 at 16:21
4

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.
Kamafeather
  • 8,663
  • 14
  • 69
  • 99
Peter Matisko
  • 2,113
  • 1
  • 24
  • 47
  • 2
    I like your detailed response from an abstract perspective instead of complaining about one use case. Would you be willing to share your custom data mapper? I'm heavily invested in Doctrine, but I enjoy looking at alternatives and your solution sounds intriguing. – Fodagus Feb 05 '19 at 20:38
  • 1
    @Fodagus Thanks! I wouldn't mind sharing it, but I have been too busy to make it a stand alone package on git. I keep copying it from one project to another, which isn't a good long term solution :) I plan to create a git package somewhen this year. Check my profile and contact me, I can share some ideas with you and maybe some code as well. – Peter Matisko Feb 06 '19 at 18:44
  • 1
    @PeterMatisko any update on your data mapper? Thanks – reformed Jun 26 '19 at 06:09
  • @reformed, I have it as a stand alone package, but without much documentation so far. Contact me by linkedin or email, I can share. I have contacts on my web. – Peter Matisko Jun 26 '19 at 09:13
3

After some research into the various ORM libraries for PHP, I decided on PHP ActiveRecord (see ). 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.

surfmuggle
  • 5,527
  • 7
  • 48
  • 77
3

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.

YiSh
  • 347
  • 1
  • 4
  • 12
0

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.

darjus
  • 417
  • 3
  • 7
  • 21