Custom Collection in Doctrine2 - php

Just starting to work with Doctrine2, and am wondering how/if I can use a custom collection class. Searches point me to this part of the documentation:
Collection-valued persistent fields and properties must be defined in terms of the Doctrine\Common\Collections\Collection interface. The collection implementation type may be used by the application to initialize fields or properties before the entity is made persistent. Once the entity becomes managed (or detached), subsequent access must be through the interface type.
While I'm sure that's crystal clear to someone, I'm a little fuzzy on it.
If I setup my Entity to initialize (say in __construct()) the collection variable to a class that implements the correct interface - will Doctrine2 continue to use that class as the collection? Am I understanding that correctly?
Update: Also, I gather from various threads that the placeholder object used in lazy loading may influence how a custom collection can be used.

Let me try to clarify what is possible, not possible and planned with examples.
The quote from the manual basically means you could have the following custom implementation type:
use Doctrine\Common\Collections\Collection;
// MyCollection is the "implementation type"
class MyCollection implements Collection {
// ... interface implementation
// This is not on the Collection interface
public function myCustomMethod() { ... }
}
Now you could use it as follows:
class MyEntity {
private $items;
public function __construct() {
$this->items = new MyCollection;
}
// ... accessors/mutators ...
}
$e = new MyEntity;
$e->getItems()->add(new Item);
$e->getItems()->add(new Item);
$e->getItems()->myCustomMethod(); // calling method on implementation type
// $em instanceof EntityManager
$em->persist($e);
// from now on $e->getItems() may only be used through the interface type
In other words, as long as an entity is NEW (not MANAGED, DETACHED or REMOVED) you are free to use the concrete implementation type of collections, even if its not pretty. If it is not NEW, you must access only the interface type (and ideally type-hint on it). That means the implementation type does not really matter. When a persistent MyEntity instance is retrieved from the database, it will not use a MyCollection (constructors are not invoked by Doctrine, ever, since Doctrine only reconstitutes already existing/persistent objects, it never creates "new" ones). And since such an entity is MANAGED, access must happen through the interface type anyways.
Now to what is planned. The more beautiful way to have custom collections is to also have a custom interface type, say IMyCollection and MyCollection as the implementation type. Then, to make it work perfectly with the Doctrine 2 persistence services you would need to implement a custom PersistentCollection implementation, say, MyPersistentCollection which looks like this:
class MyPersistentCollection implements IMyCollection {
// ...
}
Then you would tell Doctrine in the mapping to use the MyPersistentCollection wrapper for that collection (remember, a PersistentCollection wraps a collection implementation type, implementing the same interface, so that it can do all the persistence work before/after delegating to the underlying collection implementation type).
So a custom collection implementation would consist of 3 parts:
Interface type
Implementation type (implements interface type)
Persistent wrapper type (implements interface type)
This will not only make it possible to write custom collections that work seemlessly with the Doctrine 2 ORM but also to write only a custom persistent wrapper type, for example to optimise the lazy-loading/initialization behavior of a particular collection to specific application needs.
It is not yet possible to do this but it will be. This is the only really elegant and fully functional way to write and use completely custom collections that integrate flawlessly in the transparent persistence scheme provided by Doctrine 2.

No, whenever Doctrine gives you back an implementation of the Doctrine\Common\Collections\Collection interface, it will be a Doctrine\ORM\PersistentCollection instance. You cannot put more custom logic on the collection. However that is not even necessary.
Say you have an entity (Order has many OrderItems), then a method to calculate the total sum of the order should not be located on the collection, but on the Order item. Since that is the location where the sum has meaning in your domain model:
class Order
{
private $items;
public function getTotalSum()
{
$total = 0;
foreach ($this->items AS $item) {
$total += $item->getSum();
}
return $total;
}
}
Collections however are only technical parts of the ORM, they help to implement and manage references between objects, nothing more.

Same question here, with a reference to the official doctrine Jira issue page with the details and status of this 'feature'... You can keep track of the development there!

Related

How to avoid implicit dependencies between Service class and Model class in PHP

