2017 © Pedro Peláez
 

project framework

A modern PHP framework built-upon configuration, dependency injection and middlewares.

image

phossa2/framework

A modern PHP framework built-upon configuration, dependency injection and middlewares.

  • Tuesday, October 11, 2016
  • by phossa2
  • Repository
  • 1 Watchers
  • 1 Stars
  • 11 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 1 Versions
  • 0 % Grown

The README.md

phossa2/framework

phossa2/framework is a modern PHP framework built-upon configuration, dependency injection and middlewares., (*1)

It requires PHP 5.4, supports PHP 7.0+ and HHVM. It is compliant with PSR-1, PSR-2, PSR-3, PSR-4, and other proposed PSR standards., (*2)

Create the project

Install via the composer utility., (*3)

# cd installation_dir/
# composer create-project phossa2/framework PROJECT

Directory structure

phossa2/framework is delivered with the single server installation directory structure. It also can be restructured to fit different requirements by modifying directory settings in the .env file., (*4)

  • Single server installation, (*5)

    Default framework distribution is for a single server installation., (*6)

    |--- .env                             the environment file
    +--- PROJECT/                         the project directory
        |--- phossa2                    the utility script
        |--- app/                       app installation dir
        |--- config/                    where all the config files located
        |--- plugin/                    where all the plugins installed
        |--- public/                    where public stuff located
        |      |--- asset/
        |      +--- index.php           single public entry
        |--- runtime/                   runtime related stuff
        |      |--- local/              host-specific storage
        |      |      |--- cache
        |      |      +--- session
        |      +--- log/                log file directory
        |--- system/                    system files
        |      +--- bootstrap.php       bootstrap file
        +--- vendor/                    third-party libs
    
  • Multiple servers installation, (*7)

    The framework can also be installed across multiple servers to provide capabilities such as load balancing, central app managment (NFS mounted) etc., (*8)

    |--- .env                             host-specific environments
    |--- local                            host-specific local storage
    |     |--- cache/
    |     +--- session/
    |
    |--- PROJECT/                         shared among servers (NFS mounted)
    |     |--- phossa2
    |     |--- app/
    |     |--- config/
    |     |--- plugin/
    |     |--- public/
    |     |--- system/
    |     +--- vendor/
    |
    +--- runtime/                         shared runtime stuff (NFS mounted)
        |--- log/host1                  host-specific log dir
        |--- upload/                    upload dir
        +--- static/                    generated static html files
    

Execution path

  • Application execution path, (*9)

    1. public/index.php

    Single app entry point. Load system/bootstrap.php file and then process the app middleware queue defined in config/middleware.php, (*10)

    <?php
    // public/index.php
    
    // Load bootstrap file
    require dirname(__DIR__) . '/system/bootstrap.php';
    
    // execute the main middleware queue
    $response = Service::middleware()->process(
        ServerRequestFactory::fromGlobals(),
        new Response()
    );
    
    1. system/bootstrap.php

    Required by public/index.php or phossa2 utility script. Bootstrap all required stuff, including, (*11)

    • set basic environments., (*12)

    • start autloading., (*13)

    • load other environments from .env file., (*14)

    • start $config and $container which read configs from the config/ directory., (*15)

    1. .env

    Environment file installled at one level upper of PROJECT directory. This file is host specific and may differ on different servers., (*16)

    See phossa2/env and phossa2/config for detail., (*17)

    • To change app environment, (*18)

      Change the value of PHOSSA2_ENV to implement different servers, such as production server, dev server or staging servers., (*19)

    • To restructure the framework, (*20)

      By changing directory settings in this file, user may be able to restructure the framework., (*21)

    1. start $config and $container
    • configure, (*22)

      Configurations are grouped into files and located in the directory config/., (*23)

      See phossa2/config for detail., (*24)

    • container, (*25)

      phossa2/di provides a PSR-11 compliant container implementation built upon phossa2/config., (*26)

      Container objects are configured in config/di.php or scattered in the 'di' section of different files such as config/db.php., (*27)

      A service locator Phossa2\Di\Service is also provided., (*28)

      The container object is available as Service::container(). The configuration object is available as Service::config()., (*29)

      use Phossa2\Di\Service;
      
      $config = Service::config();
      $container = Service::container();
      
      // get the db configuration array
      $db_conf = $config->get('db');
      
      // get the db object
      $db = $container->get('db');
      
      // or get from locator
      $db = Service::db();
      
    1. Process the app middleware queue

    Middlewares are defined in config/middleware.php., (*30)

  • Console script execution path, (*31)

    1. phossa2 utility script

    Single utility entry point. Load system/bootstrap.php file and then process command line arguments, (*32)

    1. Common line arguments

    Common line arguments processed. And then look for controller/action pairs in the 'system/Console/' and 'app/Console/' directories for specific actions., (*33)

