Scorpio2 Introduction

Posted by Dave Redfern (Writer), News on 31 Mar 2012 @ 19:40

It has been a while, but Scorpio 2 is underway and is available from Github! This is still highly experimental and much work remains to be done, but if you are feeling brave: clone, deploy and have a look.

Scorpio 2 is a complete rebuild of the framework from the ground up, utilising Symfony 2 components and a standardised (with-in reason) layout and naming structure. Development is following Symfony 2 conventions and the PHP PSR-0 naming styles so Scorpio files will load via any PSR-0 compliant auto-loader.

From Symfony 2, Scorpio 2 uses:

It has not been decided if form, validator and locale will be used - however they are currently being included as recommendations.

In addition, Scorpio 2 uses (or will use):

The main repo can found at: https://github.com/scorpioframework/scorpioframework

Installation

Currently setting up Scorpio is a little involved as various parts are still being worked on and the configuration requirements are not yet finalised. Installing the base files is easy enough, and the dependencies are managed via Composer.

To get up and running you will need to first download and install composer.phar and ensure that you have a Git client.

Create a folder for the project for example: ~/Projects/Scorpio2 and from a command line (or in your Git client):

cd ~/Projects/Scorpio2

git clone git@github.com:scorpioframework/scorpioframework.git ./

composer.phar install

Folder Structure

The current folder layout for Scorpio 2 is:

Not all of these folders exist in the repository, but should be added if missing. Vendors is created automatically by Composer.

The structure is intended to be used as follows:

Configuration

