Wallogit.com
2017 © Pedro Peláez
JFF php objects observer
Sometimes we need to listen class calling actions, but for example we haven't permissions to edit it., (*1)
Sometimes we have some instance of class only and we can't extend this class. (For example Database class. Instance was created and if we try to create new extend instance - new connection will be created. Or class can be final etc.), (*2)
But functional of this class does not satisfy to our needs., (*3)
For such cases you can use this strange observer ;), (*4)
Install package via composer, (*5)
bash
composer require "ed-fruty/strange-php-observer": "1.0.0", (*6)
For example we have class User with method register($attributes) and we want to add listeners for this method, (*7)
```php <?php, (*8)
use Fruty\Observe\Manager; use Fruty\Observe\Event;, (*9)
class User extends SomeClass { /** * @access public * @param array $attributes * @return bool */ public function register(array $attributes) { return $this->save($attributes); } }, (*10)
// create instance $user = Manager::make('User');, (*11)
// or we can use instance of User extend of class name $instance = new User(); $user = Manager::make($instance);, (*12)
```
All done!
We can use $user as previously, (*13)
php
$user->register(array('username' => 'root'));
Ok, now we want to add validation before register, (*14)
```php $user()->before('register', function(Event $event) { // validate data // get method arguments $params = $event->getParams();, (*15)
//... some validation logic
// for abort calling register method (if validation is failed) use
$event->stopPropagation();
// for setting some return value
$event->setResult("Validation errors");
}); ```, (*16)
And we want to send email when registration was successfull, (*17)
```php $user()->after('register', function(Event $event) { if ($event->getResult()) { // in $event->getResult() result of executed method, in our case it is boolean // and if it true - registration was successfull, so send email $email = $event->getParams()[0]['email']; $mailer = new Mailer(); $mailer->body("Congratulations!") ->to($email) ->send(); } });, (*18)
```, (*19)
Now we can use, (*20)
php
$user->register(array('username' => 'root', 'email' => 'root@iam.com'));, (*21)
and before regitration will execute validaion, and after - sending email., (*22)
We can set priorities to the listeners, (*23)
```php, (*24)
$user()->before('register', function(Event $event) { // this code will be executed early than validation // because it have higher priority (Event::PRIORITY_HIGH) }, Event::PRIORITY_HIGH);, (*25)
```, (*26)
Also, we can bind new methods dynamically to the $user, (*27)
```php, (*28)
$user()->bind('updateLastLoginTime', function($userId) { //code });, (*29)
$user->updateLastLoginTime(5); ```, (*30)
We can redefine existing methods, (*31)
```php, (*32)
$user()->bind('register', function(array $attributes, $setAdminStatus) { if ($setAdminStatus) { $attributes['admin'] = true; } // call parent method return $this(true)->register($attributes); });, (*33)
$user->register(array('username' => 'root', 'email' => 'root@iam.com'), true); ```, (*34)
As you can see, in the code we uses 3 types of calling methods
1. $user->method()
2. $user()->method()
3. $user(true)->method(), (*35)
$user is instanece of Invoker class and call $user->method() remap to the real instance of User class and can be listened$user(true) is real instance of User, calling $user(true)->method() can not be listened$user() is instance of observer to adding new listeners, binding new methods
So, when you bind method, (*36)
$user()->bind('getOne', function($userId)
{
//$this is instance of Invoker, methods will remap to the instance of User and they can be listened
//$this(true) is instance of User, methods cannot be listened
// NOTE!!!
// if you write here $this->getOne() script will call this action again and again, so you must to use
// $this(true)->getOne() to use real User::getOne()
// if you call here
$this->register(); // it will be called and listened
$this(true)->register(); // it will be called but not listened, this is original User::register()
$this->updateLastLoginTime(); // it will be called and listened
$this(true)->updateLastLoginTime(); // Fatal error, calling undefined method User::updateLastLoginTime()
return array('some data');
});
We can add subscriber to the $user calls, (*37)
use Fruty\Observe\Event;
use Fruty\Observe\AbstractSubscriber;
class UserSubscriber extends AbstractSubscriber
{
/**
* This method will call before calling User::register()
*
* @access public
* @static
* @param \Fruty\Observe\Event $event
*/
public static function onBeforeRegister(Event $event)
{
// here code
}
/**
* This method will call after calling User::register()
*
* @access public
* @static
* @param \Fruty\Observe\Event $event
*/
public static function onAfterRegister(Event $event)
{
// here code
}
/**
* We can set priorities to the actions
*
* @access public
* @static
* @return array
*/
public function getPriorities()
{
return array(
'onBeforeRegister' => Event::PRIORITY_HIGHT,
'onAfterRegiter' => Event::PRIORITY_LOW,
);
}
}
// register subscriber
$user()->subscribe('UserSubscriber');
How to check instance ?, (*38)
```php, (*39)
if ($user instanceof User === true) { // Fail. $user is instance of Fruty\Observe\Invoker }, (*40)
if ($user(true) instanceof User) { // Success }, (*41)