Sounds like something similar (in the intention at least) to doctrine's embedabbles. Did you heard of it ?
Getter Setter Trait-package proposal [Not Laravel specific]
Background
Having worked with PHP for many years, I often felt frustrated when I had to copy & paste getters and setters, just so I could provide the same functionality to certain objects. Lucky PHP's traits has changed that a lot.
Nevertheless, I still often find my self in situations, where I need to provide some of the same getters and setters, throughout my data model objects. For instance, this could be getters and setters for;
- id
- Uuid
- name
- description
- create date
- update date
- deleted date
- path to file
- path to picture
- url
- width
- height
- ...etc
Naturally, I am developing traits for these, so that I do not have to copy & paste code. And this is where I got an idea, to develop a package for such very general getters and setters - one that could grow over time
Proposal
My idea is to start developing a package, which consists of interfaces and traits for general purpose getters and setters. These should aim at making model data objects faster to create, provided that they are that general. The following sections briefly illustrates how a sup-package could look like
The Interfaces - I am aware of something
/**
* PHPDoc not shown...
*/
interface IUuidAware {
// The setter
public function setUuid($id);
// The getter
public function getUuid();
// A default value - if any
public function getDefaultUuid();
// A validator
public function isUuidValid($id);
}
Every interface would be comprised of the same methods; a setter, a getter, a default value getter and a validator. This should allow for a high degree of flexibility
The Traits - Default implementation of interfaces
/**
* Not all implementation shown
*/
trait UuidTrait {
// UUID property
protected $uuid = null;
// The setter
public function setUuid($id){
if($this->isUuidValid($id)){
$this->uuid = $id;
return;
}
throw new InvalidUuidException();
}
// The getter
public function getUuid(){
if(is_null($this->uuid)){
$this->setUuid($this->getDefaultUuid());
}
return $this->uuid;
}
// A default value - if any
public function getDefaultUuid(){
return null; // By default, should always return null - can be overridden!
}
// A validator
public function isUuidValid($id){
// ... not shown ...
}
}
All traits would offer a basic implementation of a given interface. However, the get-default-value method should always be implemented with a return null, to ensure that unwanted default values are not set - concrete implementations should override this behaviour, if needed. Lastly, every trait should also have a corresponding unit test, which must ensure that it's implementation lives up to the promise of the interface.
Example of model data
/**
* Example model data object
*/
class Person implements IUuidAware {
use UuidTrait;
public function getDefaultUuid(){
return Uuid::uuid1(); // example, rhumsaa/uuid package
}
}
In the above minimalistic example, the default value method is overridden and a UUID is automatically generated, if none has been provided. This, however, might not always be needed / wanted. Furthermore, a Person class would most likely be comprised of several traits. Of course, a real Person-class should perhaps have its own dedicated interface, rather than implement several "I-am-aware-interfaces". This being said, the Persons interface could still take advantage of other / multiple smaller interfaces, each describing that common getter / setter functionality.
PHP's magic methods and a bit of PHPDoc magic
Using such traits could perhaps also allow to define some kind of automation-trait, which makes use of the __get() and __set() methods in PHP (http://php.net/manual/en/language.oop5.overloading.php), and automatically make use of the getter and setter method.
$person->uuid = '25769c6c-d34d-4bfe-ba98-e0ee856f3e7a';
echo $person->uuid; // Output the 25769c6c- ... etc
Also, using PHPDoc's "property", at class level, could enable code-hinting in most IDEs (http://www.phpdoc.org/docs/latest/references/phpdoc/tags/property.html).
But...
While the previously stated example(s) might work for me... I do not know how practicable it would be, for other developers. In addition to this, there are some questions I have yet to answer,... some of which perhaps YOU might share your thoughts upon
- Is such a package really needed, could it be beneficial?
- How does multiple interfaces and traits affect the performance of a class / object?
- How would the classification of such sub-packages be - what data-definition / validation / structure standards are going to be followed, and why?
If you have thoughts about this, suggestions, ideas, please share them :)
Please or to participate in this conversation.