multiple phalcon projects handler


Dec '16

Dec '16

2

340

0


talal424
438
edited Jan '17
Dec '16

if you like making projects using phalcon as i do

and when you have multiple projects with similar structure

its going to be a nightmare when make changes to the structure

you end up with editing all your projects over and over

thats why this would come in handy

you can find this on Github here

hope this can benefit some people and sorry for my bad-ish English

Directory structure:

  • www
    • Phalconproject1
    • Phalconproject2
    • Phalconproject3
    • Phalconproject4
    • phalcon_lib ( our handler location - can be renamed )
      • PhalconBootstrapper.php
      • Traits
        • PhalconDirs.php
        • PhalconFiles.php
        • PhalconNamespaces.php
        • PhalconServices.php
        • PhalconClasses.php

changes to app/config/services.php

you can remove all services except Phalcon\config for example:

<?php

$di->setShared('config', function () {
    $config = include APP_PATH . "/config/config.php";
    defined('BASE_URI') || define('BASE_URI', $config->application->baseUri);
    return $config;
});

changes to app/config/loader.php

the should contain only these lines:

<?php
$loader = new \Phalcon\Loader();

/**
 * We're a registering a set of directories taken from the configuration file
 */

// this is very important the path to our PhalconBoot
defined('LIB_PATH') || define('LIB_PATH', BASE_PATH . '/../phalcon_lib/');

$loader->registerNamespaces(
    [
        // define and register the namespace so we start
        "PhalconBoot" =>   LIB_PATH,
    ]
)->register();

$PhalconBoot = new PhalconBoot\PhalconBootstrapper($di,new \Phalcon\Loader,'MyAppName');

phalcon_lib/PhalconBootstrapper.php

<?php

namespace PhalconBoot;

use Phalcon\DiInterface;
use Phalcon\Loader;
use Phalcon\Config;
use PhalconBoot\Traits\PhalconServices;
use PhalconBoot\Traits\PhalconNamespaces;
use PhalconBoot\Traits\PhalconDirs;
use PhalconBoot\Traits\PhalconFiles;

class PhalconBootstrapper {

    use PhalconNamespaces;
    use PhalconDirs;
    use PhalconFiles;
    use PhalconServices;

    private $appName;

