Laravel 5 extendable entities, how to? - laravel-5

So, let's say I have basic Document with title, author,link_to_file properties and belongsToMany(Document) and hasMany(Document) recursive parent-child relations.
Now I want to extend my Document into, let's say, 3 (or more) types: Letter,Report and Contract, which can have their own unique properties (e.g. Letter has sender and recepient, Contract can have a some fields like valid_until and such) in the addition to inherited ones.
And I want them all to still have title property (inherited from Document) and be able to have child-parent relations with eachother (Contract can be parent of Letter, which can be parent of another Contract, which can be parent of Report... etc.) without hardcoding it.
How do I implement this in laravel?
I mean the extending thing. I'm aware of the fact that I can implement Letter,Report and Contract as separate entities without having an ancestor class/entity.
UPD: If I were doing it from scratch (no frameworks involved), I would've probably ended with following tables (bad design, just for demonstrational purposes):
documents= id:int, extension_type: enum(Letter,Contract,Report), extension_id: int,link:text,author:text,title:text
document_to_document = document_id:int,child_document_id:int
letters = extension_id:int,sender,recepient
contracts = extension_id:int, valid_until,additional_field_5
reports = extension_id:int, additional_field_6

Related

Laravel / Eloquent special relation type based on parsed string attribute

I have developed a system where various classes have attributes consisting of a custom formula. The formula can contain special tokens which refer to different types of object. For example an object of class FruitSalad may have the following attribute;
$contents = "[A12] + [B76]";
In somewhat abstract terms, this means "add apple 12 to banana 76". It can also get significantly more complex than that with as many as 15 or 20 references to other objects involved in one formula.
I have a trait which passes formulae such as this and each time it finds a reference to a model (i.e. "[A12]") it gets it from the database with A::find(12) and adds it to an array of component objects which can be used for other processes later on in the request.
So, in essence, it's a relationship. But instead of a pivot table to describe the relationship, there is a formula on the parent model which can include references to child models.
This is all working. Yay! But it's really inefficient because there are so many tiny queries to get single models as formulae are parsed. One request may quite easily result in hundreds of queries. Oops.
I see two potential options;
1. Get all my apples and bananas from the database at the start of the request and get them from an in-memory store instead of from the database when parsing a formula (is this the repository pattern??).
2. Create a custom relation type (something like hasManyFromFormula) which makes eager loading work so that the parsing becomes much simpler because the relevant apples and bananas would already be loaded into the parent model.
Is there a precedent for this? As for why I am doing it like this, it would a bit tough to explain in brief but suffice to say it is to support a highly configurable data retrieval system which supports as-yet unknown input data configurations.
Help!
Thanks,
Geoff
Am not completely sure if it is the best solution, but in the end I created a new directory class for basic components and then set it up in the app service provider as a singleton. The constructor for the directory class loaded all models of several relevant classes and made them available as collections throughout the app.

Spring REST and real world object graph

I've read this spring-data-rest tutorial https://spring.io/guides/gs/accessing-data-rest/ and I can't see how this can be applied in a real world situation where we don't have just one object, but a graph of objects.
Let's say that we have an Order object which has one-to-many relationship to an Item which is categorized by a Category object. Let's say for the sake of it, that the Category is implemented in a tree-like structure (so it has a parent and some children; i.e. an Electronic category could have 2 children, Computer and TV, the former having another two children, motherboard and keyboards).
And let's say that all these relation are two ways (i.e. an Order can see it's items and an Item can access it's Order)
So when I request an Order object threw my REST service, I'm gone get the Order, all it's Items and each Item will have the whole graph of Category which will be linked to each Item and thus all the orders. So I'm basically returning the whole database.
I do understand that the bidirectional relations is not ideal but even if we suppress the many side of the relationship, when requesting an Order, we would still get
Order-Item-Category-Parent Category-Parent of Parent Category-etc...
So how do you stop a graph of objects being serialized?
Furthermore, you might not want to break the graph at a fix point.
For instance when I request an Order, I might want to see it's items and the category of each item, but definitely not the parent's category.
However, when I want to explicitly display a Category, I would then like to see it's parent. Get it?
Does somebody have some insight for me?
This is where DTOs are a good thing. :)
You build the object structure you need and return it via json. You have full control over this structure, you dont have bidirectional relations and you can just give that back as an object graph from your controller.
Another (good) side effect is that you decouple persistence and view completely. I.e both can evolve independently.
One (negative) side effect can be the increased maintenance. You have, at least, twice the classes to maintain and also the mapping in between. Frameworks like Dozer can help you with the mapping at least.
Another solution can be to implement some addons for Jackson that handle all these cases without the need of DTOs.
I myself created the Antpath filter to dynamically decide which path to filter out in Jackson:
https://github.com/Antibrumm/jackson-antpathfilter
But you will need some more things to consider if you like to work with domain entities directly.
cycle breaker (to avoid bidirectional relations for example)
lazy loading / open session in view pattern as the serialization can go everywhere
hibernate proxies which have method which are not serializable (session)

How do I represent multiple DTOs for a domain object in .NET Web API?

