I'm a web developer in Norfolk. This is my blog...

Most web apps have at least some need for some additional flat pages, for purposes such as:

Terms and conditions

Cookie/privacy policy

FAQ

You can of course hard-code this content in a view file, but if this content is likely to change often it may be useful to give the site owners the capability to manage this themselves.

Laravel Flatpages is a package I wrote that adds a flatpage model, controller and view to your application. It’s loosely inspired by Django’s flatpages app. Using it, you can quickly and easily build a very simple brochure-style CMS. Each page contains fields for the title, content, slug, and an optional template field that specifies which view to use.

Note that it doesn’t include any kind of admin functionality, so you’ll need to add this yourself or find a package for it. It uses my repositories package to access the database, and this has caching built in, so when you create, update or delete a flatpage, you should either resolve Matthewbdaly\LaravelFlatpages\Contracts\Repositories\Flatpage and use the methods on that to make the changes (in which case the appropriate caches should be flushed automatically), or flush the cache. It also requires a cache backend that supports tags, such as Memcached or Redis.

It does not include routing in the package itself because I couldn’t find a way to guarantee that it would always be the last route, so instead you should put this in your routes/web.php and make sure it’s always the last route:

Otherwise you could wind up with problems. The reason for that is that it has to check the path against the slugs of the flat pages in the database, and if it doesn’t find any it raises a 404.

Or, if you prefer, you can use the middleware at Matthewbdaly\LaravelFlatpages\Http\Middleware\FlatpageMiddleware, which may be more convenient in many case. This should be added as the last global middleware in app\Http\Kernel.php.

This will create a new folder that includes a src folder containing a service provider, and a tests folder containing a preconfigured base test case, as well as a simple test case for tests that don’t need the full application instantiated, in order to help keep your test suite as fast as possible.

In addition, it includes configuration files for:

PHPUnit

PHP CodeSniffer

Travis CI

That way you can start your project off the right way with very little effort.

I’ve also added my Artisan Standalone project as a dependency - that way you can access any Artisan commands you need to generate files you need as follows:

$ vendor/bin/artisan

Hopefully this package should make it a lot easier to create new Laravel packages in future.

Recently I’ve been building and publishing a significant number of Laravel packages, and I thought I’d share details of some of them over the next few days.

Artisan Standalone is a package that, when installed in a standalone Laravel package (eg, not in an actual Laravel install, but in a package that you’re building that is intended for use with Laravel), allows you to use Artisan. It’s intended largely to make it quicker and easier to build functionality as separate packages by giving you access to the same generator commands as you have when working with a Laravel application. It came about largely from a need to scratch my own itch, as when building packages I was having to either run Artisan commands in a Laravel app and move them over, or copy them from existing files, which was obviously a pain in the proverbial.

You can install it with the following command:

$ composer require --dev matthewbdaly/artisan-standalone

Once it’s installed, you can access Artisan as follows:

$ vendor/bin/artisan

Note that it doesn’t explicitly include Laravel as a dependency - you’ll need to add that in the parent package to pull in the libraries it needs (which you should be doing anyway). It’s possible that there are some commands that won’t work in this context, but they’re almost certainly ones you won’t need here, such as the migrate command. As far as I can tell the generator commands, which are the only ones we’re really interested in here, all work OK.

While the documentation for creating Artisan tasks is generally pretty good, it doesn’t really touch on creating tasks that generate new files. The only way to figure it out was to go digging through the source code. In this case, I was building an Artisan command to create Fractal transformers as part of a package I’m working on.

There’s a specialised class for generating files at Illuminate\Console\GeneratorCommand, which your command class should extend instead of Illuminate\Console\Command. In addition to the usual properties such as the signature and description, you also need to specify $type to give the type of class being generated. Also, note that the constructor is different, so if you use php artisan make:console to create the boilerplate for this command, you’ll need to delete the constructor.

<?php

namespaceMatthewbdaly\MyPackage\Console\Commands;

useIlluminate\Console\GeneratorCommand;

useSymfony\Component\Console\Input\InputArgument;

classTransformerMakeCommandextendsGeneratorCommand

{

/**

* The name and signature of the console command.

*

* @var string

*/

protected $signature = 'make:transformer {name : The required name of the transformer class}';

/**

* The console command description.

*

* @var string

*/

protected $description = 'Create a Fractal transformer';

/**

* The type of class being generated.

*

* @var string

*/

protected $type = 'Fractal transformer';

/**

* Get the stub file for the generator.

*

* @return string

*/

protectedfunctiongetStub()

{

return__DIR__.'/stubs/transformer.stub';

}

/**

* Get the console command arguments.

*

* @return array

*/

protectedfunctiongetArguments()

{

return [

['name', InputArgument::REQUIRED, 'The name of the command.'],

];

}

/**

* Get the default namespace for the class.

*

* @param string $rootNamespace

* @return string

*/

protectedfunctiongetDefaultNamespace($rootNamespace)

{

return $rootNamespace.'\Transformers';

}

}

Note the getDefaultNamespace() method. If your class will live directly under the app folder this is not necessary. Otherwise, it needs to return the root namespace, with the folder structure you want after it. Here my class will live under app\Transformers, so I’ve set it to reflect that.

Also, note the getStub() method. This tells Artisan that it should use the specified stub file as the basis for our class. Below you’ll find the stub file I used for my transformer:

<?php

namespaceDummyNamespace;

useMatthewbdaly\MyPackage\Transformers\BaseTransformer;

useIlluminate\Database\Eloquent\Model;

classDummyClassextendsBaseTransformer

{

publicfunctiontransform(Model $model)

{

return [

'id' => (int) $model->id,

];

}

}

Note that the DummyNamespace and DummyClass fields will be overwritten with the correct values.

Once this Artisan command is registered in the usual way, you can then run it as follows:

$ php artisan make:transformer Example

And it will generate a boilerplate class something like this:

<?php

namespaceApp\Transformers;

useMatthewbdaly\MyPackage\Transformers\BaseTransformer;

useIlluminate\Database\Eloquent\Model;

classExampleextendsBaseTransformer

{

publicfunctiontransform(Model $model)

{

return [

'id' => (int) $model->id,

];

}

}

You can then replace the model with your own one as necessary, and add any further content to this class.

For many applications, using UUID’s as the primary keys on a database table can make a lot of sense. For mobile or offline apps, in particular, they mean you can create new objects locally and assign them a primary key without having to worry about it colliding with another object that was created in the meantime once it gets synchronised to the server. Also, they are less informative to nefarious users - an autoincrementing value in a URL tells a user that that value is the primary key, and means the app may potentially allow gathering of information via user enumeration (eg calling /api/v1/users/1, /api/v1/users/2 etc).

It’s fairly straightforward to use UUID’s as primary keys on your models when using PostgreSQL. First, you need to set up your migrations to use the uuid-ossp extension and set up the id field as both a UUID and the primary key. You also need to set a default value manually so that if it’s left empty it will generate a UUID for it.

Then, in the model definition, you need to tell Laravel to cast the id field to a string, and explicitly set the primary key to id:

classItemextendsModel

{

protected $casts = [

'id' => 'string',

];

protected $primaryKey = "id";

}

Once this is done, the model should generate the primary keys for you as usual, except as UUID’s. If your application needs to accept UUID primary keys that were created offline, such as in a mobile app, you will probably want to add the id field to the $fillable array on the model to allow this.

About me

I'm a web and mobile app developer based in Norfolk. My skillset includes Python, PHP and Javascript, and I have extensive experience working with CodeIgniter, Laravel, Zend Framework, Django, Phonegap and React.js.