Bone MVC Framework v3 released

vX.Y.Z – Major.minor.patch – or, BC breaks, features, hotfixes! The best software would be 1.∞.x, as that would mean an absolute tonne of new features have been added, without breaking any backwards compatibility!

Having said all of that, I would now like to present my latest BC break, and announce the release of Bone MVC Framework v3.0 😀

https://bonemvc.delboysplace.co.uk/en_PI

What’s new? Quite a lot. Try it out! We (I) ripped out the old Bone Router and replaced it with league/route, a PSR-15 middleware router based on Fastroute! We replaced Pimple with delboy1978uk/barnacle, a PSR-11 wrapper for Pimple (Pimple has a PSR-11 wrapper but it doesn’t implement the interface correctly and so doesn’t work. Fabien Potencier has went in a huff with the PHP-Fig group so I didn’t bother sending him a Pull Request 😐). Both of these improvements have allowed for a far more flexible and modular approach to site building, as you will see if you try it out!

Ok then, let’s see it in action

The recommended approach is to use Docker, as this means you can get the identical dev enironment that I do, regardless of your operating system. If you don’t wish to take this approach, you can set a virtualhost and database yourself.

Docker VM dev environment setup

To get the Docker VM working, make sure you have Git, VirtualBox (or VMWare), and Docker installed. Once you do, open a terminal window. We need to run a one off command, telling Docker to create a VirtualBox VM which will be your new Docker Machine.

docker-machine create --driver virtualbox default

You now have a Docker Machine. So, the usual process when you would like to begin coding ais as follows:

docker-machine start

Now it’s started, run this for every tab you open in the terminal to set up environment vars in your terminal

eval $(docker-machine env)

Installing Bone MVC Framework

By default, we use a fake domain https://awesome.scot, so sudo nano /etc/hosts and add the following:

awesome.scot 192.168.99.100

Now if you cd into wherever you wish to store the project (~/Sites in my case), we can clone the framework skeleton project:

git clone https://github.com/delboy1978uk/bonemvc
cd bonemvc

Inside the skeleton files, you’ll see a docker-compose.yml, and a build folder. If your’e nosey, have a look and you’ll see how it works! The VM comes with Apache, PHP 7.3, XDebug and a stack of PHP modules, Composer, Mariadb, Mailhog, self signed SSL certificate, and most of the stuff you need. Lets start it up.

docker-compose up

This will take a few minutes the first time you do this, but thereafter should be a lot faster, even with different Bone MVC projects in different folders.

At this point, your terminal is now tailing the logs from each of your services, mail, php, apache, mariadb, and so we need another tab open as we want to log into to the Linux VM to run composer. Remember when you open a new tab, you need to run the eval command again to get the environment variables.

eval $(docker-machine env)
docker-compose exec php /bin/bash

At this point, you’ll notice a slight change in your shell’s look. We are now logged into the server! Lets install the dependencies and we are ready to rock!

eval $(docker-machine env)
docker-compose exec php /bin/bash
composer install

Once composer is finished doing it’s thing, we are ready to browse to the project! Open https://awesome.scot in your browser, and you should see the following!

Okay great, so how is it all structured?

As per most projects these days, the main entrypoint is public/index.php, and all public assets are installed in public/. Bone use the environment variable APPLICATION_ENV to differentiate between your dev setup and staging, production, etc.

The build folder is part of the Docker setup as mentioned earlier, so can be ignored.

The config folder allows for subfolders based on the APPLICATION_ENV, which will override the config files sitting directly under config/. You can add as many .php files into these folders that you like.

The data folder containsa variety of things. There is a cache storage folder (delboy/bone-cache coming soon), a logs folder (delboy1978uk/bone-log coming soon), a proxies folder (for doctrine entity proxies if using delboy1978uk/bone-doctrine), a translations folder with several languages pre-configured (use poedit to edit these files), and an uploads folder.

The migrations folder is use to store database migrations if using delboy1978uk/bone-doctrine.

The src/ folder contains your applications modules, and currently only contains one module, App.

Inside src/App, you will see a class called AppPackage.php, look inside!

All packages implement RegistrationInterface, and any packages containing controller routes will also implement RouterConfigInterface. addToContainer() allows you to create object factories so you can inject any dependencies. In the AppPackage, the Controller requires the view engine so it can render pages, so we create a controller factory and pull the view from the container (view is set up automatically by Bone):

    /**
     * @param Container $c
     */
    public function addToContainer(Container $c)
    {
        $c[IndexController::class] = $c->factory(function (Container $c) {
            $view = $c->get(PlatesEngine::class);
            return new IndexController($view);
        });
    }

