What's your experience with Doctrine ORM? [clo

2019-03-12 01:29发布

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

12条回答
甜甜的少女心
2楼-- · 2019-03-12 01:53

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

查看更多
老娘就宠你
3楼-- · 2019-03-12 01:54

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 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.
查看更多
兄弟一词,经得起流年.
4楼-- · 2019-03-12 01:54

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.

查看更多
We Are One
5楼-- · 2019-03-12 02:00

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

查看更多
姐就是有狂的资本
6楼-- · 2019-03-12 02:01

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.

查看更多
够拽才男人
7楼-- · 2019-03-12 02:01

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.

查看更多
登录 后发表回答