If I have a site design which follows a dependency flow of:
Handler Class <-> Service Class <-> Mapper Class <-> Model Class
Handler receives the request, Service contains the logic, Mapper performs the DB queries and uses the Model to work on the data, while the Model represents a single record in the DB.
Ideally, you would have explicitly defined dependencies on/from the neighboring layers. So if I change a particular layer, only the two immediately neighboring layers might be affected.
However, I realized I may be using some bad practices. In particular, I have the Service class call a method on the Mapper class. The Mapper class would return an instance of the Model class. But if I then call a method of the Model class, from within the Service class, there is now a direct and implicit dependency between the Service class and the Model class.
I have a few thoughts on how to address this, which I'll outline below. But I feel there has got to be a better way. So I'm curious what the general consensus is on avoid these implicit dependency situations while avoiding unnecessary processing.
Inject an empty instance of the Model into the Service class to make the dependency explicit. But this seems clunky and doesn't account for multi-record result sets.
Specify the Model interface as the return type in the Mapper Interface for that method. To me, this seems like the preferred method. However, it gets complicated when you have to return multi-record result sets. I would rather not unnecessarily iterate through the entire result set within the Mapper class, before I even begin to use the results for the actual application logic. At a minimum, that would be O(2n) time complexity for nearly every query. So I've just been returning an object which is an \Iterable and iterating over that within the Service class (so O(n) is the floor instead of O(2n)). But this is the same situation where there is an implicit dependency on the Model class.
I've been trying to find out if it's possible to specify the type of object the \Iterable will iterate over, like you can with arrays (IE: int[] is an array of integers). The best I could come up with was to create a custom Iterator class specific to the Model class. Is this the preferred method of eliminating these implicit dependencies, while avoiding unnecessary loops?
Much appreciation!
Edit based on feedback:
I don't have any code which fails, and this question isn't meant to be specific to any real code. This question is solely about an abstract problem. That is why no code was originally included. But based on feedback I've drafted up the following to help make the purposed situation more clear.
Just ignore the Handler class, it's not needed to illustrate the concept, I was just trying to describe the overall structure with it to make it easier to identify the design pattern.
The Service class:
namespace App\Service;
class Service implements ServiceInterface
{
protected mapperInterface $mapper;
public function __construct(mapperInterface $mapper){
$this->mapper = $mapper;
}
public getAllRows() {
$iterator = $this->mapper->getAllRows();
while($iterator->valid()){
$current = $iterator->current();
// This line creates an implicit dependency on the Model class
$name = $current->getName();
$iterator->next();
}
}
}
The Mapper Class:
namespace App\Mapper;
class Mapper implements MapperInterface
{
protected modelInterface $modelPrototype;
public function __construct(modelInterface $model){
$this->modelPrototype = $model;
}
public getAllRows() : Iterator {
// Execute SQL then hydrate into an iterator over multiple "Model" objects into a variable ($resultSet in this case)
return $resultSet; // This is an Iterator instance of which each iteration contains a "Model" object.
}
}
The Model class:
class Model implements ModelInterface
{
protected string $name;
public function getName() : string {
return $this->name;
}
public function setName(string $name) : void {
$this->name = $name;
}
}
It is specifically this line in the Service class which creates an implicit dependency between the Service class and the Model class (bypassing the transitive dependency through the Mapper class):
$name = $current->getName();
There are two ways to correct this, either make the dependency explicit, or eliminate the dependency in the first place. I've listed my ideas on how to achieve those two options. But I am curious what the most common solution to this situation is. Is there some other option or method of addressing this which I have not thought of? Or is one of my proposed ideas the generally preferred method.
Technically i also don't see a dependency. The Service ask it's neighbour Mapper for a collection of Model and it provides one. The Mapper uses the Model and hydrates the data from whereever. So communication-wise everything is fine.
If you would access data in your Service with
$this->mapper->model->someModelMethod();
instead of
$this->mapper->getAllRows();
only then you would violate something at least in the sense of the law of demeter.
The dependency on the level you might think having an issue is probably some kind of tight coupling inside your layers, which is generally okay for this use case.
If you wanna decouple it between layers/modules/units consider introducing another kind of data container to pass around.
For example using some kind of Transfer Object and map/hydrate the data from your model to it. This transfer object can be used to pass around e.g. on the communication layer like Controllers, Services etc. You only rely on the transfer objects properties but not on the model itself. Only your mapper has to be adapted if something changed on both the Model and the Transfer Object

What is the purpose of using traits to define functions for an interface