Configuration driven framework

phossa2/framework is a configruation driven framework. Most of the objects, utilities are defined in config files under the config/ directory. Objects are generated automatically by the DI container and avaiable via Service::objectId()., (*34)

For example, the database connection is defined in config/db.php as follows,, (*35)

use Phossa2\Db\Driver\Pdo\Driver as Pdo_Driver;

// config/db.php
return [
    // PDO driver classname
    'driver.pdo.class' => Pdo_Driver::getClassName(),

    // connect conf
    'driver.pdo.conf' => [
        'dsn' => 'mysql:dbname=test;host=127.0.0.1;charset=utf8',
    ],

    // container section
    'di' => [
        // ${#db}
        'db' => [
            'class' => '${db.driver.pdo.class}',
            'args' => ['${db.driver.pdo.conf}'],
        ],
    ],
];

The last section di equals to defining a $db in the container, (*36)

$db = new Pdo_Driver(['dsn' => '...']);
$container->set('db', $db);

To utilize the database connection in your code, you may either inject it in another container object configuration file., (*37)

// config/article.php
return [
    'class' => MyArticle::getClassName();

    // ${#article} in container
    'di' => [
        'article' => [
            'class' => '${article.class}',
            'args' => ['${#db}'] // inject $db
        ]
    ]
];

Or use it explicitly with the service locator,, (*38)

use Phossa2\Di\Service;

// get db
$db = Service::db();

$article = new MyArticle($db);

Complicated db configurations can be found in config/production/db.php which uses a db connection manager with a pool of a read-write connection and couple of read-only connections., (*39)

use Phossa2\Db\Manager as Db_Manager;
use Phossa2\Db\Driver\Pdo\Driver as Pdo_Driver;

// config/production/db.php
return [
    // driver manager
    'manager.class' => Db_Manager::getClassName(),

    // more connect confs
    'driver.pdo.conf2' => [
        'dsn' => 'mysql:dbname=test;host=127.0.0.2;charset=utf8',
    ],

    'driver.pdo.conf3' => [
        'dsn' => 'mysql:dbname=test;host=127.0.0.3;charset=utf8',
    ],

    // callback to get a db from db manager with tagname
    'callable.getdriver' => function($dbm, $tag) {
        return $dbm->getDriver($tag);
    },

    // container section
    'di' => [
        // ${#dbm}
        'dbm' => [
            'class' => '${db.manager.class}',
            'methods' => [
                ['addDriver', ['${#db1}', 1]],
                ['addDriver', ['${#db2}', 5]],
                ['addDriver', ['${#db3}', 5]],
            ],
        ],

        // ${#db1}
        'db1' => [
            'class' => '${db.driver.pdo.class}',
            'args' => ['${db.driver.pdo.conf}'],
            'methods' => [
                ['addTag', ['RW']]
            ]
        ],

        // ${#db2}
        'db2' => [
            'class' => '${db.driver.pdo.class}',
            'args' => ['${db.driver.pdo.conf2}'],
            'methods' => [
                ['addTag', ['RO']]
            ]
        ],

        // ${#db3}
        'db3' => [
            'class' => '${db.driver.pdo.class}',
            'args' => ['${db.driver.pdo.conf3}'],
            'methods' => [
                ['addTag', ['RO']]
            ]
        ],

        // ${#dbro} read only driver (round-robin)
        'dbro' => [
            'class' => '${db.callable.getdriver}',
            'args' => ['${#dbm}', 'RO'],
            'scope' => Container::SCOPE_SINGLE,
        ],

        // ${#dbrw} readwrite driver (round-robin if any)
        'dbrw' => [
            'class' => '${db.callable.getdriver}',
            'args' => ['${#dbm}', 'RW'],
            'scope' => Container::SCOPE_SINGLE,
        ],

        // ${#db} either RW or RO
        'db' => [
            'class' => '${db.callable.getdriver}',
            'args' => ['${#dbm}', ''],
            'scope' => Container::SCOPE_SINGLE,
        ],
    ],
];