Unlike Symfony 2, Scorpio 2 has split configuration - there is the config for the dependency injection container (DIC) and then there is the platform level config that is not injected into the DIC, but is accessed via a ConfigProvider. This is essential as otherwise the configuration would not be modifiable if it were all contained in the DIC (a'la Symfony2).

Currently Scorpio2 requires at least 3 main "config" files:

DIC Config: container.yml

Please note: at the time of writing the basic DIC configuration has not been finalised and is using a port of the Symfony2 framework bundle config. This is subject to change as the container configuration is finalised.

container.yml sets up the shared configuration that is used by all components within Scorpio. This is across sites and CLI applications. It should only contain components that do not need to be overridden or that are not specific to a single entity.

Currently the file format and extension is fixed as YAML, however this will be updated to allow this file to use XML and PHP.

The current file has the following structure:

framework:

    # general configuration
    charset:              "UTF-8"
    secret:               ""
    ide:                  ""
    default_locale:       "en"

    # router configuration
    router:
        http_port:            80
        https_port:           443

    # session configuration
    session:
        auto_start:           true
        storage_id:           session.storage.native
        name:                 ScorpioSession
        cookie_lifetime:      86400
        cookie_path:          /
        cookie_secure:        ~
        cookie_httponly:      ~

    # templating configuration
    templating:
        assets_version:       ~
        assets_version_format:  "%%s?%%s"
        assets_base_urls:
            http:                 []
            ssl:                  []
        cache:                ~
        engines:              ["php", "smarty"]
        loaders:              []
        packages:

    # translator configuration
    translator:
        enabled:              true
        fallback:             en

Master Config: config.xml

Just like previous versions of Scorpio, there is a single master config file that is used throughout the whole platform. In Scorpio2 this is separate from the DIC config as the DIC config is cached into the DIC itself and cannot be changed. This config however, can be modified once loaded.

Unlike previous versions of Scorpio, the format of the config file has changed: it can now use a more freeform XML format.

The database config, logging etc is all defined within this file. Typically it will contain something like the following:

<?xml version="1.0" encoding="UTF-8" ?>
<config>
	<app override="0">
		<author override="0">Your Name</author>
		<copyright override="0">Your Company (c) 2012</copyright>
		<version override="0">X.Y</version>
	</app>
	<log>
		<writer>Scorpio\Framework\Log\Writer\FileWriter</writer>
		<level>ALWAYS | ERROR | CRITICAL | WARNING | NOTICE | INFO | DEBUG</level>
		<register>1</register>
	</log>
	<db>
		<dsn>%TYPE%://%USER%:%PASSWORD%@%HOST%/%DATABASE%</dsn>
		<defaults>
			<database>system</database>
			<user>scorpio</user>
			<password>password</password>
			<type>mysql</type>
			<host>localhost</host>
			<port>3306</port>
		</defaults>
		<databases>
			<system>
				<database>scorpio_system</database>
				<user>scorpio_system</user>
			</system>
			<logging>
				<database>scorpio_logging</database>
				<user>scorpio_logging</user>
			</logging>
		</databases>
	</db>
	<console>
		<user>user</user>
		<group>group</group>
	</console>
</config>

Bootstrap: init.php

init.php is the shared bootstrap file used by both web and CLI components. This sets up the autoloader, DIC, main config and environment. It currently is some variation of the following code sample:

/**
 * init.php
 *
 * init.php provides the main bootstrapping and setup for the Scorpio environment.
 * You can change this to suit your needs / update the packages. This is just to
 * get you started.
 *
 * @author Dave Redfern
 * @copyright Dave Redfern (c) 2007-2012
 * @package init.d
 * @subpackage init
 * @license http://www.scorpioframework.com/static/license  BSD License
 */


/*
 * Location of the vendor packages
 */
$vendorDir = dirname(dirname(__DIR__)).'/vendor';
/*
 * Main custom source directory
 */
$sourceDir = dirname(dirname(__DIR__)).'/src';
/*
 * Compiled all-in-one class built from {@link Scorpio\Framework\Package\Packager}.
 */
$bootstrap = __DIR__.'/bootstrap.php';

/*
 * If we have a bootstrap, use it, otherwise load the autoloader
 */
if ( file_exists($bootstrap) ) {
	include_once $bootstrap;
} else {
	$autoload = '/Scorpio/Framework/Autoload/Autoload.php';
	if ( file_exists($vendorDir.$autoload) ) {
		include_once $vendorDir.$autoload;
	} elseif ( file_exists($sourceDir.$autoload) ) {
		include_once $sourceDir.$autoload;
	} else {
		throw new \Exception(
			sprintf(
				'Unable to load Autoload.php from either "%s" or "%s". Please correct the paths.',
				$vendorDir.$autoload, $sourceDir.$autoload
			)
		);
	}
}

use Scorpio\Framework\Autoload\Autoload;

/*
 * Register default autoloader and required packages
 */
$oLoader = Autoload::setInstance(new Autoload());
$oLoader->registerNamespaces(
	array(
		'Scorpio' => dirname($vendorDir) . '/src',
		'Symfony\\Component\\Yaml' => $vendorDir . '/symfony/yaml',
		'Symfony\\Component\\Templating' => $vendorDir . '/symfony/templating',
		'Symfony\\Component\\Routing' => $vendorDir . '/symfony/routing',
		'Symfony\\Component\\HttpKernel' => $vendorDir . '/symfony/http-kernel',
		'Symfony\\Component\\HttpFoundation' => $vendorDir . '/symfony/http-foundation',
		'Symfony\\Component\\Finder' => $vendorDir . '/symfony/finder',
		'Symfony\\Component\\EventDispatcher' => $vendorDir . '/symfony/event-dispatcher',
		'Symfony\\Component\\DependencyInjection' => $vendorDir . '/symfony/dependency-injection',
		'Symfony\\Component\\Console' => $vendorDir . '/symfony/console',
		'Symfony\\Component\\Config' => $vendorDir . '/symfony/config',
		'Doctrine\\ORM' => $vendorDir . '/doctrine/orm/lib',
		'Doctrine\\DBAL' => $vendorDir . '/doctrine/dbal/lib',
		'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib',
	)
);

/*
 * Register "old" style packages and libs
 */
$oLoader->registerPrefixes(
	array(
		'Smarty' => $vendorDir . '/smarty/smarty/libs',
		'PHPExcel' => $vendorDir . '/CodePlex/PHPExcel',
	)
);

/*
 * Install autoloader
 */
$oLoader->register();

/*
 * Start the Scorpio Bootstrap
 */
$oBootstrap = new Scorpio\Framework\Bootstrap\Bootstrap(
	new Scorpio\Framework\Bootstrap\BootstrapBundles(
		array(
			new Scorpio\Framework\FrameworkBundle(),
			new Scorpio\SmartyTemplating\SmartyBundle()
		)
	),
	array(
		'production' => false,
	)
);

Websites and Launching

Scorpio2 continues to support the site-hierarchy and inheritance from previous versions, however it has been reworked. Each site still has its own config and routing files except now the routing uses the Symfony 2 routing format and the config is much simple and follows the more freeform examples.

Website configuration is located within /etc/websites and is organised by site domain name without any leading type sub-domains (e.g. www, rss, xml). At the very minimum there will be at least one file per site: config.xml (or ini, yml, php). If the site is intended to be usable it will need a routing.xml (ini, yml, php) file. Note: the routing file is unique for each site and is not inherited but can use import definition of other route files - so long as they can be resolved.

Website controllers, models and views are now located within /src/websites. Unlike previous versions there are substantial differences in the actual format of these components. Each "site" is now just a container for essentially "undefined bundles". Basically controllers / models / views are organised into packages following the following convention:

An example component might be a "Blog" within "example.com":

/src/websites/example.com/Blog/Controller/BlogController.php

With view templates located in:

/src/websites/example.com/views/Blog/Blog

A site can contain controllers or just views or nothing if it has no customisations.

Scorpio2 is designed to use Smarty as the template layer, however it implements the Symfony2 "templating" PHP engine as well. The engine can be switched by setting the template extension to either .tpl for Smarty or .php for the PHP engine. Additional engines can be added for other templating systems and defined in the container configuration.

To handle basic websites a main rewrite handler implementation is needed. This can be as basic as the following example, which will also need a .htaccess modrewrite rule to direct requests to it.

/**
 * Web Distributor
 *
 * Stored in index.php
 *
 * @author Dave Redfern
 * @copyright Dave Redfern (c) 2007-2012
 * @package web
 * @subpackage index.php
 * @license http://www.scorpioframework.com/static/license  BSD License
 */
require_once dirname(__DIR__).'/etc/init.d/init.php';

use Symfony\Component\HttpFoundation\Request;

$oBootstrap
	->getContainer()
	->get('distributor')
		->handle(Request::createFromGlobals())
		->send();

Finally: to get a site working you will need to create the site definitions, routing config and define at least a single controller. Continuing the example above, the BlogController could be implemented in the following manner:

namespace Blog\Controller;
use Scorpio\Framework\Controller\Controller as BaseController;
use Symfony\Component\HttpFoundation\Response;

class BlogController extends BaseController {

	function indexAction() {
		return $this->get('templating')->renderResponse('Blog:Blog:index.html.tpl');
	}
}

Scorpio2 uses the same controller conventions as Symfony2.

More Still To Come

This is just the basics. Much more is still to be completed (such as the CLI layer, code generators, main configuration etc).

The switch to using shared components with Symfony is a learning curve, but the benefits outweigh the difficulties. Having a well-tested and debugged set of components for routing and other components means that we can focus on what Scorpio needs. There is some overlap (translation, config etc) but where it makes sense using the third party libraries via Packagist and Composer should make getting up and running that much easier.

In terms of performance, already there are substantial gains. Ad-hoc testing with Apache bench in a totally unscientific manner on an Intel i7-860 running Kubuntu resulted in over 300 requests per second without real performance tuning and running through Smarty with translations and sessions enabled.

It is still early days and changes still need to be made: Scorpio2 is based on Symfony 2.1 which is still under development, so as it changes Scorpio2s base will change.

< Return to article