Sorry if this is a duplicate question or a common design principle, I have searched around but was unable to find any answers to this question. I'm probably just searching with the wrong keywords.
I have been looking at a popular library Sabre/Event (https://sabre.io/event/) and in the code there is a simple class/inheritance model that I am trying to understand:
The class EventEmitter implements EventEmitterInterface and uses EventEmitterTrait (see below for code).
There is a comment in EventEmitterTrait above the class which says:
* Using the trait + interface allows you to add EventEmitter capabilities
* without having to change your base-class.
I am trying to understand why this comment says this, and why it allows adding capabilities without changing the base class, and how that is different from just putting the routines into EventEmitter itself.
Couldn't you just extend EventEmitter and add capabilities in the derived class?
Simplified code:
// EventEmitter.php
class EventEmitter implements EventEmitterInterface {
use EventEmitterTrait;
}
// EventEmitterInterface.php
interface EventEmitterInterface {
// ... declares several function prototypes
}
// EventEmitterTrait.php
trait EventEmitterTrait {
// ... implements the routines declared in EventEmitterInterface
}
You're basically asking two questions here.
What are interfaces and why are they useful?
What are traits and why are they useful?
To understand why interfaces are useful you have to know a little about inheritance and OOP in general. If you've ever heard the term spaghetti code before (it's when you tend to write imperative code that's so tangled together you can hardly make sense of it) then you should liken that to the term lasagna code for OOP (that's when you extend a class to so many layers that it becomes difficult to understand which layer is doing what).
1. Interfaces
Interfaces diffuse some of this confusion by allow a class to implement a common set of methods without having to restrict the hierarchy of that class. we do not derive interfaces from a base class. We merely implement them into a given class.
A very clear and obvious example of that in PHP is DateTimeInterface. It provides a common set of methods which both DateTime and DateTimeImmutable will implement. It does not, however, tell those classes what the implementation is. A class is an implementation. An interface is just methods of a class sans implementation. However, since both things implement the same interface it's easy to test any class that implements that interface, since you know they will always have the same methods. So I know that both DateTime and DateTimeImmutable will implement the method format, which will accept a String as input and return a String, regardless of which class is implementing it. I could even write my own implementation of DateTime that implements DateTimeInterface and it is guaranteed to have that method with that same signature.
So imagine I wrote a method that accepts a DateTime object, and the method expects to run the format method on that object. If it doesn't care which class, specifically, is given to it, then that method could simply typehint its prototype as DateTimeInterface instead. Now anyone is free to implement DateTimeInterface in their own class, without having to extend from some base class, and provide my method with an object that's guaranteed to work the same way.
So in relation to your EventEmitter example, you can add the same capabilities of a class (like DateTime) to any class that might not even extend from DateTime, but as long as we know it implements the same interface, we know for sure it has the same methods with the same signatures. This would mean the same thing for EventEmitter.
2. Traits
Traits, unlike interfaces, actually can provide an implementation. They are also a form of horizontal inheritance, unlike the vertical inheritance of extending classes. Because two completely different class that do not derive from the same base class can use the same Trait. This is possible, because in PHP traits are basically just compiler-assisted copy and paste. Imagine, you literally copied the code inside of a trait and just pasted it into each class that uses it right before compile time. You'd get the same result. You're just injecting code into unrelated classes.
This is useful, because sometimes you have a method or set of methods that prove reusable in two distinct classes even though the rest of those classes have nothing else in common.
For example, imagine you are writing a CMS, where there is a Document class and a User class. Neither of these two classes are related in any meaningful way. They do very different things and it makes no sense for one of them to extend the other. However, they both share a particular behavior in common: flag() method that indicates the object has been flagged by a user for purposes of violating the Terms of Service.
trait FlagContent {
public function flag(Int $userId, String $reason): bool {
$this->flagged = true;
$this->byUserId = $userId;
$this->flagReason = $reason;
return $this->updateDatabase();
}
}
Now consider that perhaps your CMS has other content that's subject to being flagged, like a Image class, or a Video class, or even a Comment class. These classes are all typically unrelated. It probably wouldn't make much sense just to have a specific class for flagging content, especially if the properties of the relevant objects have to be passed around to this class to update the database, for example. It also doesn't make sense for them to derive from a base class (they're all completely unrelated to each other). It also doesn't make sense to rewrite this same code in every class, since it would easier to change it in one place instead of many.
So what seems to be most sensible here is to use a Trait.
So again, in relation to your EventEmitter example, they're giving you some traits you can reuse in your implementing class to basically make it easier to reuse the code without having to extend from a base class (horizontal inheritance).
Per Sabre's Event Emitter's docs on "Integration into other objects":
To add Emitter capabilities to any class, you can simply extend it.
If you cannot extend, because the class is already part of an existing
class hierarchy you can use the supplied trait.
So in this case, the idea is if you're using your own objects that already are part of a class hierarchy, you may simply implement the interface + use the trait, instead of extending the Emitter class (which you won't be able to).
The Integration into other objects documentation says:
If you cannot extend, because the class is already part of an existing class hierarchy you can use the supplied trait".
I understand it's a workaround when you already have an OOP design you don't want to alter and you want to add event capabilities. For example:
Model -> AppModel -> Customer
PHP doesn't have multiple inheritance so Customer can extend AppModel or Emitter but not both. If you implement the interface in Customer the code is not reusable elsewhere; if you implement in e.g. AppModel it's available everywhere, which might not be desirable.
With traits, you can write custom event code and cherry-pick where you reuse it.
This is an interesting question and I will try to give my take on it. As you asked,
What is the purpose of using traits to define functions for an interface ?
Traits basically gives you the ability to create some reusable code or functionality which can then be used any where in your code base. Now as it stands, PHP doesn't support multiple inheritance therefore traits and interfaces are there to solve that issue. The question here is why traits though ?? Well imagine a scenario like below,
class User
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
public function name(){}
public function friends(){}
// and a few other methods
}
Now lets say that we have a post class which has the same logic as user and that can be achieved by having hasRatings() and hasBeenFavorited() methods. Now, one way would be to simply inherit from User Class.
class Post extends User
{
// Now we have access to the mentioned methods but we have inherited
// methods and properties which is not really needed here
}
Therefore, to solve this issue we can use traits.
trait UserActions
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
}
Having that bit of logic we can now just use it any where in the code where ever it is required.
class User
{
use UserActions;
}
class Post
{
use UserActions;
}
Now lets say we have a report class where we want to generate certain report on the basis of user actions.
class Report
{
protected $user;
public function __construct(User $user)
{
$this->user = $user
}
public function generate()
{
return $this->user->hasRatings();
}
}
Now, what happens if i want to generate report for Post. The only way to achieve that would be to new up another report class i.e. maybe PostReport.. Can you see where I am getting at. Surely there could be another way, where i dont have to repeat myself. Thats where, interfaces or contracts come to place. Keeping that in mind, lets redefine our reports class and make it to accept a contract rather than concrete class which will always ensure that we have access to UserActions.
interface UserActionable
{
public function hasRatings();
public function hasBeenFavorited();
}
class Report
{
protected $actionable;
public function __construct(UserActionable $actionable)
{
$this->actionable = $actionable;
}
public function generate()
{
return $this->actionable->hasRatings();
}
}
//lets make our post and user implement the contract so we can pass them
// to report
class User implements UserActionable
{
uses UserActions;
}
class Post implements UserActionable
{
uses UserActions;
}
// Great now we can switch between user and post during run time to generate
// reports without changing the code base
$userReport = (new Report(new User))->generate();
$postReport = (new Report(new Post))->generate();
So in nutshell, interfaces and traits helps us to achieve design based on SOLID principles, much decoupled code and better composition. Hope that helps

