Yii 1.1: Yiinitializr: The Library

25 followers

Introduction

For those who have created a project boilerplate with Yiinitializr site, you will find that is not just a project boilerplate what you just downloaded. Within the boilerplate comes a library named: Yiinitializr (not very original I know). The classes within this tiny library are simple, yet powerful, and will help you build your own project setup, the one that really fits your needs for your Yii application.

The Classes Explained

The Yiinitializr classes will help boost your application installation with ease and also to run Yii applications from its bootstrap files on a much cleaner way that the framework currently proposes. Let's have a look at the following example:

// if installed via composer (pretty neat right?)
require('./../../common/lib/vendor/autoload.php');
 
Yiinitializr\Helpers\Initializer::create('./../', 'frontend', array(
    // will override frontend configuration file
    __DIR__ .'/../../common/config/main.php', // merged with
    __DIR__ .'/../../common/config/env.php', // merged with
    __DIR__ .'/../../common/config/local.php' // merged with
))->run();

Yiinitializr\Cli namespace

This namespace brings utilities to interact with the terminal or 'cli'. A free beer goes to mr nramenta for them.

Yiinitializr\Cli\Console

The Console class helps you to display information to the console. You probably, think that it as easy as to 'echo' from any of your Command components that are runed by the Yiic command and is true, but this class comes with some magic:

Color

Console::output('this is %rcolored%n and %Bstyled%n');

Prompt

$db_host = Console::prompt('database host', ['default' => 'localhost']);

Selection

$opt = Console::select('Do you love Yii?',
    ['y' => 'yes', 'n' => 'no', 'a' => 'all']
);

Confirm

$sure = Console::confirm('are you sure?');

Work

<?php
Console::stdout('Working ... ');
Console::work(function($socket) { // $socket is optional, defaults to a spinner
    $n = 100;
    for ($i = 1; $i <= $n; $i++) {
        // do whatever it is you need to do
        socket_write($socket, "[$i/$n]\n");
        sleep(1); // sleep is good for you
    }
});
Console::stdout("%g[DONE]%n\n");

Yiinitializr\Cli\Daemon

The Daemon class provides helpers for starting and killing daemonized processes.
<?php
use Yiinitializr\Cli\Daemon;
 
if (Daemon::isRunning('/path/to/process.pid')) {
    echo "daemon is running.\n";
} else {
    echo "daemon is not running.\n";
}

Yiinitializr\Composer namespace

I should just call this namespace Tobias Schmunk as he was the master guru behind this class, the only thing I did was to read the e-book of Composer and studied every single piece of his fabulous Phundament application boilerplate. To modify the class to become of more general usage out of Phundament has no much credit.

Here, we find the Callback class, a super useful class that will allow you to execute commands prior, post Composer extensions installations or updates. It makes use of the scripts configuration feature and even though for the current templates found at Yiinitializr Site the only thing it does is to call Yiic migrate commands but I am sure that you are already thinking of its possibilities.

Yiinitializr\Helpers namespace

Yiinitializer\Helpers\ArrayX

This class includes cool functions to work with arrays. It contains one cloned from CMap, the mergeArray function, as we require this method in order to combine the different configuration files before the Yii application is even included. A clear example of it you find it on Yiinitializr/config/console, which is the file that where you set the configuration of your console application to run Composer callbacks. It has also

Yiinitializr\Helpers\Config

It reads the configuration file and provides an interface to access the settings. It also, when working with different environments, writes the "env.lock" file. By creating this file, it tells the Initializr helper class to not recreate the env.php configuration file of the environment selected. If anybody wishes to recreate them, in order to make use of other environment configuration file (ie. stage vs local), the coder just needs to delete the "env.lock" file from the Yiinitializr/config folder.

The configuration file

As with Yii, you need to go through a bit of configuration settings if you wish to handle your project structure initializing setup with Yiinitializr. But don't worry, is not going to be too hard, the following is an example configuration file:
\\ where am i?
$dirname = dirname(__FILE__);
\\ where is the application folder?
$app = $dirname . '/../../..';
\\ where is the root?
$root = $app . '/..';
 
return array(
    // yii configurations
    'yii' => array(
        // where is the path of the yii framework?
        // On this example we have installed yii with composer
        // and as it is used after composer installation, we
        // can safely point to the vendor folder.
        'path' => $app . '/lib/vendor/yiisoft/yii/framework'
    ),
    // yiinitializr specific settings
    'yiinitializr' => array(
        // config folders
        'config' => array(
            // we just need the console settings
            // On this example, and due that I used environments
            // i created a custom console.php app for
            // Yiinitializr\Composer\Callbak class
            'console' => $dirname . '/console.php'
        ),
        // application structure settings
        'app' => array(
            // where is the root?
            'root' => $root,
            // directories setup
            'directories' => array(
                // where are the different configuration files settings?
                'config' => array(
                    // 'key' is the configuration name (see above init example)
                    'main' => $app . '/config',
                    'console' => $app . '/config',
                    'test' => $app . '/config'
                ),
                // where are my runtime folders?
                'runtime' => array(
                    // heads up! only the folder location as "/config" will be
                    // appended
                    $app
                ),
                'assets' => array(
                    // where to write the "assets folders"?
                    $root . '/www'
                )
            ),
            'files' => array(
                // files to merge the main configuration file with
                // initializr will merge it automatically
                'config' => array(
                    'main' => array('env', 'local'),
                    'console' => array('env', 'local'),
                )
            )
        ),
    )
);

