Serialization / Deserialization

In my quest to find the best approach to work with serialization / deserialization in the ‘no-framework’ project where I do not use a full stack framework I have found my self with a small challenge:

I would like to save, what I consider a class Settings Value Object, in my database as a JSON string and for that JMS Serializer does a great job. But then for my API I need to work with arrays. How can I avoid crappy methods and solutions where I need to add a “toArray()” method? How can I avoid writing my very own custom serializer to handle from/to array conversion? How can I make use of JMS Serializer to do that? I have already written the configuration files, I don’t want to write more code! ARGH!

Quick note: About the configuration files, guys, one huge recommendation is that when you use JMS Serializer, make sure you use XML configuration files for your mapping. That way you will avoid spending hours to figure out what the heck has happened to your code that is not working properly. By the way, how to create your XML configuration files is out of the scope of this tutorial/tip.

I really wanted to avoid to create new interfaces to hold the ‘arraySerializable‘ thingy and ‘toArray()‘ methods on each of the classes. So I made a search and found the ‘https://packagist.org/packages/epwt/array-jms-serializer-bundle‘ package. It was a great finding but I didn’t want to use Symfony or a Bundle, how can I could configure the serializer on the container of my personal library? And this is what I did:

First of all, got its two Serialization/Deserialization visitor classes and place it one of the of the folders of my work in process library:

The Deserializer Visitor Class

namespace XXX\Service\Serializer;

use JMS\Serializer\GenericDeserializationVisitor;

/**
 * Class ArrayDeserializationVisitor
 * @package EPWT\ArrayJMSSerializerBundle\Visitor
 * @author Aurimas Niekis <aurimas.niekis@gmail.com>
 */
class ArrayDeserializationVisitor extends GenericDeserializationVisitor
{
    protected function decode($str)
    {
        return $str;
    }
}

And The Serializer Visitor Class

namespace XXX\Service\Serializer;

/**
 * Class ArraySerializationVisitor
 * @package EPWT\ArrayJMSSerializerBundle\Visitor
 * @author Aurimas Niekis <aurimas.niekis@gmail.com>
 */
class ArraySerializationVisitor extends GenericSerializationVisitor
{
    /**
     * @return array
     */
    public function getResult()
    {
        return $this->getRoot();
    }

    /**
     * @param array $data
     * @param array $type
     * @param Context $context
     * @return array|\ArrayObject|mixed
     */
    public function visitArray($data, array $type, Context $context)
    {
        $result = parent::visitArray($data, $type, $context);
        if (null !== $this->getRoot() && isset($type['params'][1]) && 0 === count($result)) {
            // ArrayObject is specially treated by the json_encode function and
            // serialized to { } while a mere array would be serialized to [].
            return new \ArrayObject();
        }
        return $result;
    }

    /**
     * @param ClassMetadata $metadata
     * @param mixed $data
     * @param array $type
     * @param Context $context
     * @return \ArrayObject
     */
    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
        $rs = parent::endVisitingObject($metadata, $data, $type, $context);
        // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null.
        if (empty($rs)) {
            $rs = new \ArrayObject();
            if (array() === $this->getRoot()) {
                $this->setRoot(clone $rs);
            }
        }
        return $rs;
    }
}

How to use it? Well, exactly as we do with the other formats:

// as json 
$json = Container::serializer()->serialize($myClassInstance, 'json');
$objectFromJson = Container::serializer()->deserialize($json, MyClassInstance::class, 'json');
// ...
// same with yaml or xml 
// ...
// as array
$array = Container::serializer()->serialize($myClassInstance, 'array');
$object = Container::serializer()->deserialize($array, MyClassInstance::class, 'array');

Easy right? Now, some of you may think that this is an overkill to simply return an array representation of an object. I don’t think so at all if you are using JMS Serializer. You already have the configuration files that expose how do you want your objects to serialize/deserialize, you really want to create your own serializer, your own methods to return arrays? And this solution is an overkill? Yeah, right. Is up to you but I would rather keep my models or resource classes CLEAN.

And what about if you need to modify the value that an attribute of my model represents? Your solution SUCKS!