I'm writing a set of REST services and have come upon a problem that I'm sure has an appropriate solution/pattern that's just eluding me.
For instance /api/People/1 will return a serialized representation of PersonDto (which is a pared down representation of the Person domain object created by Entity Framework. I'm using AutoMapper to hydrate PersonDto.
However a second controller (say, /api/Classes/) is going to return different complex object, which may contain one or more Persons, however I want to represent each person in a different way than simply using an existing PersonDto (e.g. I might require more or less fields).
Do I need to define a ClassPersonDto? I'm not sure what the "proper" thing is to do here.
If the model of "person" being passed back in "Classes" is different then the "PersonDto" model, then yes, create a different model. You don't need to, but it's almost always better to keep your classes, including entities, as specific as possible.

Best practice with coding system values

I think this should be an easy one, but haven't found any clear answer, on what would the best practice be.
In an application, we keep current status of an order (open, canceled, shipped, closed ...).
This variables cannot change without code change, but application should meet the following criteria:
status names should be easily displayed in different languages,
application can search via freetext status names (like googling for "open")
status_id should be available to developer via enum
zero headache when adding new statuses
Possible ways we have tackled this so far:
having DB table status with PK(id, language_id) and a separate enum which represents this statuses in an application.
PROS: 1.,2.,3. work out of the box, CONS: 4. needs to run update script on every client installation, SQL selects can become large and cumbersome, when dealing with a lot of code tables
having just enum:
PROS: 3.,4. CONS: 1.,2. is a total nightmare
having enums, which populate database tables on each start of an application:
PROS: 1.,2.,3.,4. work CONS: some overhead on application start, SQL select can become large and cumbersome, when dealing a lot code tables.
What is the most common way of tackling this problem?
Sounds like you summarized it pretty good yourself, and comparing the pros/cons points towards #3. Just one comment when you implement #3 though:
Use a caching mechanism (even a simple HashMap!) plus adding the option to refresh the cache - will ease your work when you'll want to change values (without the need to restart every time!).
I would, and do, use method 3 because it is the best of the lot. You can use resource files to store the translations in and map the enum values to keys in the resource files. Your database can contain the id of the enum for the status.
1.status names should be easily displayed in different languages,
2.application can search via freetext status names (like googling for "open")
These are interfaces layer's concern, you'd better not mix them in you domain model.
I would setup a mapping between status enum and i18n codes. the mapping could be stored in a file (cached in memory) or hardcoded.
for example: if you use dto or view adatper to render your ui.
public class OrderDetailViewAdapter {
private Order order;
public String getStatus() {
return i18nMapper.to(order.getStatus());//use hardcoded switch case or file impl
}
}
Or you could done this before you populating you dtos.
You could use a similar solution for goal2. When user types text, find corresponding enum from mapping and use enum for search.
Anyway, use db tables the less the better.
Personally, I always use dedicated enum class inside domain. Only responsibility of this class is holding status name (OPEN, CANCELED, SHIPPED, ...). Status name is not visible outside codebase. Also, status could be also stored inside database field as string (varchar or similar).
For the purpose of rendering, depending of number of use cases, sometimes I implement formatting inside formatter (e.g. OrderFormatter::formatStatusName(), OrderFormatter::formatAbbreviatedStatusName(), ...). If formatting is needed often I create dedicated class with all formatting styles needed (OrderStatusFormatter::short(), OrderStatusFormatter::abbriviated()...). Of course, internal mapping is needed to map status name to status title, and this is tricky part. But if you want layering you can't avoid mapping.
Translation is not dealt so far. I translate strings inside templates so formatters are clean of that responsibility. To summarize:
enum inside domain model
formatter inside presentation layer
translation inside template
There is no need to create special table for order status translations. Better choice would be to implement generic translation mechanism, seperated from your business code.

Validation on domain entities along with MVP

How do you apply validation in an MVP/domain environment ?
Let me clearify with an example:
Domain entity:
class Customer
{
string Name;
etc.
}
MVP-model
class CustomerModel
{
string Name;
etc.
}
I want to apply validation on my domain entities but the MVP model has it's own model/class
apart from the domain entity, does that mean I have to copy the validation code
to also work on the MVP-model?
One solution I came up with is to drop the MVP-model and use the domain entity as MVP-Model,
but I don't want to set data to the entities that isn't validated yet.
And second problem that rises is that if the entity has notify-events,
other parts of the application will be affected with faulty data.
A third thing with that approach is if the user edits some data and then cancels the edit, how do I revert to the old values ? (The entity might not come from a DB so reloading the entity is't possible in all cases).
Another solution is to make some sort of copy/clone of the entity in question and use the copy as MVP-model, but then it might get troublesome if the entity has a large object graph.
Anyone has some tips about these problems?
Constraining something like the name of a person probably does not rightfully belong in the domain model, unless in the client's company there is actually a rule that they don't do business with customers whose names exceed 96 characters.
String length and the like are not concerns of the domain -- two different applications employing the same model could have different requirements, depending on the UI, persistence constraints, and use cases.
On the one hand, you want to be sure that your model of a person is complete and accurate, but consider the "real world" person you are modeling. There are no rules about length and no logical corollary to "oops, there was a problem trying to give this person a name." A person just has a name, so I'd argue that it is the responsibility of the presenter to validate what the user enters before populating the domain model, because the format of the data is a concern of the application moreso than the domain.
Furthermore, as Udi Dahan explains in his article, Employing the Domain Model Pattern, we use the domain model pattern to encapsulate rules that are subject to change. That a person should not a have a null name is not a requirement that is likely ever to change.
I might consider using Debug.Assert() in the domain entity just for an added layer of protection through integration and/or manual testing, if I was really concerned about a null name sneaking in, but something like length, again, doesn't belong there.
Don't use your domain entities directly -- keep that presentation layer; you're going to need it. You laid out three very real problems with using entities directly (I think Udi Dahan's article touches on this as well).
Your domain model should not acquiesce to the needs of the application, and soon enough your UI is going to need an event or collection filter that you're just going to have to stick into that entity. Let the presentation layer serve as the adapter instead and each layer will be able to maintain its integrity.
Let me be clear that the domain model does not have to be devoid of validation, but the validation that it contains should be domain-specific. For example, when attempting to give someone a pay raise, there may be a requirement that no raise can be awarded within 6 months of the last one so you'd need to validate the effective date of the raise. This is a business rule, is subject to change, and absolutely belongs in the domain model.

Resources