Author: Vallo Reima
Viewers: 474
Last month viewers: 24
Categories: PHP Tutorials
Read this article to learn more about the gateway pattern and how you implement it to access common methods and properties from any part of your PHP application code following the OOP principles, as well how it can be used to implement other well known design patterns.
Contents
Introduction
Property Access Methods
Property Access Path
Other Design Patterns
Conclusion
Introduction
In a previous article it were described 3 Ways to Access Application Common Data in PHP. The Gateway pattern was introduced as one of the 3 ways to access the application's common methods and properties. The methods are called and properties accessed through a single point of the program.
However, there is a risk to improperly access (unintentionally overwrite) the common properties from several parts of the program. Additional methods are described in this article for secured and unified access to the properties.
Modern PHP applications tend to follow the OOP paradigm. Accessing common data in the global scope is not in accordance with the use of the OOP. The gateway pattern implemented by the Gateway class alleviates this problem.
Property Access Methods
Common properties can be implemented via the Gateway class' static variable using property overloading (see previous article). This is convenient but makes difficult to follow the variables changes. A new _() method is added to handle the common properties and the $_ static variable is retained to be used as work area for the time-critical activities:
class ¤ { private static $cmi; /* common instance */ private static $sep; /* path separator */ public static $_; /* workarea */ /** * link to common data * @param string $cln common class name * @param string $sep path separator */ public static function _Init($cln = 'Common', $sep = '.') { self::$cmi = new $cln( self::$_ ); /* instantiate the common class */ self::$sep = $sep; /* save property path separator */ } /** * access a method * @param object $func method name * @param array $args arguments list * @return mixed */ public static function __callStatic( $func, $args ) { return call_user_func_array( array( self::$cmi, $func), $args ); } /** * get/set a property value * @param arguments -- 1st - path string * 2nd - value (set only) * @return mixed get/set value */ public static function _() { $path = trim(func_get_arg(0), self::$sep); /* remove leading / trailing separators */ $pth = explode( self::$sep, $path); /* split the path */ if (func_num_args() > 1) { $value = func_get_arg( 1 ); /* value to set */ self::$cmi->_set($pth, $value); /* set a value */ } else { $value = self::$cmi->_get($pth); /* get a value */ } return $value; } }
¤::_() either gets or sets the property value depending on the number of arguments is 1 or 2 respectively. The first argument specifies the property path. The second argument specifies the value to set.
The Common class supplies the _get() and _set() methods processing the common properties. Do not confuse with __get() and __set() magic methods. See the common.php file for these methods. Maybe you can figure a better algorithm to implement the _get and _set methods.
Property Access Path
The property is identified by the access path. Each path element represents either an object property or associative array element. Thus the path can be a mix of the object property and associative array key names.
The example below demonstrates the using of the common gateway property access path (the dot is used as a path separator and it can be redefined).
<?php include 'gateway.php'; include 'common.php'; define('BR', '<br />'); $ctt = array('phn' => '444555666', 'eml' => 'info@mail.com', /* test data */ 'adr' => (object) array('str' => 'Elm', 'twn' => 'Sunny')); ¤::_Init(); /* instantiate common */ header("Content-Type: text/html; charset=utf-8"); ¤::_('ctt', $ctt); /* set a structured value */ ¤::_('ctt.chd', array('Sally', 'Billy')); /* set an array value */ echo 'Phone: ' . ¤::_('ctt.phn') . BR; /* get a value */ ¤::_('ctt.adr.str', 'Oak'); /* replace a value */ echo 'Street: ' . ¤::_('ctt.adr.str') . BR; /* get a value */ echo 'Town: ' . ¤::_('ctt.adr.twn') . BR; /* get a value */ $c = 'chd';
if (version_compare(PHP_VERSION, '5.4', '<')) { $a = ¤::_("ctt.$c"); /* get a value */ echo 'Child1: ' . $a[0] . BR; } else { echo 'Child1: ' . ¤::_("ctt.$c")[0] . BR; /* array dereferencing */ }
The overloading and dereferencing of values are applicable to the results.
Other Patterns
The Gateway supplies frequently used functions as the methods and commonly needed data as the properties via the static calls. It can also act as the container of the commonly used class instances. There are several patterns to supply the services and handle dependencies. The Gateway approach provides similar functionality.
The Gateway initialization resembles the one used to implement the Singleton pattern, but instantiates the common class instead of itself, and saves the reference. You can modify the _Init() method assure that only one instance is created.
Here is a Service Locator implementation example:
$locator = new ServiceLocator() $locator->set('app', new Application()); $locator->set('db', new Database()); // ... $locator->get('db')->connect(); $locator->get('app')->run();
Compared with the Gateway implementation:
¤::_Init(); ¤::_('app', new Application()); ¤::_('db', new Database()); // ... ¤::_('db')->connect(); ¤::_('app')->run();
The Gateway implementation of the Dependency Injection Container
¤::('usr', new User(new Auth()); //... ¤::('usr')->Login($creds);
The art is to find a balance between using of the common data and the parameter passing.
Conclusion
In a PHP application the core functions must be extended by the custom ones to perform standard actions like for instance data conversions.
It is not very practical to implement all elementary actions as separate classes because it makes the application become too fragmented into many small classes. Gathering all those elementary actions into one class is much more comfortable to develop and maintain, as it makes the application code easier to understand.
The developers are responsible to decide what is a purpose of a class or a function, what data be retrieved from common data containers, and what data is better to pass as the parameters to classes or functions.
The purpose of using solutions like the Gateway pattern is avoid the pain of passing frequently used values to many objects, class methods or functions. In this sense, the gateway approach is a solution that follows OOP paradigm to a great extent as it promotes better encapsulation.
Any method of accessing common data creates dependencies. Professionally design applications do not use or minimize the user of global variables. Furthemore using the Gateway pattern, the dependencies are handled by code implemented in a single point, the gateway class.
If you liked this article or have questions, post a comment here.
You need to be a registered user or login to post a comment
1,616,820 PHP developers registered to the PHP Classes site.
Be One of Us!
Login Immediately with your account on:
Comments:
1. This is great - Yoni Lamri (2015-07-23 19:01)
This is great... - 1 reply
Read the whole comment and replies