    /**
     * Start the Booting
     *
     * @param  Phalcon\DiInterface  $di
     * @param  Phalcon\Loader  $loader
     * @param  string  $appName
     * @return void
     */
    public function __construct(DiInterface $di, Loader $loader, $appName = null) {
        // get Phalcon\Config service
        $config = $di->getConfig();
        // set an uid for the app or use basefolder name as an app name
        $this->appName = is_null($appName) ? str_replace('/', '', $config->application->baseUri) : $appName;
        // register namespaces
        $this->registerNamespaces($loader,$config);
        // register directories
        $this->registerDirs($loader,$config);
        // register files
        $this->registerFiles($loader,$config);
        // register classes
        $this->registerClasses($loader,$config);
        // inject services
        $this->injectServices($di);
        // load composer (optional)
        $this->loadComposer();
    }
    /**
     * Start the namespaces register
     *
     * @param  Phalcon\Loader  $loader
     * @param  Phalcon\Config  $config
     * @return void
     */
    private function registerNamespaces(Loader $loader, Config $config)
    {
        // register common namespaces for all apps
        $loader->registerNamespaces($this->commonNamespaces($config),true);
        // check if there is a namespace method for the current app
        if (method_exists($this,$this->appName . 'Namespaces')) {
            // register the namespaces for the current app
            $loader->registerNamespaces($this->{$this->appName . 'Namespaces'}($config),true);
        }
    }
    /**
     * Start the directories register
     *
     * @param  Phalcon\Loader  $loader
     * @param  Phalcon\Config  $config
     * @return void
     */
    private function registerDirs(Loader $loader, Config $config)
    {
        // register common directories for all apps     
        $loader->registerDirs($this->commonDirs($config),true);
        // check if there is a directory method for the current app
        if (method_exists($this,$this->appName . 'Dirs')) {
            // register the directories for the current app
            $loader->registerDirs($this->{$this->appName . 'Dirs'}($config),true);
        }
    }
    /**
     * Start the files register
     *
     * @param  Phalcon\Loader  $loader
     * @param  Phalcon\Config  $config
     * @return void
     */
    private function registerFiles(Loader $loader, Config $config)
    {
        // register common files for all apps
        $loader->registerFiles($this->commonFiles($config),true);
        // check if there is a file method for the current app
        if (method_exists($this,$this->appName . 'Files')) {
            // register the files for the current app
            $loader->registerFiles($this->{$this->appName . 'Files'}($config),true);
        }
    }
    /**
     * Start the class register
     *
     * @param  Phalcon\Loader  $loader
     * @param  Phalcon\Config  $config
     * @return void
     */
    private function registerClasses(Loader $loader, Config $config)
    {
        $loader->registerClasses($this->commonClasses($config),true);
        if (method_exists($this,$this->appName . 'Classes')) {
            $loader->registerClasses($this->{$this->appName . 'Classes'}($config),true);
        }
        // last step is to register all our previous work (namespaces, directories and files)
        $loader->register();
    }
    /**
     * Start the services injection
     *
     * @param  Phalcon\DiInterface  $di
     * @return void
     */
    protected function injectServices(DiInterface $di)
    {
        // start looking for services to inject
        foreach (get_class_methods($this) as $method) {
            // do checks on method name if this is a service and if can be run on this app
            if (!$service = $this->checkIfCanRun($method)) {
                continue;
            }
            // get the anonymous function
            $function = $this->{$method}();
            // finally inject the service
            $di->setShared($service,$function);
        }
    }
    /**
     * checks if method is a service and can be run on this app
     *
     * @param  string  $method
     * @return boolean
     */
    private function checkIfCanRun($method = null)
    {
        // i used a pre 3 underscores to identify services to be injected
        $methodIsService = strpos($method, '___') === 0 ? true : false;
        if (!$methodIsService) {
            return false;
        }
        // is it common but not for this app ?
        if (($index = strpos($method, 'NotFor')) > 4) {
            // is it not for this app ?
            if (strpos($method, $this->appName) === 4) {
                return false;
            }
            // it is common and this app is not restricted
            return substr($method,3,$index - 3);
        }
        // is it exclusive for an app ? and is it for this app ?
        if (strpos($method, 'OnlyFor') > 4 && strpos($method, $this->appName === false)) {
            return false;
        }
        // if the method bypasses all filters then it can be run
        // remove all identifying text so we can use it as a service name
        return str_replace(['___','OnlyFor',$this->appName], '', $method);
    }

    private function loadComposer()
    {
        // uncomment and change the path to composer vendor dir
        //require LIB_PATH . 'vendor/autoload.php';
    }
}

phalcon_lib/Traits/PhalconDirs.php

<?php
namespace PhalconBoot\Traits;

use Phalcon\Config;

trait PhalconDirs
{
    /**
     * Common directories register for all apps
     *
     * @param  Phalcon\Config  $config
     * @return array
     */
    private function commonDirs(Config $config)
    {
        return [
            $config->application->controllersDir,
            $config->application->modelsDir,
            $config->application->libraryDir,
        ];
    }
    /**
     * Example for an app named (SomeApp) specific directory register
     *
     * @param  Phalcon\Config  $config
     * @return array
     */
    private function SomeAppDirs(Config $config)
    {
        return [
            'some/namespace/path/to/dir/',
        ];
    }
}

phalcon_lib/Traits/PhalconFiles.php

<?php

namespace PhalconBoot\Traits;

use Phalcon\Config;