The addRoutes() method tells the router which actions in which controller to call.

    /**
     * @param Container $c
     * @param Router $router
     * @return Router
     */
    public function addRoutes(Container $c, Router $router): Router
    {
        $router->map('GET', '/', [IndexController::class, 'indexAction']);
        $router->map('GET', '/learn', [IndexController::class, 'learnAction']);

        return $router;
    }

If you have Doctrine entities, return true in the hasEntityPath() method, and return the path to the Entity folder in the getEntityPath() method.

Controllers now just take in a PSR-7 request, and return a PSR-7 Response. However we can wrap the request and response in middleware! See league/route docs for more info.

For a bit of fun, I’ll show you a module with a Doctrine entity, and just how quickly you can add a new feature! In the VM CLI, type the following:

composer require delboy1978uk/bone-doctrine
composer require delboy1978uk/bone-gentest

You now have the doctrine and my test entity package in the vendor folder.

Open config/packages.php, and add the two packages.

<?php

use BoneMvc\Module\App\AppPackage;
use BoneMvc\Module\BoneMvcDoctrine\BoneMvcDoctrinePackage;
use Random\Developer\JediPackage;

return [
    'packages' => [
        AppPackage::class,
        BoneMvcDoctrinePackage::class,
        JediPackage::class,
    ],
    'viewFolder' => 'src/App/View'
];

Ok, so we have entities need migrated to the database. In the VM CLI, type the following:

migrant diff
migrant migrate

You’ll notice that migrant is just Doctrine migrations, but tweaked for usage with Bone MVC. Now you have migrated, head over to https://awesome.scot/jedi

You now have a demo module with an index list page, add edit and delete functionality, with form filtering and validation and rendering done via delboy1978uk/form. Have a look through the module code to see how to set everything up!

Please play around and have fun with it, and feel free to leave any comments!

Manually compiling PHP modules successfully

This look familiar?

PHP Warning:  PHP Startup: memcached: Unable to initialize module
Module compiled with module API=20090626
PHP    compiled with module API=20100525
These options need to match

I don’t know about you, but i like to be up to date! My PHP is on 5.5, and I had to install some modules. But sometimes, old versions can rear their ugly head, and cause all manner of grief. Package managers do a good job to take care of all this for you, but sometimes they just don’t work. Leaving you to compile yourself! So lets do it! I’m going to install memcached, and then the imagick libraries (now i know what i’m doing!)

I’m doing this on a CentOS 6 server, but as we are doing the old skool way of compiling etc, this should work on any other flavour of Linux, or indeed Mac OS X.

First step is to download your .tar.gz  then unzip it with tar -zxvf file.tar.gz and change into the folder.
Bring up a web page displaying your servers php.ini. You are looking for the version of PHP API, and the extension_dir.
In your terminal, cd into the module source code folder, and type phpize.

If when you check the API versions , they are different from your php.ini, then an old version of php is being used in the terminal, and your module will not work! In this case, you need to get it to use the correct phpize.

type 'which phpize' to find out where the offending file is. (mine was /usr/bin/phpize)

My PHP appeared to be in /usr/local, so I tried running /usr/local/phpize. The API’s matched. So then I did the following:

mv /usr/bin/phpize /usr/bin/phpize-old
 ln -s /usr/local/bin/phpize /usr/bin/phpize

Half way there! We need to do the same for php-config

mv /usr/bin/php-config /usr/bin/php-config-old
 ln -s /usr/local/bin/php-config /usr/bin/php-config

Now you have done that, installation should be trivial, and work as per loads of tutorial/instrruction pages on the web.

./configure
 make
 make install

Finally edit your php.ini and add ‘extension = memcached.so’ (or whatever module you compiled), and restart your apache server!

EDIT : you may need to run ‘phpize –clean’ if it is still compiling with the older stuff from within the modules source folder

Using Zend Framework 2 – Modules & Composer

ZF2 is totally redefining PHP development, I love the direction they are going! Anyway, those who have shown interest will no doubt have played with Akrabats tutorial on the zf2 site. I for one have, and I also went and met the guys themselves at the PHPNW2012 Conference in Manchester at the start of this month! The ZF2 tutorial day was great! Thanks Evan & Rob! Anyway, i’m straying off topic here.

It’s all about the modules! Most sites have a login! A blog! A contact form! Facebook? Twitter? Whatever! Why reinvent the wheel? http://modules.zendframework.com allows you to choose from a growing number of modules, and installing them is a piece of cake (i should stop saying that, this is zend!) using the PHP Composer. So let’s have a look!

Completely starting from scratch, bung this in your Apache’s VirtualHosts config, tweaking the path to wherever your site is:

<VirtualHost *:80>
 ServerName zf2
 DocumentRoot /path/to/my-site/public/
 SetEnv APPLICATION_ENV "development" 
 <Directory /path/to/my-site/public/>
 DirectoryIndex index.php
 AllowOverride All
 Order allow,deny
 Allow from all
 </Directory>
</VirtualHost>

Now you’ve done that, time to install the Zend Framework Skeleton Application, by cloning it from the Git repository. Go into your sites folder, and say:

git clone git:/github.com/zendframework/ZendSkeletonApplication.git my-site
cd my-site
ls

You’ll notice a composer.json in there. Open this up, and you’ll see it depends on PHP and zendframework. In the command prompt:

php composer.phar self-update

This updates composer to the latest version, since it has updated its version since the SkeletonApplication was released. Then:

php composer.phar install

Composer kicks in, and downloads our dependency (zf2), after having made sure you have a sufficient version of PHP (>=5.3).

What’s this? ZF2 recommends installing more modules? Fine, lets do that, but first, lets choose even more modules to add! Change your composer.json to look like this:

{
 "name": "zendframework/skeleton-application",
 "description": "Skeleton Application for ZF2",
 "license": "BSD-3-Clause",
 "keywords": [
 "framework",
 "zf2"
 ],
 "homepage": "http://framework.zend.com/",
 "minimum-stability": "alpha",
 "repositories":[
{
 "type": "composer",
 "url": "http://packages.zendframework.com/"
 }],
 "require": {
 "php": ">=5.3.3",
 "zendframework/zendframework": "2.*",
 "doctrine/doctrine-orm-module": "dev-master",
 "doctrine/doctrine-module": "dev-master",
 "zendframework/zendpdf": "2.*",
 "zendframework/zendservice-recaptcha": "2.*",
 "symfony/yaml": "dev-master",
 "zendframework/zend-developer-tools": "dev-master"
 }
}

I’ve deliberately left two of ZF2s recommendations out of this, as they’re actually pecl extensions, not models, and I ain’t covering that just now, but I added Doctrine functionality. So, to get all this new stuff, we tell Composer to go update itself!

php composer.phar update

And bang, we now have the modules downloaded into the vendor folder. So! How to use them, I hear you cry? Well, the example I’ll show you is probably the best example to start with, and indeed, was the module we were shown at Evan & Rob’s ZF2 Tutorial day at PHPNW2012! ZfcUser.

Goto http://modules.zendframework.com
Scroll down to ZfcUser (formerly EdpUser) (that’s Evan btw) and click, which will take you to the github page.
Scroll down to Requirements. You’ll see you also need ZF2 and ZfcBase to use this module. We have ZF2, but not the ZFCommons base use Classes, so we’ll install both of these. Again, a simple case of adding the lines, then running php composer.phar update. Watch out for unnecessary tabs, brackets, and commas, or the json parser will take a fit!

"zf-commons/zfc-base": "dev-master",
 "zf-commons/zfc-user": "dev-master"

Great! All running smoothly I see! So jump in the ZfcUser module in the vendor folder and go into data, there you’ll get the sql for creating your user table. Run that on your MySQL in your database server, and you’re ready to rock! Now we just need to enable the modules (I’ll only show the relevent ones for the example, so I won’t be using the Doctrine stuff for now) and set up our db connection.

Stick your DB parameters in the config autoload local php file:

return array(
 'db' => array(
 'username' => 'user',
 'password' => 'pass',
 ),
);

and in the global file, we’ll put the meat and bones (the local php file is in .gitignore, which is why we keep the credentials there):

return array(
 'db' => array(
 'driver' => 'Pdo',
 'dsn' => 'mysql:dbname=my-site-db-here;host=localhost',
 'driver_options' => array(
 PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
 ),
 ),
 'service_manager' => array(
 'factories' => array(
 'Zend\Db\Adapter\Adapter'
 => 'Zend\Db\Adapter\AdapterServiceFactory',
 ),
 ),
);

Now if you open the application config you’ll see an array called modules, where we register the modules our application uses. Change it to this:

'modules' => array(
        'Application',
'ZfcBase', 
'ZfcUser'
    ),

And that’s literally it! try browsing to /user/login! register and login! with Gravatars and everything!

The really great thing about all of these modules is that they are extensible. Is something not happening in a module quite the way you would like it? Write a module extending it!
For instance, my first thought about ZfcUser was ‘what about activating your account by email when you register? Well, guess what? There’s a module for that. Evan told me to go check out CdliTwoStageSignup! (extending ZfcUser)

Working in this manner really is getting to the stage where functionality is literally drag, drop, ‘n’ tell your app! And by studying a module’s code, especially a module extending another module, we can start to see how it all connects up through the service and event managers, and how it’s all tied together! But that’s for you to mess around with! Have fun!