I'm facing to an issue with Doctrine relation and DDD.
I already searched a lot but I didn't find a suitable answer.
Let's take a simple example:
I have an aggregate Category and an aggregate Product.
I would like to have a ManyToOne relation between Product and Category.
Unfortunately Doctrine makes me add an attribute $category in my Product. But as Vaughn Vernon said, aggregate should reference to other aggregate by his identity, not by the aggregate itself.
Moreover even if I do this, Doctrine overwrites category_id to null if I don't set $category.
My only solution, at this moment, it's to add category_id field in mapping definition and add foreign key by myself.
Is there any other solution ?
I suspect you maybe trying to use the wrong tool for the job. Doctrine 2 is an Object Relational Manager hence it focuses on objects. If you read through the docs you won't find very much on domain driven design.
Given that Doctrine focuses on objects then:
$category = $product->getCategory();
Makes perfect sense. It also maps nicely onto how sql is designed to work.
If you really want a property Product::CategoryId then go ahead and add it. The latest Doctrine even has limited support for value objects.
But if you then want to somehow access the actual category object then you will need to add in your own query somehow. Kind of makes the orm code pretty much useless as you would be handing your own relations. Maybe drop down to pdo or the database access layer.
I have seen a few articles trying to do what you want but they barely manage the simplest cases and are impractical for any kind of production scenarios. Especially since DDD implies complex business logic.
I just would add a property categoryId to Product and that's it.
So I can't navigate from Product to Category directly, but instead I would need the CategoryRepository to fetch the respective category object, if I need it.
I lose the lazy loading convenience, but the aggregates are separated clean and nice.
Related
I have one collection like
"_id": ObjectId("58e33b757100a1e4543f9c5c"),
"job_title": "Internship Job",
"category_list": [
"58de55747100a126748b4567",
"570660fca88ae1415a3c9869",
"5706645ea88ae1117a3c9869"
]
in the above collection category ids are from another collection of ObjectIds
Now i want to map this ids to category collection ids
simply i want category name instead of category ids by using PHP please can one help me out
Several things you can try:
DBRef. You can think it as a shortcut of doing your loop. Only difference is it's done by MongoDB. So it's going to be slow, but convenient.
You can also try $lookup. However it doesn't work for sharded cluster for now.
Data model design in MongoDB is mostly a matter of "balance". You can forget about normalization, just do whatever fits your use case best. In your case, consider embedding category name into your collection would probably make more sense since category name usually doesn't change very frequently. Thus you would mostly benefit from embedding. Rarely suffer from it. Once you do, the worst case is to update all category names.
The above assumption is based on the fact that "category name doesn't change frequently". It might not be real. So analyse base on your fact, how you do CRUD to the data? How frequently do you do them? Then try to find the model works best for your use case.
A good start would be reading the documentation data model design.
Perhaps this is a question with a trivial answer but nevertheless it is driving me nuts for a couple of days so i would like to hear an answer. I'm recently looking up a lot of information related to building a custom datamapper for my own project (and not using an ORM) and read several thread on stackoverflow or other websites.
It seems very convincing to me to have AuthorCollection objects, which are basically only a container of Author instances or BookCollection objects, which hold multiple Book instances. But why would one need a mapper for the single Author object? All fetch criterias i can think of (except the one asking for the object with a specified BookID or AuthorID) will return multiple Book or Author instances hence BookCollection or AuthorCollection instances. So why bother with a mapper for the single objects, if the one for the appropriate collection is more general and you don't have to be sure that your criteria will only return one result?
Thanks in advance for your help.
Short answer
You don't need to bother creating two mappers for Author and AuthorCollection. If your program doesn't need an AuthorMapper and an AuthorCollectionMapper in order to work smoothly and have a clean source, by all means, do what you're most comfortable with.
Note: Choosing this route means you should be extra careful looking out for SRP violations.
Long(er) answer
It all depends on what you're trying to do. For the sake of this post, let's call AuthorMapper an item data mapper and AuthorCollectionMapper a collection data mapper.
Typically, item mappers won't be as sophisticated as their collection mappers. Item mappers will normally only fetch by a primary key and therefore limit the results, making the mapper clean and uncluttered by additional collection-specific things.
One main part of these "collection-specific things" I bring up is conditions1 and how they're implemented into queries. Often within collection mappers you'll probably have more advanced, longer, and tedious queries than what would normally be inside an item data mapper. Though entirely possible to combine your average item data mapper query (SELECT ... WHERE id = :id) with a complicated collection mapper query without using a smelly condition2, it gets more complicated and still bothers the database to execute a lengthy query when all it needed was a simple, generic one.
Additionally, though you pointed out that with an item mapper we really only fetch by a primary key, it usually turns out to be radically simpler using an item mapper for other things. An item mapper's save() and remove() methods can handle (with the right implementation) the job better than attempting to use a collection mapper to save/remove items. And, along with this point, it also becomes apparent that at times throughout using a collection mappers' save() and remove() method, a collection mapper may want to utilize item mapper methods.
In response to your question below, there may be numerous times you may want to set conditions in deleting a collection of rows from the database. For example, you may have a spam flag that, when set, hides the post but self-destructs in thirty days. I'm that case you'd most likely have a condition for the spam flag and one for the time range. Another might be deleting all the comments under an answer thirty days after an answer was deleted. I mention thirty days because it's wise to at least keep this data for a little while in case someone should want their comment or it turns out the row with a spam flag isn't actually spam.
1. Condition here means a property set on the collection instance which the collection mapper's query knows how to handle. If you haven't already, check out #tereško's answer here.
2. This condition is different and refers to the "evil if" people speak of. If you don't understand their nefariousness, I'd suggest watching some Clean Code Talks. This one specifically, but all are great.
first I appologize if the topic may confuse you. I try to explain my question. In an application there are a lot of information which are too small to build an own entity for that. Some examples gender or status.
Is there a recommended way to do that or is it still an entity with two to five value in a table?
What I need is the standard behaviour in forms (selectbox) and show the value by an id.
I would certainly create these as entities!
You may feel it to be overkill, especially when you are just populating select boxes. However, it will be required to create the correct entity relationships such as $user->getGender()->getName() etc I doubt that the Gender options will change but it will be a reusable class for all your other projects.
Remember that Doctrine and other popular ORMs will proxy access to the object so it will be called in a lazy manner.
You could also use a "view helper" of some description that directly queries the database for the values you want and displays the select options accordingly, while you are still using your new entities elsewhere.
I have a site that has different type of products with different specifications for each of them.
I want to be able to use only one products table with a set of columns but because columns are different depending on what type, I have to create multiple products table catering for each type. This I think is time consuming and not really effective way to manage as an ongoing solution.
Is there a good way to manage this type of scenario with the database?
I'm using Cakephp as the framework.
Normalise your data structure: for example, have a product_info table (with FK into the products table) that contains columns key and value to express additional information about each product.
Martin Fowler lists three general approaches.
Single table - Putting all the columns in one table and only using the ones you need (this sounds the closest to what you have)
Class table - All classes have their own table storing data specific to that class (with the same primary key in every relevant table)
Concrete table - The same as above, but only concrete classes have tables, not abstract ones.
Single table is the simplest unless you have a good reason not to - just have all possible fields there, and only use the ones you need in each class. You do have the disadvantage of not being able to enforce NOT NULL; if this matters, either make a custom constraint depending on the type of object, or use option 2 or 3.
I wrote about using the EAV model with cake a little while ago, I think this post might be helpful, but slightly outdated.
http://nuts-and-bolts-of-cakephp.com/2010/07/27/keyvalue-tables-and-how-to-use-them-in-cakephp-1-3/
Also, this could be very helpful for your particular question... Please take a look and study some concepts in Magento (a very popular PHP-based ecommerce framework) makes heavy use of EAV schemas and does a nice job of indexing and flattening the data.
You can certainly gain a lot of interesting perspective on EAV implementation. Whether you love it or not is a different story :)
I'm creating my own CMS and use doctrine for database.
Now I wonder, when I crate Post record, how much work should that record do?
An example:
I have Post -> Categories relation (one to many), should I create separate functions to append categories (to look if Post already has category, etc. ) or should Post do that using accessors / mutators?
What's the best practice?
I think adding methods for the purprose you described is a good idea. Doctrine can sometimes be a bit tricky if you try to override the default actions that happen when accessing the properties.
In general, if there's anything that needs more than the default action, I would recommend having it as a method in the model class.
If you have a specific table with some table-specific actions, such as get every object by some rule, then it's a good idea to add a new method to the table-specific SomeTable class.
Since this is kind of like ActiveRecord, you would have the domain logic in the Doctrine record object.