Doctrine ORM and factories with abstract classes strategy - php

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.

Related

Which is the proper way to create Entity classes in PHP

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

Doctrine inheritance strategy when two different subclasses extend the same entity instance

I am developing an application for managing court interpreter services (using Doctrine and Zend Framework 2). There are a lot of people involved who have various specialized roles, hence a Person superclass, and subclasses. The class hierarchy is not complicated in a vertical sense -- one generation of inheritance is enough -- but the horizontal aspect is giving me trouble.
I don't think mapped superclasses fit my case. I also considered single-table inheritance but that would quickly get ugly because the subclasses have their own entity relationships, too much stuff to cram gracefully into a single table.
That leaves us with class table inheritance, which is a really nice fit in most respects, but... I will have plenty of cases where the subclass User (for authentication) and the subclass Interpreter will (or should) point to the same row in the parent data table, because they represent one and the same person in reality. But because of the discriminator column you have to choose one or the other, or else create two different rows holding the same data -- and the normalization police should get you for that.
I think maybe either the User or the Interpreter entity has to simply have a one-to-one relationship with the Person entity, and deal with that semi-manually. Another option I suppose would be to collapse User into Person -- but that's ugly because a lot of people will not be authenticating and will not have or need a password.
I have looked at
Doctrine inheritance, several entities extending the same super class and
How to change and entity type in Doctrine2 CTI Inheritance (inter alia) and neither one solves this.
So, I wonder if anyone has any suggestions. Thanks.
It sounds like you're managing a bunch of data about Persons, which identifies individual humans in the world. Since only some subset of the people in the system are Users, I'd argue that concerns about authentication, audit logging, notifications, etc are separate from the concerns of the Person class hierarchy.
I'd advise removing User from the Person class hierarchy. Perhaps rename it Account, to make it feel less person-y. An Account can have an owner property, which is a relation to Person. If you want to use the Person's email address as an identifier for authentication, that's fine. If you later wanted to add a username instead, that would be a property of Account, since it's only meaningful in that context.
Not sure about the underlying code (not a ZF developer), but I think you are confusing the behavior and the data.
To make the authentication working you do not need the inheritance really. Just found you code ontop of the interface dependencies.
To make the users able to auth (while generic person could not) - use the inheritance or, as #timdev suggested, the relation. In symfony world I'd better write this something like
class User extends Person implement UserInterface {
//... implementation
}
class Person {
//...
}
After that you can just be sure, that you have a UserInterface while any service stuff and authentication particularly.
In case if you have to dynamically switch the underlying class of User entity (i.e. you have Author extends Person and want allow some authors to sign in) I think the composition is the only suitable solution. Split the logic, split the entites, split the data. Be happy.

What is the best way to dynamically set a linked property with just their FK

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.

Modelling in Zend framework

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.

PHP classes: Need help to inherit two classes

I need help in designing my PHP classes where I need to extend from multiple classes.
I have a general class, Pagination.php that does all sort of pagination and sorting. All other classes will use this for pagination.
To make my life easier, I made a class generator that generates a class from MySQL table. All the properties, getters, setters and common methods are created automatically, which really saves time and money.
As an example, class Staff_Base in Staff_Base.php is generated automatically from SQL table t_staff.
Since class Staff_Base is automatically generated from SQL table, any 'custom' methods / properties are located in another class that extends Staff_Base.php. (So that whenever a new field is added, I can simply regenerate Staff_Base class and overwrite in Staff_Base.php).
So I have class Staff.php that extends Staff_Base.php.
The problem is, Staff.php also needs to extend another class, Pagination.php.
(The current workaround is to put methods in Pagination.php into every class. This is really troublesome whenever I make changes to the pagination/sorting methods.)
How do I do this?
What is the best design pattern to achieve this?
I know common suggestions to restructure my classes, but I really think hard of other workaround/solution. Also, I may also need to extend other classes than Pagination.php.
Thanks!
Can you have your generated Staff_Base class inherit from Pagination? Or does Staff_Base already inherit from another base class (that you do not have control over)...
Sounds like either Doctrine or Propel, I do not recall which uses the *_Base class system.
My suggestion would be to rewrite pagination to be able to be used by your entity classes instead of requiring your entity classes to extend it.
So if I am reading what you wrote correctly, since you can't inherit from 2 classes you are duplicating paginate into every class you have.
Class stacking is a solution. One of the first things I googled.
I would recommend changing your Staff_Base.php generator to make that class extend Pagination by default. That way Staff extends Staff_Base, and Staff_Base extends Pagination. I think that's probably the cleanest (and most object-oriented) way of getting the results you want.
you cant, multiple inheritance is not supported in php, but if you do a google search on this topic you can find some workarounds...
It sounds like you're mixing things up here. A class (such as a Staff class) is used to represent a single entity. Eg:
$john = new Staff('John');
How exactly does the paging fit into this? Being page-able (paginatable?) sounds like a property of whatever it is that allows access to these Staff entities, not of the entity itself. That way, the way is clear for each type of Staff class you create to inherit from the base class.
So, what I believe would be the solution you need:
A Staff class (Staff_Base, and its graph of children)
A Staff Data Access Object (DAO\Staff would be a nice name, if you're using namespaces)
An Interface, to signal to the world that a DAO can be paged
Import to note is that there is no direct inheritance between the DAO class and the Staff class. You can still generate the Staff_Base class based on its properties in the database, and extend from there... as long as you don't include the actual data access in that class.
The code using this would then look something like this:
<?php
$staffDao = new DAO\Staff;
$staffMembers = $staffDao->getPagedResult($start, $amount);
?>
Edited to emphasize that the inheritance structure should be separate from the actual retrieval
Well, you might already know that PHP doesn't support multiple inheritance. One way around might be using Interfaces instead of superclasses, although, if the logic is identical for each implementing of the interface, this might become tedious. How about writing a code generator, that simply injects the methods to each class? You seem to already do that on the "common methods".
Oh, and using getters and setters (as they are used in e.g. Java) in PHP is considered not a good idea. Objects are slow as they are, so using public fields is considered the norm.
Edit: Then there's the __call()-hack, which could recognize the methods that actually reside in your other classes, and call them manually.

Categories