We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Borrow Facade design pattern from Laravel

I like the way Laravel use to get service throgh facade design pattern.

    public function isValid($data = null)
    {
        if(SessionFacade::has('auth')) return true;
        if(CookieFacade::has('auth')) {
            $user = Users::findByCookieAuth($this->getCookie());
            if(!$user) return false;
            FlashFacade::success('欢迎'.$user->name.'登录!你上次登录的时间是:'.$user->updated_at);
            //利用cookie实现登录
            EventFacade::fire('auth:login',$user,['remember'=>'on']);
            return true;
        }
        return false;
    }
    private function getCookie()
    {
        $auth = CookieFacade::get('auth')->getValue();
        foreach($auth as $key=>$value){
            $auth[$key]=CryptFacade::decrypt($value);
        }
        return $auth;
    }

To achieve this, I found I could borrow some code from laravel.

 abstract class Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     * @throws \RuntimeException
     */
    public static function getFacadeAccessor()
    {
        throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
    }
    public static function getService()
    {
        return \Phalcon\Di::getDefault()->get(static::getFacadeAccessor());
    }
    public static function __callStatic($method, $args)
    {
        $instance = static::getService();
        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }
        switch (count($args)) {
            case 0:
                return $instance->$method();
            case 1:
                return $instance->$method($args[0]);
            case 2:
                return $instance->$method($args[0], $args[1]);
            case 3:
                return $instance->$method($args[0], $args[1], $args[2]);
            case 4:
                return $instance->$method($args[0], $args[1], $args[2], $args[3]);
            default:
                return call_user_func_array([$instance, $method], $args);
        }
    }
}

Then you can extend this abstract Facade class, like:

 class SessionFacade extends Facade
{
    public static function getFacadeAccessor()
    {
        return 'session';
    }
}

And if you like the autocomplete function provided by PHPStorm, then you could put the file _ide_helper.php in your root path.

namespace {

  exit("This file should not be included, only analyzed by your IDE");
  class SessionFacade extends \Facade{
        /**
         * Gets a session variable from an application context
         * <code>
         * $session->get('auth', 'yes');
         * </code>
         *
         * @param string $index
         * @param mixed $defaultValue
         * @param bool $remove
         * @return mixed
         */
        public static function get($index, $defaultValue = null, $remove = false) {}
        /**
         * Sets a session variable in an application context
         * <code>
         * $session->set('auth', 'yes');
         * </code>
         *
         * @param string $index
         * @param mixed $value
         */
        public static function set($index, $value) {}
        /**
         * Check whether a session variable is set in an application context
         * <code>
         * var_dump($session->has('auth'));
         * </code>
         *
         * @param string $index
         * @return bool
         */
        public static function has($index) {}
        /**
         * Removes a session variable from an application context
         * <code>
         * $session->remove('auth');
         * </code>
         *
         * @param string $index
         */
        public static function remove($index) {}
        /**
         * Destroys the active session
         * <code>
         * var_dump($session->destroy());
         * var_dump($session->destroy(true));
         * </code>
         *
         * @param bool $removeData
         * @return bool
         */
        public static function destroy($removeData = false) {}
    }
}

If you want to expose more functions, just edit this helper file. Do you like this method? Or have better idea?



7.0k

Facade pattern help me understand Why Di is called service container. So that makes me think more clear!

I would strongly recommend making getFacadeAccessor() abstract:

abstract public static function getFacadeAccessor();

You'll be able to find errors much quicker.



7.0k

Yes, this method could be defined as abstract. Like I said the Codes is borrowed from laravel, it just works.

I would strongly recommend making getFacadeAccessor() abstract:

abstract public static function getFacadeAccessor();

You'll be able to find errors much quicker.

Facade pattern help me understand Why Di is called service container. So that makes me think more clear!

OKAY, but what is then actually missing in Phalcon? You have a nice, clean and lean IoC / DI and you can extend / intercept anything you need from there.



7.0k
Accepted
answer

I think this is not about sth missing, this is about sth the framework can provide to make the job easy. Facade pattern is not invented by Laravel guys, but the code above is. And Facade Pattern can be a powerful tool to help coder think more clear about service.

I am just learning to practice some idea, and have found sth good. Just share some idea and want some feedback.

Facade pattern help me understand Why Di is called service container. So that makes me think more clear!

OKAY, but what is then actually missing in Phalcon? You have a nice, clean and lean IoC / DI and you can extend / intercept anything you need from there.