Prefixing API route names in Laravel

The Laravel 5.3 application I am currently working on uses the following resource controllers in the web and api namespace:

// app/routes/web.php
Route::resource('movies', 'MovieController');

// app/routes/api.php
Route::resource('movies', 'Api\MovieController');

This results in the resources being accessible at /movies and /api/movies – so far so good, but the problem I encountered was that now, the web and api routes had the same names (shortened output of php artisan route:list):

POST      | api/movies              | movies.store
GET|HEAD  | api/movies              | movies.index
GET|HEAD  | api/movies/create       | movies.create
PUT|PATCH | api/movies/{movie}      | movies.update
GET|HEAD  | api/movies/{movie}      | movies.show
DELETE    | api/movies/{movie}      | movies.destroy
GET|HEAD  | api/movies/{movie}/edit | movies.edit

GET|HEAD  | movies                  | movies.index
POST      | movies                  | movies.store
GET|HEAD  | movies/create           | movies.create
DELETE    | movies/{movie}          | movies.destroy
PUT|PATCH | movies/{movie}          | movies.update
GET|HEAD  | movies/{movie}          | movies.show
GET|HEAD  | movies/{movie}/edit     | movies.edit

There are two ways to make the route names unique again:

Adding an option to the route definition:

// routes/api.php
Route::resource('movies', 'Api\MovieController', [
    'as' => 'api'
]);

Add the as option in the RouteServiceProvider

// app/providers/RouteServiceProvider.php

protected function mapApiRoutes()
{
    Route::group([
        'middleware' => 'api',
        'namespace' => $this->namespace,
        'prefix' => 'api',
        'as' => 'api.' // Mind the trailing dot (.)
    ], function ($router) {
        require base_path('routes/api.php');
    });
}

And now, everything looks how I want it:

POST      | api/movies              | api.movies.store
GET|HEAD  | api/movies              | api.movies.index
GET|HEAD  | api/movies/create       | api.movies.create
PUT|PATCH | api/movies/{movie}      | api.movies.update
GET|HEAD  | api/movies/{movie}      | api.movies.show
DELETE    | api/movies/{movie}      | api.movies.destroy
GET|HEAD  | api/movies/{movie}/edit | api.movies.edit

GET|HEAD  | movies                  | movies.index
POST      | movies                  | movies.store
GET|HEAD  | movies/create           | movies.create
DELETE    | movies/{movie}          | movies.destroy
PUT|PATCH | movies/{movie}          | movies.update
GET|HEAD  | movies/{movie}          | movies.show
GET|HEAD  | movies/{movie}/edit     | movies.edit

In the end, I settled with defining the prefix in the RouteServiceProvider and defining my routes like this:

Route::resource('movies', 'Api\MovieController', ['except' => ['create', 'edit']]);

because the create and edit routes are not needed in the API namespace.

How to use UUIDs in Laravel/Eloquent models

This article describes quickly how you can use a UUID as a primary key for Eloquent models – I’ll keep it short on purpose, because we all don’t have time for this, and you probably have googled this for ages, as I did :).

Add ramsey/uuid as a composer dependency

$ composer require ramsey/uuid

Create a Trait to be used in your Model

// app/Model/HasUuidAsPrimaryKey.php

namespace App\Model;

use Ramsey\Uuid\Uuid;

trait HasUuidAsPrimaryKey
{
    public static function bootHasUuidAsPrimaryKey()
    {
        static::creating(function ($model) {
            $model->{$model->getKeyName()} = Uuid::uuid4()->toString();
        });
    }

    public function getIncrementing()
    {
        return false;
    }
}

Add a UUID column to your Model’s database table

// database/migrations/xxxx_xx_xx_xxxxxx_create_my_models_table.php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateMyModelsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('my_models', function (Blueprint $table) {
            $table->uuid('id')->primary();
            $table->string('name')->unique();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('my_models');
    }
}

Use the Trait in your Model

// app/MyModel.php

namespace App;

use App\Model\HasUuidAsPrimaryKey;
use Illuminate\Database\Eloquent\Model;

class MyModel extends Model
{
    use HasUuidAsPrimaryKey;

    protected $fillable = ['name'];
}

As the UUID column in the database really just has the type CHAR(32), the performance will probably not be the best. The advantage is that you can continue to use the ID in your routes and queries.

Firebase PHP SDK 2.0

I am really excited (hence the date and time :)) to announce kreait/firebase-php 2.0, as a first beta and welcome everyone willing to give it a try. Version 2.0 is a complete rewrite in PHP 7, and leverages the Firebase REST API to provide a fluent interface to your Firebase Application.

The only reason for it being a beta release is the outdated 1.x documentation, which I will start updating soon. If your IDE supports autocompletion, you should just be fine :).

