简体   繁体   中英

How to alias a class method in PHP?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM