Download the PHP package nicmart/building without Composer
On this page you can find all versions of the php package nicmart/building. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download nicmart/building
More information about nicmart/building
Files in nicmart/building
Package building
Short Description A PHP library that abstracts the definition of fluent builders.
License MIT
Informations about the package building
Building
Building is, more than a library, a suggestion on how to model fluent builders in your php code.
What is a fluent builder
Building the object graph of the instances of your object model requires often hard to read lines of code, with a lot of nested instantiations and method calls.
In that case you can benefit from a Fluent Builder, adding an easy-to-read and easy-to-write separate API on top of your object API.
The builder offers an alternative API for the construction of your objects, and its fluent interface helps the code to be readable and more DSL-oriented.
How Building works
The approach of this library is using nested builders to define complex objects, and the key point is passing a "finalizing callback", from the parent builder to the child one, that will be called by the child builder when the subvalue has been built.
This decouples completely the child builder from the parent: the responsability of what to do with the builded object lies completely on the parent builder.
A simple example
Let's see now a little example which explains how to define a builder for boolean predicates. The example is really simple and it could be improved a lot, but it is fine for our purpose.
You have atomic predicates, like equalities and inequalities, and composite ones, like ANDS and ORS:
The expression
will be represented in your model by the code
Let's now define a builder for our predicates.
A builder implements the interface NicMart\Building\Builder
, and in the library you can
find an abstract class, NicMart\Building\AbstractBuilder
, that implements the methods of
that interface for you.
A Builder, as you can see by the interface, does exactly two things: it provides a way to
set a callback and implements an end()
method that will be called by the client code
when the building of the object has ended. The end()
method will call the callback and returns
the returned value.
In this way the builder's responsability is only to build the value, and it delegates completely to the parent builder (calling the callback passed by the parent builder) the responsability to deal with the just builded subvalue.
Going back to our example will clarify the process.
We can now use the builder to define our predicate in a way closer to the domain of boolean expressions:
The last end()
automatically returns the builded object because, by default,
the abstract builder class sets for itself a callback that returns
the builded value.
Other examples
For testing purposes I have included an ArrayBuilder and an ObjectBuilder in the repository.
Drawbacks
You have to be aware of some drawbacks of fluent interfaces and method chaining in general:
- Code completion: although there is no use of magic methods, the specific builder type returned by the
end()
is known only at runtime, so IDES fail to autocomplete builder methods after anend()
. - You often violate the Law Of Demeter when using nested builders.
- Marco Pivetta thinks that fluent interfaces are evil. There are a lot of good points there, but I think that the concept of "Contract" expressed there is much more restrictive than the language itself (or, better, the phpdoc type system) can ensure.
Bibliography
- Domain Specific Languages - Martin Fowler (chapters 32-35)
Install
The best way to install Building is through composer.
Just create a composer.json file for your project:
Then you can run these two commands to install it:
$ curl -s http://getcomposer.org/installer | php
$ php composer.phar install
or simply run composer install
if you have have already installed the composer globally.
Then you can include the autoloader, and you will have access to the library classes: