Download the PHP package giuseppe-mazzapica/faber without Composer

On this page you can find all versions of the php package giuseppe-mazzapica/faber. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package faber

Faber

A WordPress-specific dependency injection container that doesn't suck at factoring objects.


It is mainly inspired to Pimple, but allows easier object instances creation.

It is not a full-working plugin, it is a library to be embedded in larger projects via Composer.

As Pimple (and other DI containers), Faber manages two different kind of data: services and properties.

Properties are variables stored "as they are", that is possible to retrieve when needed.

Services are objects that are used in different part of the application, and when they are required again and again, same instance is returned. Services are registered via factory closures: they are anonymous functions that return instances of objects.

Faber also implements factory pattern: is possible to use registered factory closures to obtain always fresh, vanilla instances of objects.


Travis Status

How it Works

Requirements, Installation and License


Create Container Instance

Before being able to do anything, an instance of container is needed. There are two ways: the static way and the dynamic one.

Static Instantiation: The instance() Method

First way to create an instance of the container is to use the static instance() method:

The argument passed to instance method is the ID of the instance: is possible to create any number of instances passing different IDs, they will be completely isolated one from another:

Benefit of this approach is simple: once having a container is useless if it isn't accessible from any part of application, using this method is possible to access container from anywhere in the app by calling the instance() method again and again.

Note that the instance() method has an alias: i():

Dynamic Instantiation

Instances of container can be also created using canonical way:

When instantiated like so, a method to retrieve container instance should be arranged, maybe using a global variable:

Init Hook

No matter the method used to instantiate the container, when an instance is created, an action hook is fired: "faber_{$id}_init". The $id part is the instance ID.

When container is instantiated using dynamic method, to pass an ID is optional, but when no ID is passed to constructor an unique ID is automatically created, it isn't predictable, but can be retrieved using getId() method.

However, when one plans to use the init hook and dynamic instantiation, is probably preferable to pass an ID to constructor like so:

The ID is the second argument, because first is an array of properties / services to be registered during instance creation.

Init hook can be used to add properties and services to container, because it passes the just-created container instance as argument to hooking callbacks:

Registering and Getting Services

Having an instance of container, is possible to register services to be used everywhere in app code.

A service is an object that does something as part of a larger system.

Services are defined by closures (anonymous functions) that return an instance of an object:

Things to note in previous code:

To get registered services is possible to use array access:

or, as alternative, the container get() method:

Services are cached, it means that when same service is required after first time, same instance is returned:

Objects with Arguments

Sometimes classes require some arguments to be instantiated, and these arguments vary from instance to instance.

An example:

Actually, this is not a service, however it's an object that needs a variable argument ($id) and a service ($options).

Whereas the service fits perfectly workflow explained above (an instance of Options can be saved in the container and passed to Post) is not possible to do the same thing with $id.

This is the limit of a lot of DI containers, but luckily not of Faber.

As example having following definitions

is possible to build some post objects like so:

In short, get() method can be used to pass an array of arguments to factory closure where it is used to generate objects.

When same ID and same arguments are passed to get() method, the same instance is obtained; changing arguments different instances are returned.

Note: in code above the instance of Options passed to Post objects is always the same.

How To Force Fresh Instances

Normally, services are cached: if same arguments are passed to get() method then the same instance is returned.

What if a fresh instance of Post having ID 1 is required even if it has been required before?

The make() is there for the scope:

Get data using "Demeter chain" IDs

Assuming some classes are defined like so

and first class is registered in the container like so:

To get call getResult() method of Baz class, is possible to do something like:

Fine. But (since version 1.1) in Faber is also possible to do:

So is possible to access methods of objects in container by using object assigment operator (->) to "glue" object IDs and methods to be called in chain.

Registering and Getting Properties

Properties are usually non-object variables that need to be globally accessible in the app. They are registered and retrieved in same way of services:

For properties just like for services, is possible to use add() or array access to register properties and get() or array access to retrieve them.

Additional prop() method can be used to get properties, it returns an error if used with a service ID:

Saving Closures as Properties

When a closure is added to container, by default it's considered a factory closure for a service. To store a closure "as is", treating it as a property, is possible use the protect() method:

Hooks

There are only three hooks fired inside Faber class.

The first is "faber_{$id}_init" explained here.

The other two are filters, and they are:

These filters are fired every time, respectively, a service or a property are retrieved from the container.

The variable $id part is the container instance ID.

The variable $which part is the ID of service / property being retrieved.

First argument they pass to hooking callbacks is the value just retrieved from container. Second argument is the instance of container itself.

Bulk Registering

Instead of registering services one by one using array access or add() method, is possible to register more services (and properties) at once. That can be done in three ways:

Definitions to Constructor

Definitions to load() method

Definitions to loadFile() method

First a definitions file is needed, something like:

and then

Load On Init

An intersting usage of load() and loadFile() methods is combined with the Faber init hook:

It's a simple way to register services keeping code clean and readable.

Updating, Removing, Freezing and Unfreezing

Updating

Once a service or a property is registered, it can be updated using array access or update() method:

Note that a service can be updated only with another service and a protected closure with another closure:

Removing

Once a service or a property is registered, it can be removed using unset() and array access or via remove() method:

Freezing and Unfreezing

Updating and removing definitions can be avoided by freezing them via, guess it, freeze() method.

When frozen, a property or a service can't be updated or removed until unfrozen via unfreeze() method:

Fluent Interface

Methods that set things on container return an instance of the container itself, allowing fluent interface, i.e. chained methods.

Among methods that support this interface there are:

E. g. the following is valid code:

Issers and Info Getters

Conditional Methods AKA Issers

For a better control of application flow and to avoid errors, is reasonable that one wants to check if a specific ID is registered in the container and if it is associated to a property or a factory, if it is frozen, and so on.

To fulfill these needs there are a set of conditional methods ("issers"). They are:

(where $c is an instance of the container, of course)

Info Getters

Sometimes is also desirable to have informations on the current state of a container instance.

There are some getters that provide useful informations:

Cached Objects

Thanks to the fact that factory closures accept arguments, for every factory closures can exist different cached objects. An example:

So there are three cached objects, all related to the factory with ID "foo".

Using following code is possible to prove that objects are cached:

Worth to know that every cached object is stored in the container with an identifier (usually called $key).

This identifier (aka "key") is visible among informations retrieved via $c->getObjectInfo() or $c->getInfo() methods.

It is a long hash string, but predictable if the ID of the factory closure and the array of used arguments are known. In facts, using those informations, object key can be retrieved via getObjectKey() method:

isCachedObject() method can be used with object key to know if a specific object has been cached or not

Freezing and Unfreezing Cached Objects

Up in this page is explained how to freeze and unfreeze factory closures. Faber also allows to freeze and unfreeze specific cached objects: that is possible using same methods with object key instead of factory ID.

Note: when a factory closure is deleted or updated, all the cached objects it has generated are removed, unless specific cached object was frozen.

Example:

Faber has helper method getAndFreeze() that gets an object and also freeze it:

About Serialization

Current versions of PHP have a limitation: can't serialize closures or any variable that contains closures, e. g. array containing closures or objects having closures in properties: trying to serialize them a catchable fatal error is thrown.

Faber is designed to have quite a lot closures as properties, but no errors happen when its instances are serialized, because Faber implements __sleep() and __wakeUp() PHP methods to prevent that.

When an instance of Faber is serialized and then unserialized, the serialized/unserialized object contains only the ID and the hash of original objects, that being strings, bring no problems.

A little sugar: serializing and then unserializing a Faber instance during same request will create an exact clone of original object, because on wake up container state is cloned from saved instance:

Error Handling

Things can go wrong. Every method of Faber can fail, for different reasons.

When it happens, Faber returns an Error object that is a subclass of WP_Error and so can be checked using is_wp_error() function.

The extended WP_Error class used by Faber works well with fluent interface. When using fluent interface everyone of the chained functions can fail and return a WP_Error object, so next method in the chain is called on error object instead of on Faber object.

That's not a problem: the custom error ebject will add an error to its errors storage and then returns itself, so that at the end of the chain an error object is obtained and it has track of every method called on it: debug happiness.


Requirements

Installation

In composer.json require Faber like so:

{
    "require": {
        "php": ">=5.4",
        "giuseppe-mazzapica/faber": "dev-master"
    }
}

License

Faber is released under MIT.


All versions of faber with dependencies

PHP Build Version
Package Version
Requires php Version >=5.4
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package giuseppe-mazzapica/faber contains the following files

Loading the files please wait ....