Slow down cowboy, don’t you know that Mr. JMS Serializer allows you to provide custom handlers for a specific attribute types? Your excuse of bloating your classes with extra code that could easily be handled with this amazing library or building your very own Serializer strategy is just, IMHO, silly. But hey! Its just an opinion from a nobody like me :)

Happy coding guys!

It’s been a long time

I have to admit, I didn’t have the time to do the things I love for the past year. In fact, my last post on my blog was more than a year a go. I even thought I should just simply close it down but that is not going to happen anytime soon.

So, during the last year I didn’t have time for absolutely nothing. It was very hard to even keep up to date with all my email accounts and those requests sent to this blog, were just left unanswered. So, please, accept my biggest apologies for those who took the time to send me a contact request, or asked me a question and I just didn’t reply.

Last week, I have recovered my blog, this blog, and I am going to update you guys with all my encounters with programming. As you can see, I have updated the layout of the blog too, I prefer to keep it clean, and will  remove anything related to advertising that was making it so ugly (still ugly but hey! is my blog :)).

One of the series that I am going to start is a personal experiment that I wanted to develop since long time a go: How to build your very own framework from scratch.

I can hear the voices saying: WTF!? Another framework? Is this guy nuts? Relax yo! I do not want to create a new PHP framework, just the building blocks for my selection of libraries that will create the framework where I am going to setup the base of my MVP or site or whatever. What I would like to demonstrate (even to my self) is that we do not really need frameworks at all, that sometimes their approaches make us become even worst developers and that maybe, maybe, mr Rasmus is right by stating that “all PHP frameworks suck“, and that there are tons of amazing well developed, supported and tested PHP components and libraries out there that can really suit your development needs.

Maybe I am wrong, and thats the whole point of the experiment. I think could be a good starting point for a brand new set of articles on my blog. If you wish to join me, would be more than happy to hear your findings too.

Thank you all for coming back, thank you all for passing by… it’s been a long time without you my friends :)

 

How to implement form events on Yii2

You have that, when a product is on development they can change its API anytime. This change is quite important though, its related on how to set the events of your form, for example, the useful beforeSubmit.

Before, we could do that easily on an ‘ActiveForm’s property but now we have to do some extra work and register the javascript event your self.

Now, lets imagine we wish to deal with a ‘beforeSubmit’ event on our form:

<?php $form = ActiveForm::begin(
    [
        // make sure you set the id of the form
        'id' => $model->formName(), 
        'action' => ['yada/create']
    ]
);?>

<!-- more stuff here -->

<?php ActiveForm::end();?>

In order to register your beforeSubmit event, we will have to register the event this way:

<?php
$js = <<<JS
// get the form id and set the event
$('form#{$model->formName()}').on('beforeSubmit', function(e) {
   var \$form = $(this);
   // do whatever here, see the parameter \$form? is a jQuery Element to your form
}).on('submit', function(e){
    e.preventDefault();
});
JS;

$this->registerJs($js);

And thats it… hope you find it useful. Its a bit confusing at first when you do not know what has just happened.

How to use GridView with AJAX on Yii2

With the adoption of PJax on Yii2 things  have change quite a bit with GridView when it comes to work with them in AJAX mode. It will probably be confusing at the beginning, but then you will soon realize how powerful the new approach is.

Using PJax widget

The way to work with GridView in AJAX mode, is by using the PJax widget. The basic usage is like the following:

<?php \yii\widgets\Pjax::begin(); ?>
<?= GridView::widget([
// ... configuration here
]);?>
<?php \yii\widgets\Pjax::end(); ?>

Thats it, from now, the links and forms (filtering) on your GridView widget will work on ajax mode. But wait a minute, how come the action buttons do not work on AJAX mode? Well, if you check closely the rendered HTML, you will see that the links do have the HTML5 attribute data-pjax="0". That means that if you don’t wish PJax to handle your links, you need to add this HTML5 attribute to them.

How to Update my GridView

You will surely missing $('#grid').yiiGridView('update') and wondering how to do it with PJax. The following code comes to the rescue:

// on your javascript
// I highly recommend that you setup the id of your PJax widget
$.pjax.reload({container:'#idofyourpjaxwidget'});

For more information about the options that you can pass to the reload function, please check the PJax plugin code.

Final Notes

The PJax widget works with any links and/or forms that are inside its begin() and end() statements. That means, that this tutorial is also valid for ListView, LinkPager, etc… Anything that holds a link and/or a form.

HappYii2 coding

Displaying, Sorting and Filtering Model Relations on a GridView – Yii2

One of the things you will find tricky to implement is the the sorting and filtering of a GridView’s column that displays related model data.

As you know if you have been playing with Yii2 lately, there is a new proposed way to search for data and is by using objects that extend from the main entity models and mark the searchable attributes as “safe”. So, how do we sort and filter related data on a GridView widget?

Lets imagine we have the following relations of a model named “Tour”:

/**
 * @return \yii\db\ActiveQuery
 */
public function getCountry()
{
    return $this->hasOne(Country::className(), ['id' => 'country_id']);
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getCity()
{
    return $this->hasOne(City::className(), ['id' => 'city_id']);
}

And we wish to display the name of the country and the name of the city on a GridView. To do that, we do the following on our “TourSearch” model:

class TourSearch extends Tour // extends from Tour see?
{
    // add the public attributes that will be used to store the data to be search
    public $city;
    public $country;

    // now set the rules to make those attributes safe
    public function rules()
    {
        return [
            // ... more stuff here
            [['city', 'country'], 'safe'],
            // ... more stuff here
        ];
    }
// ... model continues here

Now we will be able to setup our GridView so to display the related data:


// ... more grid configuration here
 'columns' => [
 // ... more columns configuration here
 [
 'attribute' => 'city',
 'value' => 'city.name'
 ],
 [
 'attribute' => 'country',
 'value' => 'country.name'
 ],
 // ... more stuff here
 

By doing as explained above, we will be able to display data but how to sort or filter? Lets explain that by example, and this time lets focus on the “search” method of our “TourSearch” class:

public function search($params)
{
    // create ActiveQuery
    $query = Tour::find();
    // Important: lets join the query with our previously mentioned relations
    // I do not make any other configuration like aliases or whatever, feel free
    // to investigate that your self
    $query->joinWith(['city', 'country']);

    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    // Important: here is how we set up the sorting
    // The key is the attribute name on our "TourSearch" instance
    $dataProvider->sort->attributes['city'] = [
        // The tables are the ones our relation are configured to
        // in my case they are prefixed with "tbl_"
        'asc' => ['tbl_city.name' => SORT_ASC],
        'desc' => ['tbl_city.name' => SORT_DESC],
    ];
    // Lets do the same with country now
    $dataProvider->sort->attributes['country'] = [
        'asc' => ['tbl_country.name' => SORT_ASC],
        'desc' => ['tbl_country.name' => SORT_DESC],
    ];
    // No search? Then return data Provider
    if (!($this->load($params) && $this->validate())) {
        return $dataProvider;
    }
    // We have to do some search... Lets do some magic
    $query->andFilterWhere([
        //... other searched attributes here
    ])
    // Here we search the attributes of our relations using our previously configured
    // ones in "TourSearch"
    ->andFilterWhere(['like', 'tbl_city.name', $this->city])
    ->andFilterWhere(['like', 'tbl_country.name', $this->country]);

    return $dataProvider;
}

Thats it… Hope this tutorial helps you find your way around.

Escape from Default’s Yii2 Delete Confirm Box

EDIT: Article has been updated with latest changes on Yii2 yii.js API.

If you started playing with Yii2’s new GridView, you will soon realize that some things have improved quite a lot, but I am sure its going to be a bit confusing at first glance when you try to modify certain javascript behaviors like for example, its delete confirmation dialog box.

I am sure there will be others finding better solutions, but on my case, I found the following quite simple to execute. On this article I am going to show you how to use the excellent library “BootboxJS” to display our confirmation box.  So, the first thing you need to do is to download that library and place it on your “web/js” folder (I am using the basic template application structure for the example).

Override Yii.js Module

The first thing we need to do is to override the methods “confirm” and “allowAction” on the yii.js module. The reason is that the module is the responsible of handling the click events of our rendered ActionColumn action links.

In order to override its methods, lets create a javascript file named “main.js” (for example) and we are going to place it on our “web/js” folder. These are the contents:

yii.allowAction = function ($e) {
    var message = $e.data('confirm');
    return message === undefined || yii.confirm(message, $e);
};
yii.confirm = function (message, ok, cancel) {
    bootbox.confirm(message, function (confirmed) {
       if (confirmed) {
         !ok || ok();
       } else {
         !cancel || cancel();
       }
    });
    return false;
}

The way the module comes by default is by using the native browser’s confirm dialog window that obviously stops the asynchronous execution of Javascript, but when you try to use “bootbox::confirm” method, that is not happening as the callback of the plugin does not return until the user clicks on one of the dialog’s buttons.

Thats the reason we override the “yii::confirm“, because we require the reference of the DOM object in order to call “yii::handleAction” properly. But is “yii::allowAction” the method who receives that reference, and thats why we had to override that method as well.

With this solution, the “yii::allowAction” will return false the first time, but “bootbox::confirm” will react according to user’s action. Thats the price you pay, but it works.

Register Your Assets

There is one last thing to do, modify our application’s asset bundle to register both “bootbox.min.js” and “main.js” script files.

For that we go to our “assets/AppAsset.php” file and write the following:

namespace backend\assets;

use yii\web\AssetBundle;

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = ['css/site.css'];
    // register the library first after our
    // script
    public $js = ['js/bootbox.min.js', 'js/main.js'];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}

And thats it, next time we click on the delete action of our grid, we will see a beautiful Bootstrap Confirm dialog.

bootbox dialog

How to use BootstrapInterface – Yii2

Yii2 introduces the BootstrapInterface to ease our application initialization tasks, whether they are `composer` based or Application bootstrap (do not mistaken with Bootstrap CSS Framework) based tasks. On this article, I am going to explain how to use it on your Application bootstrap process.

For our example, our site has two themes, one for desktop and the other for mobile rendering respectively, and we wish to switch between themes after detecting user’s platform. I am not going to explain how to install and configure your Yii2 Application (for a brief hint, please check my previous post on Yii2: Adding FontAwesome to your Yii2 Project Via Composer) so I assume that you have already a Yii2 application ready folder structure.

Install required extensions

In order to check whether our visitor is using a mobile, tablet or desktop device, we are going to use the wonderfully made class Mobile_Detect from mr Serban Ghitta (Thanks buddy!). In order to do that, we are going to include the following on our composer.json file:

"require": {
// ....
"mobiledetect/mobiledetectlib": "dev-master"
// ....

},

And run your composer update command at your terminal window.

Configure your desktop theme

Yep, before we forget, we need to configure our desktop theme. On this example, I am using the basic project template from Yii2, so the file where I am configure my theme is on config/web.php.

'view' => [
    'title' => '2amigOS! Consulting Group LLC',
    'theme' => [
       'baseUrl' => '@web/themes/desktop',
       'basePath' => '@app/themes/desktop'
    ]
],

As you can see, my themes are located under the application’s root directory and within the folder named themes. Note: Even though it is not shown here, I have another theme named mobile under the same folder themes.

The ThemeBootstrap class

Ok, now that we have configured our desktop theme, lets code our ThemeBootstrap class. This class will extend from the already mentioned BootstrapInterface interface and as you can see it has only one public method that is required to be implemented: bootstrap. This method is fired on our application’s init function per bootstrap class configured. For a closer look on how and where it occurs, please check Application::init method at github.

The following is our ThemeBootstrap class, placed in our app/extensions/components folder:


namespace app\extensions\components;

use yii\base\Application;
use yii\base\BootstrapInterface;

class ThemeBootstrap implements BootstrapInterface
{
    /**
    * Bootstrap method to be called during application bootstrap stage.
    * @param Application $app the application currently running
    */
    public function bootstrap(Application $app)
    {
        // create an instance of Mobile_Detect class
        $detector = new \Mobile_Detect();

        if ($detector->isMobile() || $detector->isTablet()) {
        // modify the configuration of our view component
        $app->set('view', [
            'class' => 'yii\web\View',
            'title' => '2amigOS! Consulting Group LLC',
            'theme' => [
                'baseUrl' => '@web/themes/mobile',
                'basePath' => '@app/themes/mobile'
            ]
        ]);
        }
    }
}

You probably are wondering what is going on? How come we change the component’s configuration like this? Well, in case you don’t know, Yii2 now supports DI (dependency injection) and our Application component extends from a Module, which extends from DI’s ServiceLocator class (check ServiceLocator::setComponents and Application::preInit functions, and you will soon realize how the Application merges the required classes with their configuration).  What we are using, is the ServiceLocator::set method to override the configuration of the view.

Configure ThemeBootstrap

There is one more thing to do, we need to tell our Application that we wish the ThemeBootstrap::bootstrap to run when initialized and we do that by setting Application::bootstrap property.

// ...
'bootstrap' => [
    'app\extensions\components\ThemeBootstrap',
],
'components' => [
// ...

And that’s it, now when your application starts Yii will automatically call ThemeBootstrap::bootstrap method thus modifying the theme of your application.

Adding FontAwesome to your Yii2 project via Composer

Well, it is time for Yii2 folks. Yep, even if its on alpha :)

This time I would like to explain how to include Fontawesome (external assets) to your Yii2 project. For this example, I am going to use the yii2 app-advance project template.

For this tutorial, I assume that you have `composer` or `composer.phar` installed on your computer.

Step 1 – Initialize your project

Install via Composer

php composer.phar create-project --stability=dev yiisoft/yii2-app-advanced /path/to/yii-application
Configure your environment

On my case, the only thing I did was to change the params-local.php file in environments/dev/common/config folder and edit the database configuration.

Run the
init

command

./init 

Once the command runs, you need to select your environment. In my case, I choosed [0] Development.
In addition, you can run the ./yii migrate command to setup your tables… but thats not important for the example.

Step 2 – Install FontAwesome

Now that we have the project setup, its time to include our fontawesomeness. For that, we are going to make use of composer.
By checking on packagist.org or the FontAwesome repository, we see that to install FontAwesome on our project we need to add FortAwesome/Font-Awesome": "*" on our composer.json. This is how it looks on mine:

// ...
"require": {
    "php": ">=5.4.0",
    "hybridauth/hybridauth": "dev-master",
    "FortAwesome/Font-Awesome": "*",
    "yiisoft/yii2": "*",
    "yiisoft/yii2-swiftmailer": "*",
    "yiisoft/yii2-bootstrap": "*",
    "yiisoft/yii2-debug": "*",
    "yiisoft/yii2-gii": "*"
},
// ...

Step 3 – Create your FontAwesome asset bundle

To register the files, we are going to create an asset bundle named FontAwesomeAsset.php and place it on frontend/assets with the following contents:

namespace frontend\assets;

use yii\web\AssetBundle;
class FontAwesomeAsset extends AssetBundle
{
    // The files are not web directory accessible, therefore we need 
    // to specify the sourcePath property. Notice the @vendor alias used.
    public $sourcePath = '@vendor/fortawesome/font-awesome';
    public $css = [
        'css/font-awesome.css',
    ];
}

Register the files!

There are a couple of ways of doing it.

The following example is if you wish to register the bundle on a specific view:

// this code is written on that specific view
use frontend\assets\FontAwesomeAsset;

FontAwesomeAsset::register($this);

But it could be that you wish to use it as part of another asset bundle or globally registered on your application. For the following example, we going to registered as part of the main application asset bundle AppAsset:

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'css/site.css',
    ];
    public $js = [
    ];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
        // here we add our FontAwesomeAsset bundle class
        'frontend\assets\FontAwesomeAsset'
    ];
}

