My favourite new Laravel 5 feature: Events and event listeners

Laravel 5 has been out for a while now and I’ve had a chance to write some code using all the new features apotheke online cialis. So: what stands out as my favourite feature so far? The answer is events and event listeners

In Laravel 4 you might see some code in the controller like this:

public function processContact(Request $request)
$user = new Student();
$workshop = $event->getWorkshop();
if(!$user->isStudent($Input::get('name'),$event->getRequest()->get('email'))){
    $user->fill($request);
    $user->status = 'C';
    $user->profile = $this->getProfile($request);
    $user->save();
}else {
    $user = $user->getByEmailAndName($event->getRequest()->get('name'),$event->getRequest()->get('email'));
}


if(!$user->isRegistered($user->name,$user->email, $workshop->id)){
    $user->workshops()->attach($workshop->id, ['sign_date'=>date('Y-m-d H:i:s')]);
}
 return $this->getView('contact_done');
}

In Laravel 5, it’s been tidied up so you can do this:

public function processContact(Request $request)
{
    $this->validate($request, [
        'name' =>'required',
        'email' => 'required|email',
        'comments' => 'required'
    ]);

    Event::fire(new ContactEvent($request));

    return $this->getView('contact_done');
}

All the event code in this example has been moved to a ContactListener class

Laravel Multi-tenant multi-site setup

Recently I needed to create multi-tenant set up in Laravel. I had an existing site which was running on a url. The client wanted a new site with a separate database with a different url. I could have just cloned the existing site and used it but that would have meant 2 separate code bases. Instead, I decided to have 2 databases and one code base. I found some useful documentation at:

https://medium.com/laravel-4/laravel-4-multisites-26cdc75e4810#.yeqca98z2

  • Set up new site in Nginx
  • Create config folder called construction (the site was running under a url with something like construction.myurl.com
  • Create folders for new site  with bootstrap folder
  • Sym link folders from main site
  • Created database
  • Created a new file bootstrap/environment.php
  • Update bootstrap/start.php
$env = $app->detectEnvironment(function() use($app){

    if(isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] == 'construction.myurl.com'){
        return require '/pathtosite/construction/bootstrap/environment.php';
    }

    if(file_exists( __DIR__.'/environment.php')){
        return require __DIR__.'/environment.php';
    }

    return $app->detectEnvironment(array(
        'local' => array('localhost.localdomain','localhost')
    ));

});


Everything worked out fine.

I then created a new config file called config/site.php and config/construction/site.php which contained all the site specific strings that I needed.

Working with the PHP Laravel Framework

laravel-logo-bigI’ve worked with Laravel for about a year and half now and it’s the third PHP framework I’ve  learned so far (the others are Code Iginiter (2 projects) and Zend (1 project).

So, what’s to like about Laravel and what are the niggles?

As a coder, there’s lots to like about Laravel. The code is clean and well written. It follows all the best Object Oriented practices, uses patterns and is generally easy to read.

Niggles: It’s definitely the pet project of the guy who created it, Jeffrey Way. That means whatever he decides goes. Expect some quite quirky bits of code.

The main niggle, which also happened with Zend, is the project structure has changed in a way to make an upgrade really complicated. With Zend, the upgrade from Zend 1.2 to Zend 2.0 meant that you had to substantially re-write your project. This was a major annoyance on lots of levels. It increased the cost to the client and it also meant I had to learn Zend again.

Having written a fair amount of code in Laravel 4.2 for a client, I took a look to see if I could easily update it to Laravel 5.1 Answer, not at all. I took nearly a whole day to experiment on this and only managed to get some basic pages up.

I’ve written a simple Laravel 5 project to demo my code. There wasn’t that much to relearn once I had got used to the project structure. The major thing I can see is the addition of middleware.

Laravel is still a great framework to work with and I look forward to doing further work on it.

Installing Redis to use as Laravel 4 cache

The following commands will install redis on a server running CentOS 6.4.

First, install the epel repo

sudo rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm 

Next, install the remi repo

sudo rpm -Uvh http://rpms.famillecollet cialis bestellen ohne rezept.com/enterprise/remi-release-6.rpm 

Now, you should be able to install redis using the yum package manager.

yum install redis -y http://codybonney.com/installing-redis-on-centos-6-4/
http://codybonney.com/installing-redis-on-centos-6-4/

mkdir /usr/share/redis
cd /usr/share/redis
git clone https://github.com/ErikDubbelboer/phpRedisAdmin.git
cd phpRedisAdmin
git clone https://github.com/nrk/predis.git vendor
ln -s /usr/share/redis/phpRedisAdmin /vagrant/public/redis

in local/config/database.php

'redis' => array(
'cluster' => false,
'default' => array(
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
),
)
'driver' => 'redis',
  • Find out the name of service’s script from /etc/init.d/ directory e.g. redis
  • Add it to chkconfig
    sudo /sbin/chkconfig --add redis
  • Make sure it is in the chkconfig.
    sudo /sbin/chkconfig --list redis
  • Set it to autostart
    sudo /sbin/chkconfig redis on

					

Updating PHP memory limits with Nginx

I needed to update the PHP memory limits.

Running phpinfo() showed that the php.ini file was in /etc/php.ini so I updated the file and restarted nginx

Nothing happened, the memory limit remained the same.

I found that I need to restart the php-fpm service to get it to update

service php-fpm restart

It’s also worth reading this article for more details

https://rtcamp.com/tutorials/php/increase-script-execution-time/

Unit testing Laravel 4 Auth extension

Laravel 4 is a great framework, it has all sorts of good stuff like IoC, automatic injection of Models into Controllers based on routes.

However, if you try and unit test a custom extension to the Auth package, you will find that some of the tests fail.

Here’s the code:

/**
 * ----------------------------------------------------
 * Extend the Auth functionality
 * to allow admin user to switch users
 * ----------------------------------------------------
 */
Auth::extend('eloquent', function($app) {
    $hasher = new \Illuminate\Hashing\BcryptHasher();
    $user_class = '\Repository\User\EloquentUserRepository';
    $provider = new \Illuminate\Auth\EloquentUserProvider($hasher, $user_class);
    return new CustomAuthGuard($provider,  App::make('session.store'));
});

This works fine if you test it by clicking through but this unit test failed

public function testLoginAsUser()
{
     $login_user = EloquentUserRepository::find($this->admin_user_id);
     $this->be($login_user);
     $this->assertEquals(Auth::user()->id, $this->admin_user_id);
}

The problem turned out to be in the way that the ‘be’ function set the logged in user

public function be(UserInterface $user, $driver = null)
{
     $this->app['auth']->driver($driver)->setUser($user);
}

The Auth::user() function finds the user by checking the session for the user id and then querying that user against the UserProvider. It relies on a session key ‘login_’+md5(class name). In testing, this is not being picked up. The solution I found was to use this instead.

public function testLoginAsUser()
{
     $login_user = EloquentUserRepository::find($this->admin_user_id);
     Auth::login($login_user);
     $this->assertEquals(Auth::user()->id, $this->admin_user_id);
}