Yiinitializr\Helpers\Initializer

This class requires a little bit more attention and I hope you take a bit of time reading its code to truly understand what it does. Improving this class, can make our lives easier with Yii and I explain why:

  1. It tries to solve the problem with YII_DEBUG dynamically (no need to hardcode true|false on your index.php bootstrap file) - check the setOptions function.
  2. It creates all necessary read+write folders like runtime and assets (Yiinitializr works in conjunction with Composer but I am pretty sure some of you are already thinking on why is not Yii creating those folders when they are not found? Initializer class may provide the solution: if it doesn't exist, build it don't fail on error!)
  3. Automatically merges different configuration files that you may have for the different type of applications - check the config function.

Final Notes

We truly hope at 2amigOS! that you find this library as useful as it is for us. We do not expect that this procedure should be implemented at Yii's core but some of the features included in this small library are certainly something to consider on its future releases. Happy Yii coding!

References

2amigOS!
web development has never been so fun
www.2amigos.us

Total 9 comments

#14765 report it
Alex.Sh at 2013/09/08 02:15pm
Configuration

Hi, few questions.

Is there fast way to change env config from "dev" to "prod"? Steps before uploading on production?

Thanks!

#13879 report it
DryKillLogic at 2013/07/03 04:37pm
Thanks

@gb5256 thanks. Maybe you're right but this is what I need to my project so I need to make it work. I have problems related to db config (I set the db configuration in common/config/main.php) and nginx (some workaround would be great). Antonio, do you have any tips about this issues?

Thanks guys. I was struggling all day and no luck :s

#13878 report it
gb5256 at 2013/07/03 03:54pm
Db problem

@DryKillLogic

I did fix this one, but I encoutered so many other issues, that I have stopped using it. I am not blaming anybody, but Yiinitializr is in its early stages. It looks extremely promising, but to use it right now for any website which needs to go into production soon, this is too early. So for now, I went back to YiiBooster as that one is working out of the box.

Looking at the work of Christoffer and Antonio, Yiinitializer will one day be much better than YiiBooster, but that takes a bit more time.

gb5256

#13876 report it
DryKillLogic at 2013/07/03 02:27pm
Db problem

@gb5256 How did you fix it?. I've got the same problem and I don't know which config file is required to db connection.

Thanks.

#13736 report it
gb5256 at 2013/06/20 12:57pm
Wow, but...

Hello out there. This looks really cool. I am working currently with yiiBoilerplate and wanted to check out what Ramirez is doing... I have made everything which is shown at git under the point "Setup and first run", but when I access root-www of the backend, I get an:

CHttpException
 
The system is unable to find the requested action "error".

What is wrong? I can not even access the gii (after enabling it in the config).

gb5256

EDIT: it was a wrong database connection, shame on me... But I was confused with all the different config files...

#13006 report it
Antonio Ramirez at 2013/04/27 02:10pm
@le_top

I think is a great option to consider. Could we move this to github issue to further discuss its implementation to the config Yiinitialzr file? I like the idea.

#13004 report it
le_top at 2013/04/27 01:50pm
Further suggestions for configureability

Hi This is another step in a nice direction. Could you consider adding:

  • Url/Server dependent configuration;
  • Debug configuration based on Url option?

I currently do stuff like this in my 'index.php':

// Determine debug mode depending on site name or get parameter (secret_dbg_key in this example):
 
$prodtest=(preg_match('/^expressiontocomparewith?$/',getenv('HTTP_HOST'))>0);
 
$debugmode=!$prodtest&&(preg_match('/^localhost([:\/].*)?
$/',getenv('HTTP_HOST'))>0)||isset($_GET['secret_dbg_key']);
 
$isProduction = $prodtest||(preg_match('/^([^\/].*)?prodsite.com/',getenv('HTTP_HOST'))>0);
if($debugmode) {
    defined('YII_DEBUG') or define('YII_DEBUG',true);
    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',5);
}

and similar for the configuration where I have

if(!CliCheck::isCli()) {
    $host = $_SERVER['HTTP_HOST'];
 
    $host = getenv('SERVER_NAME');
} else {
    $host=gethostname();
}
/** Check if there is a site configuration */
$siteconf = dirname(__FILE__).DIRECTORY_SEPARATOR.$host.'_common.php';
if(file_exists($siteconf)) {
    $siteconf=require($siteconf);
} else {
    $siteconf=array();
}

which loads a configuration file based on the host name. "CliCheck::isCli()" checks if it is run from the command line or not. '$siteconf' gets merged with the default/common configuration.

#12963 report it
Antonio Ramirez at 2013/04/23 03:46pm
@Ramin Farmani

You can implement namespaces in controllers for sure, but would you do that? wouldn't be easier to just name the different controllers you wish to extend from?

#12962 report it
Ramin Farmani at 2013/04/23 03:14pm
namesapaces

is it possible to implement namespaces in controller? I have many issue with that its quite common to use same name for controllers in back/front-end and or some version in api so how can I use name sapaces in controller?

I have also some core component places in common/components so a SiteController in backend should have a namesapce like:

namespace SomeCoreNameSpace\backend;
use SomeCoreNameSpace\common\CTBaseController
class SiteController extend CTBaseController {}

and my core component is like:

namespace SomeCoreNameSpace\common;
class CTBaseController extends EController { {}

but it seems there is something wrong with it would you explain a strategy to implement namespaces?

Leave a comment

Please to leave your comment.

Write new article