Which design pattern should I use to wrap common method to entities?

I'm a PHP Developer, and I'm working with Symfony2 at the moment.
I would like to present my issue as follow:
I have 4 entities: User, Account, Customer, Merchant. All of them have status.
I want to build a common method named 'isValid' for them, but don't want to modify their code.
The method logic is very simple
<!-- language: php -->
public function isValid()
{
return self::STATUS_ACTIVE == $this->status;
}
By separate them and apply a HAS-A relation between it with entities, I think it will more flexible and maintainable. I don't have to duplicate my code to any entity need it, even in the future.
If you have experience. Could you please help me to pick a suitable pattern for this situation?
Creating a has-a relation between these entities makes no sense, since they are not related.
However, code duplication is almost never justifiable. I would solve it by creating a common interface (User is-a Validatable entity, Customer is-a Validatable entity) and make a trait to encapsulate the common behavior.
Create the common interface:
interface Validatable
{
public function isValid(): bool;
}
Create a trait to implement the common behaviour:
trait HasStatus
{
/**
* #var int
* #ORM\Column(type="integer")
*/
private $status;
public function isValid(): bool
{
return $this->status === EntityStatus::STATUS_ACTIVE;
}
}
Make your entities implement the new interface and put the trait to use to avoid duplication:
class User implements Validatable {
use HasStatus;
}
And use it:
/** #var Validatable[] $validatables */
$validatables = [new User(), new Merchant(), new Customer()];
foreach ($validatables as $validatable) {
var_dump($validatable->isValid());
}
Why do we need the interface? Well technically we do not need it, but I like to include it because it allows to refer to User, Customer, Merchant with a common "Validatable" typehint and it conveys your intention in code.
Messing with this it's not a good idea, the entity has status value, and setters/getters should be in entity file declaration.
I understand the DRY principle but doing it on this level... it's IMHO not a good idea.
But if you are sure that all of them have status, then use a trait in a separate file:
trait CheckStatusTrait{
return $this->status;
}
And you just add the trait to your classes:
class User {
use CheckStatusTrait
}
For that simple kind of code, it would be okay do leave it duplicated in each entity, you can add an interface with "isValid" to treat them like the same from outside if necessary.
Maybe your code to check Validation would become more complex and it makes sense to have a single class which is responsible.
Then you could make a StatusValidator class which checks if the status of a given object ist valid. It would make sense to add an interface to that kind of objects, which has a "getStatus" method, let's say the "getStatusInterface". Afterwords you can inject the StatusValidator and use it in your isValid method. Because your objects are entities, you need to use doctrine's postLoad event to inject the StatusValidator.
You also can do the same i little bit less complex by not inject the StatusValidator but ask the StatusValidator if the obejct with the getStatusInterface is valid.
Thank all for the supports. I'm also using trait to solve code duplication. However, I see that trait seem to be not a perfect one. I had to fact to disadvantages below:
Hiding the field in trait makes entity enigmatic. In real, not only will status field is available on many entities but also updatedDate, createdDate, type... It also looks mess when a class use many traits.
After a development period, the trait collects more and more method, for ex. StatusTrait can have isValid, hasStatus, setStatusDefault. But not all of entities use them. I mean some entities use isValid, some use setStatusDefault.., so we will have more mixed methods in traits. In this issue, I think that if I can implement a HAS-A relationship class, I can easily setup them at the runtime when an entity need.
By using trait, the entity class is modified, not extension. It isn't a good practice in OOP design. The entity class isn't consistent to reference with database table. Honestly, I prefer to build logic method outside the entity class.
Aboves are my vision. I only try to find a better way to implement this issue. I hope it's also useful for everyone. I had hear about ValueObject but not really understand it obviously. I will try to figure it out!

