Witchcraft for PHP
There are two kinds of people. Those who like their accessors and mutators to start with get
and set
. This is also what PHP-FIG seems to suggest.
$unicorn = new Unicorn();
$unicorn->setBirthday("1930-24-12")->setColor("rainbow");
print $unicorn->getAge();
It works well with IDE autocompletion. It is also easy to write API documentation using PHPDoc. Then there are those like me who prefer to leave get
and set
out.
$unicorn = new Unicorn();
$unicorn->birthday("1930-24-12")->color("rainbow");
print $unicorn->age();
Or sometimes even access them as properties.
$unicorn = new Unicorn();
$unicorn->birthday = "1930-24-12";
$unicorn->color = "rainbow";
print $unicorn->age;
The usual way
You have your usual class with boilerplate accessors and mutators.
class Unicorn
{
private $color;
private $birthday;
public function __construct($color = "white", $birthday = null)
{
$this->color = $color;
$this->birthday = $birthday;
}
public function getColor()
{
return $this->color;
}
public function setColor($color)
{
$this->color = $color;
return $this;
}
public function getBirthday()
{
return $this->birthday;
}
public function setBirthday($birthday)
{
$this->birthday = DateTime::createFromFormat("Y-m-d", $birthday);
return $this;
}
public function getAge()
{
$now = new DateTime();
return $this->birthday->diff($now)->format("%y years");
}
}
It all works really nice with ide autocompletes and everything. Problem is code looks ugly. Yes, it is matter of taste. My taste might be different than yours.
$unicorn = new Unicorn();
$unicorn->setBirthday("1930-24-12")->setColor("rainbow");
print $unicorn->getAge();
Magic methods
Witchcraft to the resque. It implements opionated PHP magic methods as traits. If you add Witchcraft\MagicMethods
trait you can use pretty methods.
class Unicorn
{
use \Witchcraft\MagicMethods;
private $color;
private $birthday;
...
}
$unicorn = new Unicorn();
$unicorn->birthday("1930-24-12")->color("rainbow");
print $unicorn->age();
HEADS UP! You still must write the boilerplate methods. Witchcraft just enables accessing them as properties.
Magic properties
If you add Witchcraft\MagicProperties
trait you can use pretty properties.
class Unicorn
{
use \Witchcraft\MagicProperties;
private $color;
private $owner;
...
}
$unicorn = new Unicorn();
$unicorn->birthday = "1930-24-12";
$unicorn->color = "rainbow";
print $unicorn->age;
HEADS UP! You still must write the boilerplate methods. Witchcraft just enables accessing them as properties.
Third party code
You can even use it with third party code. However it will work only if the library has properly implemented mutators and accessors. Let’s take League\Url as an example. I love it. It is just all the get
and set
which make my eyes bleed.
Example from League website looks like following.
use League\Url\Url;
$url = Url::createFromUrl(
"http://user:pass@www.example.com:81/path/index.php?query=toto+le+heros#top"
);
$query = $url->getQuery();
$query->modify(array("query" => "lulu l'allumeuse", "foo" => "bar"));
$query["sarah"] = "o connors";
$url->setScheme("ftp");
$url->setFragment(null);
$url->setPort(21);
$url->getPath()->remove("path/index.php");
$url->getPath()->prepend("mongo db");
echo $url . PHP_EOL;
/* ftp://user:pass@www.example.com:21/mongo%20db?query=lulu%20l%27allumeuse&foo=bar&sarah=o%20connors */
To use Witchcraft I extend the original class and add the traits.
use League\Url\Url;
Class MagicUrl extends Url
{
use \Witchcraft\MagicMethods;
use \Witchcraft\MagicProperties;
}
With magic in place above example code can become like below.
$url = MagicUrl::createFromUrl(
"http://user:pass@www.example.com:81/path/index.php?query=toto+le+heros#top"
);
$query = $url->query();
$query->modify(array("query" => "lulu l'allumeuse", "foo" => "bar"));
$query["sarah"] = "o connors";
$url->scheme("ftp");
$url->fragment(null);
$url->port(21);
$url->path->remove("path/index.php");
$url->path->prepend("mongo db");
echo $url . PHP_EOL;
/* ftp://user:pass@www.example.com:21/mongo%20db?query=lulu%20l%27allumeuse&foo=bar&sarah=o%20connors */
WARNING! Use Witchcraft on third party code only if you know what you are doing. It can break things. For example when the library already uses magic methods. Check the source first.
Install
You can install latest version using composer. You can also find the source in GitHub.
$ composer require tuupola/witchcraft