Let's say I have a class in PHP with a method that serialises data. Being English, I use the English spelling of -ISE.
class Foo
{
public function serialise($data)
{
return json_encode($data);
}
}
Let's also say that I have an American developer on my team who tries to "serialize" the data (-IZE).
$foo = new Foo();
$foo->serialize(['one', 'two', 'three']);
// PHP Fatal error: Uncaught Error: Call to undefined method Foo::serialize()
The obvious way to solve this is to alias the method. My instincts are to create another method with the American spelling and simply pass the same parameters.
class Foo
{
// ...
public function serialize($data)
{
return $this->serialise($data);
}
}
But this has a couple of downfalls:
I have to match the parameters and remember to update both methods if there's ever an update (error prone).
Additional function call for American developers means the code is less efficient.
Modifying one in a sub-class doesn't necessarily update the other.
My question is: is there a better way to alias a class method in PHP? A way that can get around the concerns that I have?
One way to reduce the maintenance burden is to use the ... operator to accept any number of arguments, and unpack them in the forwarded call:
public function serialize(...$args)
{
return $this->serialise(...$args);
}
The downside is that the function now no longer has a signature which can be auto-completed in editors; you could list the real arguments in a docblock, but that would defeat the point because you'd need to keep it up to date.
The best solution though is probably to have a naming convention, and have everyone learn it, for the same reason as any other coding convention: it's a lot easier to read code which is consistent. Using a good editor or IDE, the wrong spelling will quickly be highlighted and corrected, and there is no additional complexity of maintaining the aliases.
This is achievable using Interfaces and Traits, like so:
SerializeInterface.php (The name 'Serializable' is already used by PHP, so I'm using an unconventional name for an interface here.):
interface SerializeInterface
{
public function serialize($data);
}
SerializeableTrait.php:
require_once('SerializeInterface.php');
trait SerializableTrait
{
public function serialize($data)
{
return json_encode($data);
}
}
Foo.php
require_once('SerializeInterface.php');
require_once('SerializableTrait.php');
class Foo implements SerializeInterface
{
use SerializableTrait;
use SerializableTrait {
SerializableTrait::serialize as serialise;
}
}
$foo = new Foo();
print $foo->serialize(['one', 'two', 'three']).PHP_EOL;
print $foo->serialise(['four', 'five', 'six']).PHP_EOL;
Output of Foo.php:
["one","two","three"]
["four","five","six"]
Some caveats:
Depending on your preference, you might want to switch whether the 's' or the 'z' version of the word is used in the interface and trait vs. as the alias in the class. You'd probably want whichever spelling is going to be more commonly used to be the name in the interface and trait.
This isn't exactly failproof. There is no contract that ensures that the alias used in Foo.php is required. Therefore, the developer must remember to add the alias in each class that implements this interface.
As others have said, it may be better just to rely on standard naming conventions than to do it this way.
With the above caveats being said, this does allow for both spellings to be used and allows for the function to be updated in only one location (in SerializableTrait.php). And it also has the added benefit (relative to the IMSoP's answer using "...$args") that this should still allow for code completion in most editors.
Related
I'm working on something and I've already used some design patterns, but none of them fulfills my needs completely, and that makes me think I might use a combination of patterns, but I'm a little bit stuck so I will explain the situation here and hopefully somebody could add some light about the right way to work on this one. The language I'm working with is PHP 8, in case that it helps or limits on finding a solution.
I have a class that builds, via static methods, GraphQL queries and mutations. I can't give you the exact implementation but it's something like this:
class GraphQLBuilder
{
public static function getSettings(): string
{
return <<<GRAPHQL
query{
settings{
id
name
alias
}
}
GRAPHQL;
}
public static function getSetting(string $id): string
{
return <<<GRAPHQL
query{
setting(id: "$id"){
id
name
alias
}
}
GRAPHQL;
}
public static function setName(string $id, string $name)
{
return <<<GRAPHQL
mutation {
setting(
id: "$id",
name: "$name"
) {
id
name
}
}
GRAPHQL;
}
}
The GraphQL server is migrating to a new version and the field alias will be called aka, but for compatibility reasons they will keep the old field for a year. I need to create a new version of the Builder class that supports the new aka field, so it will have different getSettings() and getSetting($id) methods, but the setName() method will be the same.
My goal is to create a class that works with all the methods used (in the example, getSettings(), getSetting($id) and setName($id, $name)) but fallbacks to a base class for the not implemented methods. I'd use an interface to check that all the methods are covered in the new class.
So far, I've tried to use the strategy pattern by creating a BuilderFactory that returns whether GraphQLBuilder or GraphQLBuilderNewVersion, so the methods could be used at the same way: builder::getSettings(), but that makes me include the setName() method, without any difference, in the GraphQLBuilderNewVersion, and I wouldn't like to do that because I don't want to maintain the same code in different classes.
Another approach was creating an abstract class GraphQLAbstractBuilder that has a static $settingProvider attribute, and a GraphQLBuilderBase that holds all the methods that would be needed to fallback. Both GraphQLBuilder or GraphQLBuilderNewVersion extend from GraphQLBuilderBase and implement their own specific methods, but I'd like that those specific methods are controlled in the interface but they don't have a fallback, so I can make them fail in a controlled way.
I feel like I'm overthinking this and it may be a very straightforward solution, so any advice or tip to make a robust design on this problem will be really appreaciated.
Where can i use and should i use anonymous classes that are presented in PHP 7 ? I can't find a use case for them.
$message = (new class() implements Message {
public function getText() { return "Message"; }});
You can find the information you are looking for here, where the RFC is presented.
The key points of the section "Use cases" are the following:
Mocking tests becomes easy as pie. Create on-the-fly implementations for interfaces, avoiding using complex mocking APIs.
Keep usage of these classes outside the scope they are defined in
Avoid hitting the autoloader for trivial implementations
I also found this useful when writing unit tests for traits so you can test only the trait method i.e.:
trait MyTrait
{
public method foo(): string
{
return 'foo';
}
}
...
public function setUp(): void
{
$this->testObject = (new class() {
use MyTrait;
});
}
public function testFoo(): void
{
$this->assertEquals('foo', $this->testObject->foo());
}
As Rasmus Lerdorf said at WeAreDevelopers See website, when he was talking about new features in PHP7:
(Watch it on YouTube)
Anonymous classes, just like anonymous functions; basically you can spin up classes on-the-fly and throw them away. Personally, I've never had a use for this, but there are framework folks that say that this is important. I'm still a little bit dubious, but it was easy to implement; and people smarter than me have said "Yeah, yeah, it's useful"! OK!
Edit
Considering the quotation above by Mr. Lerdorf, anonymous classes doesn't mean to be really useless.
As an example, it's good for some sort of Singleton patterns, by defining and instantiating the class at the same time.
Or, another example is implementing nested classes with it. See this.
Good case I can provide is to provide context specific listener to use it only once or an adapter for external listener, without defining custom class. Here is an example:
$this-apiCaller->call('api_name', $parameters, new class($businessListener) implements ApiListenerInterface
{
private $listener;
public function __construct($originalListener)
{
$this->listener = $originalListener;
}
public function onSuccess($result)
{
$this->listener->addLog(new SuccessRecord($result));
}
public function onFailure($error)
{
$this->listener->addLog(new ErrorRecord($error));
}
});
Anonymous classes are not different than regular classes in PHP except they need to be created and instantiated at the same time.That means they can be extended from others classes, can use interfaces etc.
If you think you need a very simple class and never use it again in anywhere else, it is right for you. Another reason could be that you need a simple class (with multiple simple methods) and you don't want to spend time for documentation so you create one on the go to achieve your task.
I was trying to find a way to execute some code to alter the results of an objects methods without actually touching the object's code. One way I came up is using a decorator:
class Decorator {
private $object;
public function __construct($object) {
if (!is_object($object)) {
throw new Exception("Not an object");
}
$this->object = $object;
}
protected function doSomething(&$val) {
$val .= "!!";
}
public function __call($name, $arguments) {
$retVal = call_user_func_array(array($this->object, $name), $arguments);
$this->doSomething($retVal);
return $retVal;
}
}
class Test extends BaseTest {
public function run() {
return "Test->run()";
}
}
$o = new Decorator(new Test());
$o->run();
That way it will work properly but it has one disadvantage which makes it unusable for me right now - it would require replacing all lines with new Test() with new Decorator(new Test()) and this is exactly what I would like to avoid - lots of meddling with the existing code. Maybe something I could do in the base class?
One does not simply overload stuff in PHP. So what you want cannot be done. But the fact that you are in trouble now is a big tell your design is flawed. Or if it is not your code design the code you have to work with (I feel your pain).
If you cannot do what you want to do it is because you have tightly coupled your code. I.e. you make use of the new keyword in classes instead of injecting them (dependency injection) into the classes / methods that need it.
Besides not being able to easily swap classes you would also have a gard time easily testing your units because of the tight coupling.
UPDATE
For completeness (for possible future readers): if the specific class would have been namespaced and you were allowed to change the namespace you could have thought about changing the namespace. However this is not really good practice, because it may screw with for example autoloaders. An example of this would be PSR-0. But considering you cannot do this either way I don't see it is possible what you want. P.S. you should not really use this "solution".
UPDATE2
It looks like there has been some overload extension at some time (way way way back), but the only thing I have found about it is some bug report. And don't count on it still working now either way. ;-) There simply is no real overloading in PHP.
Found something (a dead project which doesn't work anymore that enables class overloading): http://pecl.php.net/package/runkit
Possibly another project (also dead of course): http://pecl.php.net/package/apd
I am not a PHP programmer, but I think that AOP is what you are looking for. You can try some frameworks, for example listed in this answer.
From the Wikipedia article on the decorator pattern:
Subclass the original "Decorator" class into a "Component" class
So I think you're supposed to keep the class to be decorated private and expose only the already-decorated class.
Or in more specific words, is it "ok" to not be relying on setters and getters?
I'm dealing with a class that checks the availability of rooms and sets public properties of which there are more than a dozen. Things such as:
unitNumber
roomTypes ( array )
codeCorporate
codeGroup
numberKids
numberAdults
numberRooms
currency
minRate
maxRate
soapServer
units ( array )
hotelId
And after an object is instantiated those properties are set with $this-> inside various methods. However the code that deals with the object often sets public properties directly instead of using getter/setter methods:
$object->something = 3;
foreach ($object->things as $thing ) { }
If I have the time to refactor this class..
Should I stick all of these properties in a data array that's a private property, and define __set and __get methods?
Should I make a single getter method for each of the properties?
In my opinion, it is rarely a good idea to have any public members. It increases coupling between classes, and makes refactoring very complicated (should you need it.)
Setters/Getters are the way to go, and the very small performance penalty that you pay for it is usually either optimized away, or trumped by elegance.
To answer your question about array vs. single-getter-per-var, it's a matter of taste. I tend to only keep variables of a similar type within an array, and separate the rest.
I personally have yet to find a truly good reason for a public property, though im open for suggestion :-)
Although i much prefer specified getters/setters for each property (whether that's a proxy to a generalized get($name) or not). I assume you have other code already that uses direct assignment so in that case i would say to proceed with using the magic __get/__set methods.
I think most people will recommend using setters & getters. Right now you're limited to simply setting & fetching the property, but what if you want to log when that property is accessed? Or perhaps you want to run the value by a validation function first (email, phonenumber, zip code, etc). Maybe you'll need to call another function, or set another property. I think you see where I'm heading with this. By using setters & getters, you add a valuable layer of encapsulation to your classes, and 99% of the time this is worth the extra typing you'll need to do ;) Imagine trying to do the examples above without setters & getters. It'd be a big headache to say the least.
Edit: I forgot to mention Doctrine. It's an object relation mapper (ORM) that can automatically setup setters & getters for you (amongst other things). You can check it out at http://www.doctrine-project.org/
I would take a step back and ask some more general questions:
Why am I having to expose this much information; what is using it and why?
Is this class really just a data structure without behavior, in which case should be a private class to some other class?
Does this class serve a single purpose, or is it on the path to becoming monolithic?
You may discover that you are able to create views of an instance of a class to export to a database, display in a form, etc. Check out the "Builder" and "Acyclic Visitor" patterns to start with.
Regarding accessors, I do not see a need to use them for what you are describing: retrieving class properties and internal state information, aka a struct. However, for attributes of a class I could see the benefit in certain cases, but more for retrieving attributes, not for mutations of your object's state.
If I may add my grain of salt several months later :
It is very un-OO to have public properties. Everything should be encapsulated, simply because (among other reasons) using direct attribute manipulation doesn't give you ways to easily refactor or perform (more) control checks when some external source modifies the field. For example, let's say you have a class with many fields that is used throughout a project several times, and that project contains several thousands of files; it's a project that has been running and expanded for a few years now. Let's say that the company is changing it's business model, or that a problem is found with some of the field's data type and now is required to have some validation; will you duplicate that validation in all those thousands of source code that is directly accessing the public member? In PHP, the solution may be simple, but not in most OO programming language (i.g. Java). The fact is that OO is based on encapsulation. In short, encapsulation doesn't only produce clean code, but also highly maintainable (not to say cost-effective and cohesive) code.
Your suggestion of having a private member (array) being manipulated by __get / __set is good. This way, if you need some extra validation along the road, simply create your setter and/or your getter and it will be the end of it. Some may argue with that being counter productive as the code completion cannot kick-in on __get / __set. IMHO, relying on code completion is simply lazy coding. But then again, having every member have it's own getter and/or setter allows you to write a more comprehensive API documentation. Personally, I usually use that technique for internal or very general purpose classes. If all your fields do not require any validation, or there are as you said several dozen of them, then using magic methods would be acceptable, in my opinion.
The bottom line is to avoid direct member access on class instances, period. How you decide to achieve this is strictly up to you. Just make sure that the API is well documented the more abstract you make it.
On a final note, in PHP, if you already have classes that are being used that are not encapsulating their fields, for example something like
class SomeObject {
public $foo;
public $bar;
public $baz;
//...
}
you can simply fix this class without having to refactor anything with something like :
class SomeObject {
private $_foo; // having underscore as prefix helps to know what's private/protected
private $_bar; // inside the code.
private $_baz;
public function __get($name) {
$methodName = 'get'.ucfirst($name);
if (method_exists($this, $methodName)) {
return $this->{$methodName}();
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function __set($name, $value) {
$methodName = 'set'.ucfirst($name);
if (method_exists($this, $methodName)) {
$this->{$methodName}($value);
} else {
throw new Exception("Method '{$methodName}' does not exist");
}
}
public function getFoo() { return $this->_foo; }
public function setFoo($value) { $this->_foo = $value; }
public function getBar() { return $this->_bar; }
public function setBar($value) { $this->_bar = $value; }
public function getBaz() { return $this->_baz; }
public function setBaz($value) { $this->_baz = $value; }
}
And then
$obj = new SomeObject();
$obj->foo = 'Hello world'; // legacy code support
$obj->setFoo('Hello world'); // same thing, but preferred
And you satisfy both the OO paradigm and having direct access to attributes of an instance. You could also have __call() check for prefix 'get' or 'set' and call __get() and __set() accordingly, but I would not go that far, though this would truly enable general purpose classes to access it's private members via ->member and ->getMember()/->setMember()
(This question uses PHP as context but isn't restricted to PHP only. e.g. Any language with built in hash is also relevant)
Let's look at this example (PHP):
function makeAFredUsingAssoc()
{
return array(
'id'=>1337,
'height'=>137,
'name'=>"Green Fred");
}
Versus:
class Fred
{
public $id;
public $height;
public $name;
public function __construct($id, $height, $name)
{
$this->id = $id;
$this->height = $height;
$this->name = $name;
}
}
function makeAFredUsingValueObject()
{
return new Fred(1337, 137, "Green Fred");
}
Method #1 is of course terser, however it may easily lead to error such as
$myFred = makeAFredUsingAssoc();
return $myFred['naem']; // notice teh typo here
Of course, one might argue that $myFred->naem will equally lead to error, which is true. However having a formal class just feels more rigid to me, but I can't really justify it.
What would be the pros/cons to using each approach and when should people use which approach?
Under the surface, the two approaches are equivalent. However, you get most of the standard OO benefits when using a class: encapsulation, inheritance, etc.
Also, look at the following examples:
$arr['naem'] = 'John';
is perfectly valid and could be a difficult bug to find.
On the other hand,
$class->setNaem('John');
will never work.
A simple class like this one:
class PersonalData {
protected $firstname;
protected $lastname;
// Getters/setters here
}
Has few advantages over an array.
There is no possibility to make some typos. $data['firtsname'] = 'Chris'; will work while $data->setFirtsname('Chris'); will throw en error.
Type hinting: PHP arrays can contain everything (including nothing) while well defined class contains only specified data.
public function doSth(array $personalData) {
$this->doSthElse($personalData['firstname']); // What if "firstname" index doesn't exist?
}
public function doSth(PersonalData $personalData) {
// I am guaranteed that following method exists.
// In worst case it will return NULL or some default value
$this->doSthElse($personalData->getFirstname());
}
We can add some extra code before set/get operations, like validation or logging:
public function setFirstname($firstname) {
if (/* doesn't match "firstname" regular expression */) {
throw new InvalidArgumentException('blah blah blah');
}
if (/* in debbug mode */) {
log('Firstname set to: ' . $firstname);
}
$this->firstname = $firstname;
}
We can use all the benefits of OOP like inheritance, polymorphism, type hinting, encapsulation and so on...
As mentioned before all of our "structs" can inherit from some base class that provides implementation for Countable, Serializable or Iterator interfaces, so our structs could use foreach loops etc.
IDE support.
The only disadvantage seems to be speed. Creation of an array and operating on it is faster. However we all know that in many cases CPU time is much cheaper than programmer time. ;)
After thinking about it for some time, here's my own answer.
The main thing about preferring value objects over arrays is clarity.
Consider this function:
// Yes, you can specify parameter types in PHP
function MagicFunction(Fred $fred)
{
// ...
}
versus
function MagicFunction(array $fred)
{
}
The intent is clearer. The function author can enforce his requirement.
More importantly, as the user, I can easily look up what constitutes a valid Fred. I just need to open Fred.php and discover its internals.
There is a contract between the caller and the callee. Using value objects, this contract can be written as syntax-checked code:
class Fred
{
public $name;
// ...
}
If I used an array, I can only hope my user would read the comments or the documentation:
// IMPORTANT! You need to specify 'name' and 'age'
function MagicFunction(array $fred)
{
}
Depending on the UseCase I might use either or. The advantage of the class is that I can use it like a Type and use Type Hints on methods or any introspection methods. If I just want to pass around some random dataset from a query or something, I'd likely use the array. So I guess as long as Fred has special meaning in my model, I'd use a class.
On a sidenote:
ValueObjects are supposed to be immutable. At least if you are refering to Eric Evan's definition in Domain Driven Design. In Fowler's PoEA, ValueObjects do not necessarily have to be immutable (though it is suggested), but they should not have identity, which is clearly the case with Fred.
Let me pose this question to you:
What's so different about making a typo like $myFred['naem'] and making a typo like $myFred->naem? The same issue still exists in both cases and they both error.
I like to use KISS (keep it simple, stupid) when I program.
If you are simply returning a subset of a query from a method, simply return an array.
If you are storing the data as a public/private/static/protected variable in one of your classes, it would be best to store it as a stdClass.
If you are going to later pass this to another class method, you might prefer the strict typing of the Fred class, i.e. public function acceptsClass(Fred $fredObj)
You could have just as easily created a standard class as opposed to an array if it is to be used as a return value. In this case you could care less about strict typing.
$class = new stdClass();
$class->param = 'value';
$class->param2 = 'value2';
return $class;
A pro for the hash: It is able to handle name-value combinations which are unknown at design time.
When the return value represents an entity in your application, you should use an object, as this is the purpose of OOP. If you just want to return a group of unrelated values then it's not so clear cut. If it's part of a public API, though, then a declared class is still the best way to go.
Honestly, I like them both.
Hash arrays are way faster than making objects, and time is money!
But, JSON doesn't like hash arrays (which seems a bit like OOP OCD).
Maybe for projects with multiple people, a well-defined class would be better.
Hash arrays might take more CPU time and memory (an object has a predefined amount), though its hard to be sure for every scenario.
But what really sucks is thinking about which one to use too much. Like I said, JSON doesn't like hashes. Oops, I used an array. I got to change a few thousand lines of code now.
I don't like it, but it seems that classes are the safer way to go.
The benefit of a proper Value Object is that there's no way to actually make an invalid one and no way to change one that exists (integrity and "immutability"). With only getters and type hinting parameters, there's NO WAY to screw it up in compilable code, which you can obviously easily do with malleable arrays.
Alternatively you could validate in a public constructor and throw an exception, but this provides a gentler factory method.
class Color
{
public static function create($name, $rgb) {
// validate both
if ($bothValid) {
return new self($name, $rgb);
} else {
return false;
}
}
public function getName() { return $this->_name; }
public function getRgb() { return $this->_rgb; }
protected function __construct($name, $rgb)
{
$this->_name = $name;
$this->_rgb = $rgb;
}
protected $_name;
protected $_rgb;
}
I have worked with OOP Languages over 10 years.
If you understand the way objects work you will love it.
Inheritance, Polymorphism, Encapsulation, Overloading are the key advantage of OOP.
On the other hand when we talk about PHP we have to consider that PHP isn't a full featured Object Oriented language.
For example we cant use method overloading or constructor overloading (straightforward).
Associative arrays in PHP is a VERY nice feature but i think that harms php enterprise applications.
When you write code you want to get clean and maintainable application.
Another think that you loose with Associative arrays is that you can't use intellisense.
So i think if you want to write cleanner and more maintainable code you have to use the OOP features when it is provided.
I prefer to have hard-coded properties like in your second example. I feel like it more clearly defines the expected class structure (and all possible properties on the class). As opposed to the first example which boils down to just always remembering to use the same key names. With the second you can always go back and look at the class to get an idea of the properties just by looking at the top of the file.
You'll better know you're doing something wrong with the second one -- if you try to echo $this->doesntExist you'll get an error whereas if you try to echo array['doesntExist'] you won't.