Configurable dynamic Doctrine database entities in Symfony 2

What I am trying to achieve
Users would be able to configure Doctrine entities through an HTML form on a website.
Users would be able to define new entities, as well as add and delete fields for existing entities. (Similar to Drupal's content types)
The Doctrine entities would get dynamic properties based on the configuration that the user supplied through the web UI.
Either the single DB table per Doctrine entity would be altered dynamically whenever an entity configuration changes; Or there could be multiple tables used per single entity (each new entity field would get its own table).
Done so far
I have been researching this for the past few days without much success but I stumbled across this answer which seems quite related to what I am trying to achieve.
I have registered and added the loadClassMetadata listener which maps the field foo:
// src/DynamicMappingTest/AdminBundle/EventListener/MappingListener.php
namespace DynamicMappingTest\AdminBundle\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
class MappingListener
{
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if ($classMetadata->getName() != 'DynamicMappingTest\\AdminBundle\\Entity\\CustomNode')
{
// Not the CustomNode test class. Do not alter the class metadata.
return;
}
$table = $classMetadata->table;
$oldName = $table['name']; // ... or $classMetaData->getTableName()
// your logic here ...
$table['name'] = 'custom_node';
$classMetadata->setPrimaryTable($table);
$reflClass = $classMetadata->getReflectionClass();
dump($reflClass);
// ... or add a field-mapping like this
$fieldMapping = array(
'fieldName' => 'foo',
'type' => 'string',
'length' => 255
);
$classMetadata->mapField($fieldMapping);
}
}
Now, this all works as long as I have the foo property declared in the DynamicMappingTest\AdminBundle\Entity\CustomNode class:
// src/DynamicMappingTest/AdminBundle/Entity/CustomNode.php
namespace DynamicMappingTest\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* CustomNode
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="DynamicMappingTest\AdminBundle\Entity\CustomNodeRepository")
*/
class CustomNode
{
...
private $foo;
}
Problem
However, there is no way for me to know what properties the users will define for their custom entities. If I remove the foo property from the CustomNode class, the ReflectionClass that I get from the ClassMetadata will naturally not include the foo property and so I get the following exception whenever the mapField() in MappingListener is executed:
ReflectionException: Property DynamicMappingTest\AdminBundle\Entity\CustomNode::$foo does not exist
in vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php at line 80
77. */
78. public function getAccessibleProperty($class, $property)
79. {
80. $reflectionProperty = new ReflectionProperty($class, $property);
81.
82. if ($reflectionProperty->isPublic()) {
83. $reflectionProperty = new RuntimePublicReflectionProperty($class, $property);
Questions
Is it possible to have fully configurable dynamic Doctrine entities?
Am I on the right track with my approach? If not, could you suggest an alternative?
How could I have truly dynamic class properties? Or should I be generating new Doctrine entity PHP classes whenever the users change the entity configuration?
Is it possible to have fully configurable dynamic Doctrine entities?
Doctrine generates proxy classes for you entities. That means that doctrine generates PHP code with class, which extends your Entity class and overrides the methods - puts some custom logic and then calls the parent method.
So, I think that the only way to make this really happen is to generate the PHP code for entities in your code. That is, every time entity is created in your website, you should generate PHP file with that entity, then run migrations.
Am I on the right track with my approach? If not, could you suggest an alternative?
I don't think that you should use Doctrine ORM at all in this case, at least in the way you're trying to do that.
Generally, ORM is used for easier/more manageable programming. That is, you can set relations, use lazy-loading, unit of work (change entity properties and then just flush) etc. If your entities are generated dynamically, what features will you use at all? Developer will not write code for these entities, because, as you've said, there is no way to know what fields it will have.
You haven't provided concrete use-case - why do you want to do that in the first place. But I imagine that it could be really done in some easier way.
If users can store any structure at all, should you use MySQL at all? ElasticSearch or similar solutions could be really much better in such cases.
How could I have truly dynamic class properties? Or should I be generating new Doctrine entity PHP classes whenever the users change the entity configuration?
As I've mentioned - yes. Unless you would want to override or replace some of Doctrine code, but I imagine it could be lots of it (proxy classes etc.)

How to generate or modify a PHP class at runtime?

The schmittjoh/cg-library seems what I need, but there is no documentation at all.
This library provides some tools that you commonly need for generating
PHP code. One of it's strength lies in the enhancement of existing
classes with behaviors.
Given A class:
class A {}
I'd like to modify, at runtime of course and with some cache mechanism, class A, making it implementing a given interface:
interface I
{
public function mustImplement();
}
... with a "default" implementation for method mustImplement() in A class.
You can also use a Role Object pattern and good old aggregation.
Instead of having smart Entities that contain all your business logic, you make them dumb and move all the business logic into Roles that aggregate the dumb Entities then. Your behaviors are then first-class citizens living inside the Roles.
Example:
interface BannableUser
{
public function ban();
}
Having an interface with one particular behavior follows the Interface Segregation Principle. It also dramatically increases possible reuse since you are more likely to reuse individual behaviors than an Entity with an application-specific collection of behaviors.
Now to implement that, you create an appropriate Role Class:
class BannableUserRole implements BannableUser
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function ban()
{
$this->user->isBanned = true;
}
}
You still have a User entity but it's completely stripped of all behaviors. It's essentially just a bag of Getters and Setters or public properties. It represents what your System is. It's the data part, not the interaction part. The interaction is inside the Roles now.
class User
{
public $isBanned;
// … more properties
}
Now assuming you have some sort of Web UI, you can do the following in your controller:
class BanUserController implements RequestHandler
{
// …
public function handleRequest(Request $request)
{
$userId = $request->getVar('user_id');
$user = $this->userRepository->findById($userId);
$bannableUser = new BannableUserRole($user);
$bannableUser->ban();
}
}
You can decouple this further by moving the actual lookup of the User and assignment of the Role into a UseCase class. Let's call it Context:
class BanUserContext implements Context
{
public function run($userId)
{
$user = $this->userRepository->findById($userId);
$bannableUser = new BannableUserRole($user);
$bannableUser->ban();
}
}
Now you have all the business logic inside your Model layer and fully isolated from your User Interface. The Contexts are what your system does. Your Controller will only delegate to the appropriate Context:
class BanUserController implements RequestHandler
{
// …
public function handleRequest(Request $request)
{
$this->banUserContext->run($request->getVar('user_id'));
}
}
And that's it. No need for Runkit or similar hackery. The above is a simplified version of the Data Context Interaction architectural pattern, in case you want to further research this.
Note: OP needs PHP 5.3 (it was not tagged that way before), this question is a general outline for PHP 5.4.
You can do that with defining the interface and adding traits that contain the default implementation for those interfaces.
Then you create a new class definition that
extends from your base-class,
implements that interface and
uses the default traits.
For an example, see Traits in PHP – any real world examples/best practices?
You can easily generate that class definition code and either store it and include it or eval it straight ahead.
If you make the new classname containing all the information it consists of (in your case the base classname and the interface), you can prevent to create duplicate class definitions easily.
This works without any PHP extension like runkit. If you bring serialize into the play, you can even overload existing objects at runtime with the new interface in case they can serialize / deserialize.
You can find a code-example that has been implementing this in:
DCI-Account-Example-in-PHP / src / DCI / Casting.php (usage)
I needed a tool to edit PHP classes (specifically Doctrine Entities), I could not find it so I created one that might help you, I documented it heavily. So if you want to give it a try, I'll happily help.
Here it is, SourceEditor
It gives you an API like this:
/* #var $classEditor DocDigital\Lib\SourceEditor\PhpClassEditor */
$classEditor->parseFile($classPath);
$classEditor->getClass('a')->getMethod('b')->addAnnotation('#auth Juan Manuel Fernandez <juanmf#gmail.com>');
$classEditor->getClass('a')->getAttribute('attr')->addAnnotation('#Assert\Choice(...)');
$classEditor->getClass('a')->addAttribute($attr2);
$classEditor->getClass('a')->addUse('use DocDigital\Bundle\DocumentBundle\DocumentGenerator\Annotation as DdMapping;');
$classEditor->getClass('a')->addConst(' const CONSTANT = 1;');
file_put_contents($classPath, $classEditor->getClass('a')->render(false));
Runkit extension can help you
Runkit_Sandbox — Runkit Sandbox Class -- PHP Virtual Machine
Runkit_Sandbox_Parent — Runkit Anti-Sandbox Class
runkit_class_adopt — Convert a base class to an inherited class, add ancestral methods when appropriate
runkit_class_emancipate — Convert an inherited class to a base class, removes any method whose scope is ancestral
runkit_constant_add — Similar to define(), but allows defining in class definitions as well
runkit_constant_redefine — Redefine an already defined constant
runkit_constant_remove — Remove/Delete an already defined constant
runkit_function_add — Add a new function, similar to create_function
runkit_function_copy — Copy a function to a new function name
runkit_function_redefine — Replace a function definition with a new implementation
runkit_function_remove — Remove a function definition
runkit_function_rename — Change the name of a function
runkit_import — Process a PHP file importing function and class definitions, overwriting where appropriate
runkit_lint_file — Check the PHP syntax of the specified file
runkit_lint — Check the PHP syntax of the specified php code
runkit_method_add — Dynamically adds a new method to a given class
runkit_method_copy — Copies a method from class to another
runkit_method_redefine — Dynamically changes the code of the given method
runkit_method_remove — Dynamically removes the given method
runkit_method_rename — Dynamically changes the name of the given method
runkit_return_value_used — Determines if the current functions return value will be used
runkit_sandbox_output_handler — Specify a function to capture and/or process output from a runkit sandbox
runkit_superglobals — Return numerically indexed array of registered superglobals
You can look: https://github.com/ptrofimov/jslikeobject
Author implemented dynamic JS-like objects with support of inheritance.
But it is more like a joke than real proposition.

Categories