PHP Classes


Recommend this page to a friend!
  Classes of Devis Lucato   Select   Download  
Role: Documentation
Content type: text/plain
Description: README
Class: Select
Locate classes that provide named services
Author: By
Last change: Update of
Date: 7 days ago
Size: 5,744 bytes


Class file image Download
# Description **Select** is a static **Service Locator** implementation with PHP method ovearloading. It allows to **replace classes** and can be used to **hold components/services**, identified by unique names and automatically exposed with getter methods. _Select_ is designed to be subclassed with a custom class name, as opposed to the common injection through constructors. To replace _Select_ you subclass the main class. For instance: during tests you can either use a different set of definitions (suggested) or use a mocked Service Locator class implementing the same interface _iSelect_. _Service Locator_ is an _Inversion of Control_ pattern, an alternative to _Constructor Injection_ and _Setter Injection_. Each approach has pros and cons, you might want to read [Inversion of Control Containers and the Dependency Injection pattern]( "Inversion of Control Containers and the Dependency Injection pattern") for more details on IoC, Dependency Injection and Service Locators (in the Java world). _Select_ does not require any configuration, it is simple to introduce the feature if required, see `Select::def<*>` API for details. # How to start To start using _Select_ you should extend the original class and set your namespace (optional), choosing a class name such as _SL_, _IOC_, _Manager_ etc. In order to do this create a file, ie _DI.php_ with this code: namespace MyApp; class DI extends \Select { const DEFAULT_NAMESPACE = 'MyApp\\'; static protected $_namespace = self::DEFAULT_NAMESPACE; } or class DI extends Select { const DEFAULT_NAMESPACE = 'MyApp_'; static protected $_namespace = self::DEFAULT_NAMESPACE; } You can also configure the included unit test case (see _data provider_ and _setUp_) with the custom class name, to verify that everything works properly. You might have to create a fixture, see _tests/fixtures/select\_*NS.php_. Notice that subclasses don't need to explicit any interface because _Select_ uses method overloading to catch calls to the stored dependencies. _iSelect_ should be used when replacing _Select_ with a new or fake implementation. # Customising the class methods If you intend to override methods please note that _Select_ uses `func_get_args()` to fetch parameters not explicitly defined in function signatures. To add new methods or rename existing methods, please note that _Select_ uses `__callStatic` to catch `def/ini/set/get<*>` calls. See [`__callStatic` documentation]( "PHP manual") for details. # Inversion of control The main idea is to separate configuration (class names) from implementation (class instantiations and static calls), avoiding hard coded class names, so that they can be replaced by third parties and during tests. _Select_ is an implementation of a Service Locator, a Registry holding classes and services definitions. The first step should be replacing class symbols with class identifiers: $mailer = new Mailer() with: $mailer = Select::create('Mailer') This allows to change the actual class used for the identifier 'Mailer'. You might also want to use _Select_ as a Service Locator, storing dependencies definitions in the container and retrieving them whenever you want. The previous code becomes: Select::defMailer('Mailer') $mailer = Select::getMailer() To keep definitions and uses separated, all the definitions can be stored in a "configuration file", i.e. _definitions.php_, e.g. Select::defMailer('Mailer') Select::defCache('MemCache') Select::defHTTPClient('HTTPClientV2', array('')) Select::defAuthService('AuthService', array('', 636)) etc. Dependencies defined with `Select::def<*>` will not instantiate until they are requested for the first time. However you can also define and instantiate at once if you like: $mailer = Select::iniMailer('Mailer') and Select::iniDB('DBConnector', array('', 3306, 'user', 'password'))->connect() // ... Select::getDB()->disconnect() And you can also postpone a dependency definition after its creation: $logger = Select::create('Logger', '/tmp/app.log') $logger->rotate() Select::setLogger($logger) # Constructors, Singletons, Multitons With regards to the constructor parameters, they can be passed to `Select::def<*>` and to `Select::ini<*>` as an array, after the class name. `Select::create` expects constructor's parameters inline after the class name instead. See the API documentation for details and examples. By default all dependencies defined and/or created with `Select::<def|ini|set><*>` are considered singletons. See the API documentation for multitons. `Select::create` always returns a new object. Constructors are limited to a maximum of 6 parameters, if you need more you shall override `Select::_create`, or perhaps reduce your code complexity ;-) # Notes _Select_ exceptions classes are hard coded, there shouldn't be any reason to replace them. Each error type has a dedicated exception class subclassing `Select_Exception`. Static calls require two lines of code, one to fetch the class name and one for the actual code: $class = Select::getClass('AStaticClass') $class::someMethod() The cost of the abstraction should be in the order of few ms every 1000 instantiations (tested on low spec hw). Have a look at _tests/speed.php_ to test _Select_ on your system. _Select_ requires PHP 5.3+.