Firebase PHP SDK 1.0 released, coming up: 2.0

Short Version:


firebase-logo I have never written about it here on my blog, but since last year, I have been developing a PHP SDK to access the Google Firebase Realtime Database – Firebase provides SDKs for JavaScript, iOS and Android, as well as a REST API, but with PHP being my main programming language, I was missing a PHP SDK and that’s how kreait/firebase-php was born.

I never had the feeling that the library was ready for a 1.0 release, because there were so many features to add and so much refactoring to do, but a lot has happened between Version 0.1 (Jan 9, 2015) and Version 0.10.1 (Jul 2, 2016), with the following being the most “disruptive” events:

  • In late 2015, the egeleon/ivory-http-adapter package (which my library is built upon) got deprecated, and I never got to making the switch to its successor, HTTPlug.
  • In early 2016, Firebase introduced Version 3 of their Server SDK, including a new authentication system based on the Google authentication infrastructure. Version 2 of the Firebase Server SDK is still working and maintained, but it will be shut down eventually.
  • PHP 7 was released in December 2015, and PHP 5.5 became an unsupported version in July 2016.

That’s why I started rewriting the PHP SDK some weeks ago, using PHP 7, official Google Libraries and targeted at the latest Firebase developments.

But I still felt bad about my 0.10.x being in pre-release status, so I took the last few days of my vacation to clean up the code base, prettify the documentation and make it a proper 1.0 release.

You can find the new release on the GitHub project page at github.com/kreait/firebase-php and read the documentation at firebase-php.readthedocs.io.

I will continue to support this version at least until the release of Version 2.0, which is currently being developed in the 2.x branch of the repository.

As always, if you have any feedback or suggestions, I’d like to invite you to use the comment form below.

Troubleshooting SSH with public key authentication on Synology DSM 6.0

If SSH keeps asking you to enter your password, although you have set up Public Key Authentication, make sure that file permissions are correct:

cd ~
chown -R `whoami`:users .ssh
chmod 0700 .ssh
chmod 0600 .ssh/* 

Apparently, on a Synology DiskStation, your home dir must be neither group- nor world-writable1:

cd ~
chmod 0755 .

  1. On my DiskStation, all user directories were set to 777 – I don’t remember if this has always been the case, if I did this manually (and why :)) or if this happened during the update to DSM 6.0. 

(Obsolete) How to enable the nginx plugin for Let’s Encrypt

This post is now obsolete, please use Certbot for your SSL certificates: https://certbot.eff.org

In case you haven’t heard already: Let’s Encrypt is a new Certificate Authority that promises an easy way to install their free SSL certificates for any domain. As they now have opened their beta to the public, I was finally able to give it a try.

The installation steps are as easy as they can get:

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto # will install and run the client

As I am not running Apache and the nginx plugin is not included by default1, I had to install it manually:

~/.local/share/letsencrypt/bin/pip install letsencrypt-nginx

After that, the installation was just a breeze:

./letsencrypt-auto --nginx -d www.gamez.name

Et voilà, not even a minute later this website is now secured and it didn’t hurt at all – AWESOME!

How to apply PHP and HHVM settings on Travis CI

To inject PHP settings into the build environment, you can provide an INI file and use it with

before_script:
  - phpenv config-add .travis.ini

Unfortunately, this approach can not be applied for HHVM, as the phpenv command won’t work and HHVM’s php.ini is located in a different directory.

Here is how you can inject the same INI file for both environments:

before_script:
  - if [[ "$TRAVIS_PHP_VERSION" = "php*" ]]; then phpenv config-add .travis.ini ; fi
  - if [[ "$TRAVIS_PHP_VERSION" = "hhv*" ]]; then cat .travis.ini >> /etc/hhvm/php.ini ; fi

Avoid GitHub rate limits when using Composer

If you are using Composer in your project, it is quite likely that at one time, you’ve hit the GitHub rate limits which allow just 60 requests per hour to the GitHub API.

On your local computer, this can easily be bypassed by entering your GitHub login when Composer prompts you to do so, which raises the rate limits to a whopping 5,000 requests per hour. But what can you do when the Composer install/update commands don’t take place on your local machine, but on a CI Server like Travis CI and Jenkins, or during the provisioning of a Virtual Machine, where you are not able to interactively enter your login information?

In this article, I’d like to show you three ways to do so.

Continue reading Avoid GitHub rate limits when using Composer

iOS home screen rotation

I am quite happy with my iPad NanoiPhone 6 Plus. My left hand needs more time to get accustomed to the new form factor, but except that I don’t regret having let the better camera and longer battery life dominate my decision for the larger iPhone.

One thing I don’t like as much: the behavior of the home screen when rotating the device.

Continue reading iOS home screen rotation