The previous configruations equal to the following code,, (*40)

// different db connectors
$db1 = (new Pdo_Driver($conf ))->addTag('RW');
$db2 = (new Pdo_Driver($conf2))->addTag('RO');
$db3 = (new Pdo_Driver($conf3))->addTag('RO');

// db manager
$dbm = (new Db\Manager\Manager())
    ->addDriver($db1, 1)    // readwrite, factor 1
    ->addDriver($db2, 5)    // read_only, factor 5
    ->addDriver($db3, 5)    // read_only, factor 5

// get a readonly connection (round robin)
$dbro = $dbm->getDriver('RO');

// get a readwrite connection
$dbrw = $dbm->getDriver('RW');

// get a db connection (either RW or RO)
$db = $dbm->getDriver('');

Middleware driven framework

phossa2/framework is not a pure MVC structure but a middleware-centric framework. For middleware runner implementation, please see phossa2/middleware., (*41)

Different middleware queues are defined in config/middleware.php., (*42)


Routing

Routes are handled by Phossa2\Middleware\Middleware\Phossa2RouteMiddleware. See phossa2/middleware, phossa2/route for detail., (*43)

Route dispatcher $dispatcher is defined in config/route.php. It will be injected into the main middleware queue when processing reaches the Phossa2RouteMiddleware., (*44)

Different routes should be defined in config/route/*.php files. For example,, (*45)

// route/50_admin.php
$ns = "App\\Controller\\"; // controller namespace

return [
    'prefix' => '/admin/',
    'routes' => [
        // resolve to ['App\Controller\AdminController', 'defaultAction']
        '/admin/{action:xd}/{id:d}' => [
            'GET,POST',                     // http methods,
            [$ns . 'Admin', 'default'],     // handler,
            ['id' => 1]                     // default values
        ],
    ]
];

Note: 50_ in the route filename is for sorting purpose., (*46)

Application programming

  • Do it a simple way, (*47)

    You may just start programming in the app/ directory where phossa2/app-skeleton is already installed during the project creation., (*48)

  • Do it a nice way, (*49)

    1. Git clone app-skeleton to your local directory., (*50)

    2. Add your own stuff to the cloned application skeleton., (*51)

    3. Remove the initially installed app-skeleton from the project, (*52)

    # cd PROJECT/
    # composer remove phossa2/app-skeleton
    
    1. Install your app into the PROJECT
    • If your app is on the git, (*53)

      Add the following lines to your PROJECT/composer.json, (*54)

      "repositories": [
        {
            "type":"package",
            "package": {
                "name": "my/app",
                "version": "master",
                "source": {
                    "url": "https://github.com/my/app.git",
                    "type": "git",
                    "reference":"master"
                }
            }
        }
      ]
      
    • If your app is just a zip., (*55)

      Add the following lines to your PROJECT/composer.json, (*56)

      "repositories": [
        {
            "type": "package",
            "package": {
                "name": "my/app",
                "version": "master",
                "dist": {
                    "type": "zip",
                    "url": "http://mydomain.com/downloads/app-1.4.zip",
                    "reference": "master"
                }
            }
        }
      ]
      
    • then install the app via composer require or composer update, (*57)

      # cd PROJECT/
      # composer require my/app
      

License

MIT License, (*58)

The Versions

11/10 2016

dev-master

9999999-dev https://github.com/phossa2/framework

A modern PHP framework built-upon configuration, dependency injection and middlewares.

  Sources   Download

MIT

The Requires

 

framework phossa phossa2