How to minimise CRUD front-end code duplication in Laravel 5.4 / Twig

CRUD (Create/Read/Update/Delete) is something that developers do quite a bit of. Frameworks can help with this, but there’s still a fair amount of code you’ll need to write for every CRUD screen you put together.

One particular area is the difference between Create and Update. For many of the projects I’ve worked on, Create and Update are often very similar. They aren’t identical, but if there’s enough overlap between them, you can minimise duplicate code with the following setup.

Continue reading “How to minimise CRUD front-end code duplication in Laravel 5.4 / Twig”

Advertisements

How to display errors in Laravel 5.4 with Twig / TwigBridge

As Laravel ships with Blade, the Laravel manual gives templating examples in Blade.

For displaying basic variables in a Twig template, it’s pretty simple:

{{ title }}

However, it takes slightly more effort to display form validation errors.

Continue reading “How to display errors in Laravel 5.4 with Twig / TwigBridge”

Rebuilding the post editor at City AM

When I joined City AM, one of the first things I experienced was the post editor. It did the job, but it was not particularly quick or intuitive to use. We had to add new fields in a predefined way – and doing so usually added extra work for the content team. Plus, there were a number of tasks that had to be done outside the system – such as finding and resizing images from Getty.

I knew we needed to take a radical approach and consider scrapping the existing post editor.

Continue reading “Rebuilding the post editor at City AM”

How to migrate from one PHP framework to another – gradually

Picture the scene: Your development team is getting more and more frustrated with the framework that a project was built on. Or you’ve taken on a new project, and the code is a mess. You don’t want to be stuck with that codebase forever.

In a large project, you may not have the option or the time (or indeed the desire) to do a big bang migration from one framework to another. The company may not let you do it. Aside from being boring work, it’s also pretty risky – and it could absorb a large chunk of time. Or it’ll never be completed.

The first thing you should do is trial the new framework, either as a dummy project or with a safe copy of your current project. Basically, make sure this is a move you want to make. You don’t want to start another migration before the first one’s done…

Once you’re sure you want to proceed, here’s what to do. (Hopefully it goes without saying this shouldn’t be done directly in production…)

1. Rename the index file to index-old-fw, or whatever the name of the old framework is. For instance, if you wanted to move away from CakePHP (I’m choosing a framework at random here), you might rename index.php to index-cake.php.

This will break everything.

2. Take the index file for the new framework, and name it according to your new framework. Let’s say you’re using Laravel – you might rename index.php to index-laravel.php.

3. Now create a new index.php and write some simple logic that will map to one framework or the other. Something like this:

<?php
$laravelPaths = array('/test-laravel');
if (in_array($_SERVER['REQUEST_URI'], $laravelPaths)) {
  require 'index-laravel.php';
} else {
  require 'index-cake.php';
}

(This is a really simple example; you’ll need to modify it for partial matches to handle things like query parameters later. For now the point is to get one page working on the new framework.)

4. Put the new framework code in a logical folder so it can be loaded in the new index file. This largely depends on how your current framework is set up. You probably won’t want to mix two frameworks in the same folder, as folders may have overlapping names – possibly even files. You’ll have to handle all the paths for the new framework in your new index file. The goal is to keep all your existing pages working fine on the old framework.

5. Set up the new test page in the new framework.

By now you should start to see how it’s possible to mix frameworks in a project. This isn’t a permanent solution; it allows you to start using a new framework and gradually migrate across to it.

The early part of a migration will be tricky. Unless you can reuse API code across both frameworks, you’ll probably need to rebuild a lot of code in the new framework. This is a perfect opportunity to write unit tests if you’re not already using them. Focus on building one page (a good one is a static page, such as your About page or another page that doesn’t do much) – to do this you’ll need to build a lot of the core “scaffolding” code such as getting your site theme to display properly, connecting to the database (less important for static pages but needed later), and then things like logins and so on.

As you progress onto other pages, it will get easier as a lot of the base work can be reused. You’ll need to update the URL list in your index file to map specific URLs to the new framework as pages get moved. You can write code to handle wildcard URLs so you can move entire sections of your site to the new framework, e.g. product landing page. It’s a lot of work but it can also help to rationalise your entire site, especially if there’s a lot of odd standalone pages that nobody really remembers creating!

Once the base code for the new framework is in place, you’ll have a big advantage and a big disadvantage with future work:

  1. Advantage: New functionality can be built entirely on the new framework.
  2. Disadvantage: Repetition/duplication across the two frameworks – especially with theme files.

You can improve the situation by building bridging code that will help you to migrate. Code that is framework-agnostic and can be used by both frameworks.

Keep track of how many URLs you have across the site and how the migration is going. At some stage you’ll reach a “midpoint”, which is when you need to replace your URL array. Instead of sending only specific URLs to the new framework, send everything except the URLs you specify in that direction. This requires good knowledge of your application architecture, but it can be done. Remember you can use wildcards to target entire sections that need to stay on your old framework for the time being.

I won’t claim this to be a particularly clever or elegant way to do things, but it works. So far, I’ve used it for the following migrations:

  • deprecated in-house legacy framework => Zend Framework 1
  • Drupal 7 => Laravel 4.2
  • custom framework => CodeIgniter
  • custom framework => rebuilt custom framework

Hope it’s of use to someone.

Setting up Twig in Laravel

Re-posted from my old blog

This week, I have been mostly trying… Laravel.

Trying a new PHP framework raises a few questions. What coding style does it use? How do you build models? What do templates look like?

When trying Laravel for the first time, I wasn’t keen on the Blade templating engine. So I decided to look for how to integrate Twig. One quick Google search later, and I found TwigBridge by Rob Crowe.

Following the instructions was simple enough. However, I think there was one thing missing. What do you name your template files so Twig can find them?

How to name Twig templates in Laravel

In Laravel, a Blade template for the “users” route would be called: users.blade.php

After a bit of experimenting, I found that the equivalent Twig template would be called: users.twig

This works out nicely in PhpStorm, as suddenly the file icon changed from a PHP file to a bit of green grass (maybe it looks better than a twig). And the code completion works. That’s much better than the last project I set up with Twig, which is on Zend Framework v1 and the files are named index.html.

Don’t forget to rename your base template to base.twig or similar. The Blade equivalent I created in the QuickStart guide was called layout.blade.php.

Comparing Blade and Twig templates

So, just for completeness, here’s a sample Blade template:

@extends('layout')
@section('content')
 @foreach($users as $user)
 <p>{{ $user->name }}</p>
 @endforeach
@stop

And here’s a Twig template:

{% extends "base.twig" %}
{% block content %}
{% for User in UserList %}
<p>{{ User.name }}</p>
{% endfor %}
{% endblock content %}

So far, I’m liking Laravel, but I’m much happier with Twig than Blade.