trait PhalconFiles
{
    /**
     * Common files registery for all apps
     *
     * @return array
     */
    private function commonFiles(Config $config)
    {
        return [
            // don't forget to change this
            LIB_PATH . 'Tools/Helpers.php'
        ];
    }
    /**
     * Example for an app named (SomeApp) specific file registery
     *
     * @return array
     */
    private function SomeAppFiles(Config $config)
    {
        return [
            'some/namespace/path/to/src/file.php'
        ];
    }
}

phalcon_lib/Traits/PhalconServices.php

<?php
namespace PhalconBoot\Traits;

use Phalcon\Filter;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Php as PhpEngine;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Session\Adapter\Files as SessionAdapter;


trait PhalconServices
{
    /**
     * Example for an app named (SomeApp)
     * service name: someservice
     * class name: someClass
     *
     * @return function
     */
    private function ___someserviceOnlyForSomeApp()
    {
        return function () {
            return new someClass();
        };
    }
    /**
     * Example for all apps except (SomeApp)
     *
     * @return function
     */
    private function ___routerNotForSomeApp()
    {
        return function () {
            require APP_PATH . '/config/routes.php';
            return $router;
        };
    }

    /**
     * Examples for all apps
     *
     * @return function
     */
    private function ___url()
    {
        return function () {
            $config = $this->getConfig();

            $url = new UrlResolver();
            $url->setBaseUri($config->application->baseUri);

            return $url;
        };
    }

    private function ___view()
    {
        return function () {
            $config = $this->getConfig();
            $view = new View();
            $view->setDI($this);
            $view->setViewsDir($config->application->viewsDir);
            $view->registerEngines([
                '.phtml' => PhpEngine::class
            ]);
            return $view;
        };
    }

    private function ___db()
    {
        return function () {
            $config = $this->getConfig();
            $class = 'Phalcon\Db\Adapter\Pdo\\' . $config->database->adapter;
            return new $class([
                'host'     => $config->database->host,
                'username' => $config->database->username,
                'password' => $config->database->password,
                'dbname'   => $config->database->dbname,
                'charset'  => $config->database->charset
            ]);
        };
    }

    private function ___session()
    {
        // using app name as unique id for sessions
        $appName = $this->appName;
        return function () use ($appName) {
            $session = new SessionAdapter(["uniqueId" => $appName]);
            $session->start();
            return $session;
        };
    }

    private function ___filter()
    {
        return function () {
            return new Filter;
        };
    }
}

phalcon_lib/Traits/PhalconNamespaces.php

<?php
namespace PhalconBoot\Traits;

use \Phalcon\Config;

trait PhalconNamespaces
{
    /**
     * Common namespace register
     *
     * @param  Phalcon\Config  $config
     * @return array
     */
    private function commonNamespaces(Config $config)
    {
        return [
            'Carbon'  =>   LIB_PATH . 'vendor/nesbot/carbon/src/Carbon/',
        ];
    }
    /**
     * Example for an app named (SomeApp) specific namespace register
     *
     * @param  Phalcon\Config  $config
     * @return array
     */
    private function SomeAppNamespaces(Config $config)
    {
        return [
            'SomeNamespace'   =>   'some/namespace/path/to/src/',
        ];
    }
}

phalcon_lib/Traits/PhalconClasses.php

<?php
namespace PhalconBoot\Traits;

use \Phalcon\Config;

trait PhalconClasses
{
    /**
     * Common classes loader
     *
     * @param  Phalcon\Config  $config
     * @return array
     */
    private function commonClasses(Config $config)
    {
        return [
        ];
    }

    /**
     * Example for an app named (SomeApp) specific classes register
     *
     * @param  Phalcon\Config  $config
     * @return array
     */
    private function SomeAppClasses(Config $config)
    {
        return [
            'PHPExcel' => LIB_PATH . 'PHPExcel/PHPExcel.php',
        ];
    }
}

Thien
32.6k

Thanks :)

Nice, worth to try.

Thanks.