If you check your frontend/views/layouts.php file you see how AppAsset registers the files.

use frontend\assets\AppAsset;

/**
 * @var \yii\web\View $this
 * @var string $content
 */
AppAsset::register($this);


[ad]

Yiinitializr: The Library

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


[ad]

Yiinitializr: Maximum acceleration for your Yii project start!

The history… we remember the days when we thought that YiiBoilerplate was a good fit for any project. They were good days, but we were being naive.

Every project has different needs, and it’s those needs that set the requirements. Also, lets be realistic, if you were to develop a project where only the frontend UI with a small admin section was needed, Yiinitializr was overkill. In the end, people had to remove unneeded folders, the configuration was unnecessarily complex, a lot of people were not certain where to place the components and there were many other issues.

At 2amigOS! we were slamming our heads down on our keyboards trying to figure out what was the best way to provide a project boilerplate that could fit everyones needs. We soon realized and agreed that composer was the best way to go as a dependency manager (special shout-out thanks to Mr Tobias Schmunk, the guy behind Phundament for his great work and ideas), but we did not want to provide a fixed structure nor a set of extensions, again. Otherwise, we would just be putting a fresh coat of paint on the same problems. We wanted to give the power back to the developer to pick and choose based on their own needs. You know your project the most, so you should be able to set your own desired folder structure. You should be able to select which extensions you want to have pre-installed. And that, my amigos, is how Yiinitializr was born!

