According to doctrine documentation am reading, it says concerning using
Entity classes
that all of the fields should be protected or private (not public) and this is the quote.
When creating entity classes, all of the fields should be protected or
private (not public ), with getter and setter methods for each one
(except $id ). The use of mutators allows Doctrine to hook into calls
which manipulate the entities in ways that it could not if you just
directly set the values with entity#field = foo;
While the 6th edition of an advanced PHP book(One of the best selling books on PHP and other programming books out there are being written by this company) I just read says this
In most cases, private properties are strongly preferred over public
ones. However, in the case of entity classes, you should use public
properties. The sole purpose of an entity class is to make some data
available. It’s no good having a class representing an author if you
can’t even read the author’s name!
I understand that the pattern used by doctrine might slightly be different from the book approach but when you see statements like this, you get to wonder which is which. Which of the statement is wrong and which of the statement is right
The entire house should please enlighten me
Related
i want to create a forms with only getter methods in the entity... Since I am working on already existing database which does not require to store or manipulate the data.
Hence I have created Entities for the products with only Getter methods and no Setter method.
However when i create form( like search query with some dropdowns etc) it always looking for set or Add methods. Is there a possibility if i can only use getters to get the data from the database.
And I do not want data to be modified at anytime in the future.
i tried with "read_only" but it still gives an error about setter and addMethod()
http://symfony.com/doc/current/reference/forms/types/form.html#read-only
EDIT:
I want to create a drop down ProductGroupcategory-> productSubcategory -> Product
like this(advance search): http://www.buycarspares.co.uk/
Complete Code:
https://gist.github.com/anonymous/8b2e576e69b1588e4f21
Relationships require add- and get-methods simply because it is about an array or arrayCollection of an object and not about the getters or setters for normal entity properties like strings.
Yes you can though some people might consider the solution to be worse than the problem. You could of course just declare your entity properties to be public. That would avoid not only setters but getters as well. Doctrine 2's lazy loading functionality would not work.
A more advanced approach it to realize that the form component uses a property access object to transfer data to and from your entity. That is where the 'add' and 'set' messages are coming from. Property access objects are also what allows you to use arrays as well as entities. http://symfony.com/doc/current/components/property_access/introduction.html
The form component allows you to plug in your own property access object which means that you can create your own access object which can write directly to private/protected variables using Reflection. This, by the way, is the same technique that Doctrine 2 uses to hydrate your entities using database information.
Of course I can already hear howls of protest of this approach mostly about violating encapsulation. But think about it for a moment before down voting. The form component really is just persisting and retrieving the state of an entity to and from an html document. Exactly what Doctrine 2 does. As long as you don't misuse the technique then there is no violation.
I routinely use this approach to avoid writing endless getters and setters. Seems to work fine in practice.
I've got an entity with a lot of linked properties, when I'm handling a CSV import, I don't want to create $em->getReference() calls for all the linked fields (mainly because i want to keep it as abstract as possible and don't want to hard code all the possible references).
I rather want to do this in the Entity setter method for the given properties. However that would require me to access doctrine from within the Model which in its turn is a bad practice.
Should i access the entity's Metadata and go from there or is there a better approach to this, which I haven't yet mentioned?
Doing it in the setter, really messes up the whole SOA thing. If you care about the code being decoupled and abstract you can use Dependency Inversion.
Let's say you have entity A that has associations to entity B and C, then for getting the references to correct B and C instances from the raw data you get from the CSV, you would define two interfaces e.g: BRepositoryInterface and CRepositoryInterface, they both might contain a single method find($id), but they still have to be distinct. Now make your Doctrine Repositories for the respective entities implement these interfaces and inject them into the service where create entity A.
If you really wanna make some good code, then you should create separate classes implementing each of these interfaces, and then inject your Doctrine Repositories into them, these classes then act as wrappers for those repositories, this way you have a distinct layer between your DataMapper layer and your business logic layer, which gives you the abstraction you want.
This is what I've learned in my recent studies on good code, DDD and Design patterns. It is no where near perfect(not that there is such a thing). Any Ideas/Comments would be appreciated.
Update: In regards to your comment:
One of the main things that good design strives for is "capturing the language of domain experts", (see this source item no.4 for a description of these legendary beings).i.e: What is your code in plain English?
What your code says is basically find the Objects with these given ids from the repositories of the Entities that have an association to A.This looks pretty good since you have no explicit dependencies on what A has associations to.But looking at it closer, you'll see that you do have dependencies on actual B and C Objects and their repositories, since when you provide an id for some Object, you're not just providing an id, but you're also implicitly stating what that object is, otherwise an id would have no meaning other than it's scalar Value.However that approach definitely has it's use cases both in Semantics of the Design, and RAD.But there is still the issue of Law of Demeter, but it can be solved, see below:
Either way I think you should definitely have a factory for A objects that looks something like this.
class AFactory{
protected $br;
protected $cr;
public function __construct(BRepositoryInterface $br, CrepositoryInterface $cr){
$this->br = $br;
$this->cr = $cr;
}
public function create($atr1, $atr2, $bId, $cId){
$b = $this->br->find($bId);
$c = $this->cr->find($cId);
return new A($atr1, $atr2, $bId, $cId);
}
}
Now you can actually create this factory using the design you stated by having another factory for this factory, this will also solve the issue with Law of Demeter.That Factory will have the Entity Manager as it's dependency, it will read A's metadata, and fetch the Repositories of the related objects based on that metadata, and create a new AFactory Instance from those repositories, now if you implement those interfaces (BRepositoryInterface and CRepositoryInterface) in your actual Doctrine Repositories, the AFactory instance will be successfully created.
So I've stumbled upon this hurdle where I have to create an abstract class and a factory to create objects of more specific classes that extend the abstract class and implement more specific object methods.
Simply said, I got a SocialMediaAbstract class. Extending classes are Facebook, Instagram, and they implement a SocialMediaInterface. Facebook, Instagram etc are all saved in the db, with an id, a name and several more properties that are all used among the extending classes, hence an abstract class.
Because I want to be able to query several things from the SocialMedia Objects, and every social media platform have their own APIs for it, I made the interface and created the different classes so they can all have their own implementations of those methods.
Now, the problem is of course with my abstract class and Doctrine. Doctrine says this on their website regarding inheritance:
A mapped superclass cannot be an entity, it is not query-able [...]
Now if I had a SocialMediaFactory and threw in an ID, I would like to get the respective Object of, for example, class Facebook or Instagram back. I don't want to know exactly which SocialMedia it is when I collect them. Now that is a problem with doctrine, at least that's what I think it is.
Am I overlooking something, is the factory pattern still possible? Or should I really just remove the abstract class, and create a factory that searches in every table of a SocialMediaInterface implementing class, which seems highly inefficient and unmaintable when an application gets bigger.
Any insight or pointers would be appreciated, since I'm sure this problem must've come up more often. I tried googling and searching on Stackoverflow itself, but I couldn't get any relevant questions or answers.
Thank you very much in advance.
EDIT:
I came across this interesting possibility: Class Table Inheritance. This would mean adding:
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"facebook" = "Facebook", "instagram" = "Instagram"})
to my code. I had high hopes, but sadly enough the validator gave me this error:
[Doctrine\ORM\Mapping\MappingException]
It is not supported to define inheritance information on a mapped superclas
s 'Portal\SocialMedia\Entity\SocialMediaAbstract'.
A shame mapper superclasses are not supported.
EDIT 2/CONCLUSION:
I've decided to go with Class Table Inheritance (just like the answer below suggested). Removing the abstract from the class made it possible to still use my factory.
I am using a concrete class as an abstract class now however, which feels wrong. I've documented in docblock that no objects should be instantiated from this class.
One little sidenote: Doctrine's Entity Manager more or less already provides the Factory:
$socialMedia = $entityManager->find('Portal\SocialMedia\Entity\SocialMedia', 2);
This returns an Instagram object. I still suggest you build your own factory above it for maintainability later as the SocialMedia entity might change later on.
Some time has passed now since I worked with doctrine, but if I remember correctly, doctrine's mapped super classes are an implementation of the concrete table inheritance pattern by Martin Fowler.
In the example mentioned there, the Player is the mapped super class, whose attributes are distributed to all inheriting entities / models. The point here is that a player can't be instantiated and thus has no own id. Instead, every inheriting model got it's own id, which are all independent of each other.
I think the pattern you are looking for is either single table inheritance or class table inheritance (have a look at doctrine's inheritance types).
Single table inheritance is implemented in doctrine's inheritance type "SINGLE_TABLE", where you have one table for all entities. They are sharing the exact same attributes and same id pool, meaning you can "throw in" an id, get the object and check the type (Facebook, Instagram etc..).
The downside is that if you got in any of the entites an attribute that may be NULL, you could run into problems if the other entites don't have this attribute or don't need it. This would mean you have to set the given attribute to a dummy value in the other entities to save them into the database table.
Class table inheritance overcomes this issue by saving every entity in its own table, while still being able to share the id pool, because doctrine takes care that the common attributes are saved in the base class table, while all the attributes specific to an entity are saved in the entity's table. The tables are then joined by the id, hence the inheritance type "JOINED" in doctrine.
Conclusion:
Use single table inheritance if the classes are very similar and only differ in function definition or implementation, but have the same attributes.
Use class table inheritance if the classes have distinct attributes that would be problematic to store in a single table.
Use concrete table inheritance if the classes are not really related to each other, but only share a small amount of common attributes. But this could also be implemented through PHP's traits, which in my opinion is easier and more flexibly to use than doctrine's mapped super class. In a PHP trait you can also use doctrine's annotations, because the PHP interpreter will properly assign the annotations to the classes you use the traits in.
You should still be able to use your SocialMediaFactory with either single table or class table inheritance pattern.
In laravel, the Eloquent\Builder class sends every call to methods which it doesn't have to an internal Query\Builder. To me this sounds like inheritance. Somebody knows why they didn't implement it so that the Eloquent\Builder extends Query\Builder? The reason I first noticed it was that I got "Call to undefined method" errors in IDEs, despite the code working fine which is the curse of magic methods I suppose.
For reference, here is relevant source from Eloquent\Builder.
/**
* The base query builder instance.
*
* #var \Illuminate\Database\Query\Builder
*/
protected $query;
protected $passthru = array(
'toSql', 'lists', 'insert', 'insertGetId', 'pluck', 'count',
'min', 'max', 'avg', 'sum', 'exists', 'getBindings',
);
public function __call($method, $parameters)
{
if (method_exists($this->model, $scope = 'scope'.ucfirst($method)))
{
return $this->callScope($scope, $parameters);
}
else
{
$result = call_user_func_array(array($this->query, $method), $parameters);
}
return in_array($method, $this->passthru) ? $result : $this;
}
I'll start off with my conclusion. I think it was just poorly engineered.
Let me do a few explanations, and also reply to the accepted answer by #Simon Bengtsson
I'm by no means trying to offend anyone, but I'm just trying to word out my thoughts.
Actually the whole point of inheritance is that they have similar characteristics, but you would like to add an extra layer to put some extended features. Obviously, the extended "child" class will know more than the "parent" class (such as knowing about the Eloquent Model)
To me, a "Builder" is a Builder. Afterall, both are actually building a query, regardless of what conditions its checking or observing. That's the purpose of a Builder (from what I see at least). So it's in the same layer (except Eloquent\Builder has some extra features).
The current implementation is overriding the nature of a few methods such as where() (which are basically those in Query\Builder, same name, same arguments). It's also adding a few methods, which eventually calls methods like where(). This is all about inheritance. If I call where(), and it exists in child class, the child class method gets called. If not, it will call the method in parent class.
Later down the line it becomes more difficult to then decouple the low level and ORM level components if you hypothetically wanted to use some new NoSQL DB instead
and simply write a Query\Builder signature compliant drop-in class.
#Simon Bengtsson
I don't see how it gets difficult to decouple. All you have to do, is to write a new class Query\MongoDBBuilder, which has the same interface as Query\Builder. If you're worried, you can always make the classes "implements" an Interface. If you ask me, actually the current way is harder to decouple, because it's quite messy right now as to "which features are overridden and which are not".
I do encourage class decoupling in some cases, but if I were to decouple this one (which I don't think is necessary here), I would do it this way:
Eloquent\Model
Eloquent\Adapter (This is some sort of intermediate layer, where you could put connection settings etc.)
Eloquent\Builder extends Query\Builder (This is a "wrapper" for Query\Builder so that it could do slightly more, but achieving the same goals)
Child classes also have access to protected properties on parent classes so that Eloquent\ChildOfQueryBuilder would have the freedom to rely on the low level implementation
of Query\Builder and could be coupled to it.
#Simon Bengtsson
This is the whole point about inheritance. You would to be able to access protected properties to override a feature given by the parent. Let's look at it from another point of view, what if you NEED to access these variables in order to modify the feature? In fact, the author declaring these members "protected" already implies that he is ready for another class to extend it. That's the only purpose of making it "protected", correct?
That's why you would have to know exactly what a parent class is doing before inheriting it, because it could be dangerous.
The reason why I'm giving this huge explanation is because I'm trying to modify some features for Eloquent. I've been looking at the implementation of days (the 3 god classes: Eloquent\Model, Eloquent\Builder, and Query\Builder). The layering and aliasing was really messed up. Extending the Model class requires me to redeclare almost equivalent functions due to its poor implementation. But that's off topic.
In conclusion, if you ask "why", I would actually say (now I know people will kick me) that it was just poorly engineered and implemented.
I think delmadord was sort of heading towards the right answer but I think bringing the IoC into it blurs the issue. The basic answer is that the two classes represent abstractions of the database at different levels. Query\Builder is the lower level abstraction and Eloquent\Builder is a higher level abstraction which is why, as you pointed out it makes use of Query\Builder for its core functionality.
You can tell this from the properties that are defined for each class. One has properties surrounding things such as:
connection settings,
database grammars and,
various things relating to the query that will be assembled
The other is more an ORM and is concerned with higher level concerns such as whether eager relationship loading should be used and which model the query is currently bound to. Arguably, you could use inheritance here and might have pretty much the same functionality but from an architectural standpoint there are issues with this.
One is that, strictly speaking, I should always be able to use a child class as a drop in replacement for a parent class. This is simpler to see if you adopt the "is a" reading of inheritance. This means that if you used inheritance for this pair of classes, strictly speaking, any developer down the line is able to make use of Eloquent\Builder just as easily as Query\Builder and in fact might be encouraged to do so throughout the code in order to have one less class to track in their minds. This will mean code may call $builder->getRelation() and rely on the consequences on (for argument's sake) $builder->wheres all in the same block of code.
Later down the line it becomes more difficult to then decouple the low level and ORM level components if you hypothetically wanted to use some new NoSQL DB instead and simply write a Query\Builder signature compliant drop-in class.
Child classes also have access to protected properties on parent classes so that Eloquent\ChildOfQueryBuilder would have the freedom to rely on the low level implementation of Query\Builder and could be coupled to it. You could argue that you could just make it private but then you can longer write a thin low-level extension to Query\Builder (adding some clustering, sharding or security logic maybe) that may (rightfully) need access to the implementation details that could have been a drop-in replacement for the low-level functionality.
Another is that the size of the class grows quite rapidly if you pile everything related into one "God object". Both of the Builder classes have a large amount of abstraction layer specific logic within them. If you inherit, then Eloquent\Builder would effectively be the union of the two and you would have almost twice as much code to scan for issues and your IDE would give you a much broader range of autocompletion options, with a significant fraction being unrelated to the abstraction depth you're working at.
The same pattern is used sometimes in other places where two classes are very related to each other, but inheritance would cause perception issues which would encourage their use in ways the developer does not want. With Java for example, immutable classes typically have mutable counterparts but neither inherits the other and they might not even have common ancestry.
This happens because the immutable class can't have any mutator methods. Inheriting from the mutable version would require overriding and disabling each mutator method and forever ensuring this happens correctly. Forget this once and your immutable class may be mutable for a few revisions. And you can't allow inheritance the other way around because doing so means a method expecting an immutable class might get a mutable child and add grey hairs to people.
This is another instance of related things playing distinct roles and thus being conceptually separated. Its not that you can't do things a particular way but more that certain architecture choices discourage behaviours you don't want and leave room to do things that you do think you'll want to do down the line. Sometimes with very large code-bases, decoupling things along an interface like that really helps to make it easier to reason about and work with.
If you look at the source of Illuminate/Database/Eloquent/Builder
<?php namespace Illuminate\Database\Eloquent;
use Closure;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Builder as QueryBuilder;
class Builder {
/**
* The base query builder instance.
*
* #var \Illuminate\Database\Query\Builder
*/
protected $query;
You can see, that it is using the instance of the Illuminate\Database\Query\Builder. It is not extending the class, probably for make use of the IoC in Laravel. Inject the instance and it get pulled everything needed.
I'm working on a large project at the moment and am just wondering which is best practice, to model entities and sets of entities seperately or in one class?
Currently I am implementing two classes for each entity (for example an 'author' and 'authors' class) where the plural class contains methods like 'fetch authors' (using Zend_Db_Table_Abstract for plural and Zend_Db_Table_Row_Abstract for singular).
However I realised that I've often seen methods like 'fetch/list' functions in a single entity's object, which seems quite neat in terms of the fact that I won't have to have as many files.
I know there are no hard-and-fast rules for data modelling but before I continue too far I'd be interested in learning what the general consensus on best-practice for this is (along with supporting arguments of course!).
Answers [opinions] gratefully received!
Rob Ganly
Personally, I prefer a model called Person to actually represent a single person and a model like PersonCollection to represent a collection of persons. In neither case, would I have methods for fetch/get on these objects. Rather, I would put those methods on a PersonRepository or a PersonMapper class.
That's really my biggest area of discomfort with ActiveRecord as a pattern for modeling. By having methods like find() and save(), it opens the door to methods like getPersonByName(), getPersonsWithMinimumAge(), etc. These methods are great, nothing wrong with them, but I think that semantically, they work better on a mapper or a repository class. Let the Model actually model, leave persistence and retrieval to mappers and repositories.
So, to more directly address your question, I see potentially three classes per "entity type":
Person - actually models a person
PersonCollection - extends some Abstract Collection class, each item of class Person
PersonMapper - persistence and retrieval of Person objects and PersonCollections
Controllers would use the mapper to persist and retrieve models and collections.
It's probably no surprise that I'm drawn to Doctrine2. The EntityManager there functions as a single point of contact for persistence and retrieval. I can then create repositories and services that use the EntityManager for custom functionality. And I can then layer on action helpers or factories or dependency injection containers to make it easy to get/create those repositories and services.
But I know that the standard ActiveRecord approach is quite common, well-understood, and very mainstream. You can get good results using it and can find many developers who immediately understand it and can work well with it.
As in most things, YMMV.