4Y9RS

Yiinitializr is technically still in beta (?). Why? Because we believe that we need your feedback, yes you, from the Yii community, to make Yiinitializr right for all of us. You’re going to be using it, often (c’mon, you know you will…), so why not have a say in whether it’s enough or not… in what else it should or should not provide.

Okay, okay.. enough talk… now, let’s see how this baby works!

Yiinitializr is extremely easy to use. It is composed of only one page that will ask you three simple things:

1. What template type do you want to use? Basic, Intermediate or Advanced

Captura de pantalla 2013-04-13 a la(s) 00.05.32
2. Which extensions do you want pre-installed? Just search and select… really.. that’s all… no kidding… cool, huh?

0WDkW
3. Okay… maybe we misspoke… it’s really 3 steps; not questions. Download your finished project boilerplate!

ICVY8
4. What? Step 4? Maybe we can’t count, but you need to know what to do with the file you just downloaded, right? Well, here’s what you need to do:

Unzip, wherever you want your project to be, then (no, we are not going to tell you how to setup your database configuration. This is just a gentle reminder that you need to do that next…). Ahem… make your database configurations.
Now, run the following commands inside the unzipped project’s root:

// make sure you have the latest version of composer
php composer.phar self-update
// run your installation
php composer.phar install

Now, relax and love it! (or hate us, but keep it to yourself… really, all that negativity focused on us? We’re amigos! Come and share in the enchiladas… click on the docs below the templates to go to that github place and vent there…)

So, now you’re saying, “yeah, man… that is simple, but what are the template differences?”. We thought you’d never ask:

  • Basic: The small in scope project. Is your project just a frontend, or maybe a frontend with an admin interface? Well, this is the basic one, and it contains only /app and /www. Yes, you can still choose the extensions you want.
  • Intermediate: Your needs are maybe a little more complex than the basic offers, but you don’t want to go crazy. This one is closest to the structure you might be familiar with from YiiBoilerplate, but it’s much much lighter. Intermediate has a good solid structure. It contains: /backend, /common, /console and /frontend, and this structure will work for most of your robust applications. Need more?
  • Advanced: Now you’re talking! The advanced structure adds on the /api directory for your web services. Need we say more? Got ideas of world domination? It starts here! 😉

“But I want more details!” Yes, we agree, and this a great point to start the share of some knowledge. We know that once you download any of the template boilerplates you’ll start wondering what’s going on here. What the heck is this way of initializing applications? Check out the yiic.php or the index.php scripts within any of the application’s folder. See what we are doing. There is another surprise extension within, the Yiinitializr components. A set of classes that makes for a really easy way you can configure and install a project.

More documentation and discussion will be coming… we promise. We just wanted to let you play and react a little, first.


[ad]