AUGUST 19, 2018

There is a nifty way to specify the way in which you want each of the pages (or Laravel routes) of your site to be indexed by search engines. In my case, I looked Robots meta tag and X-Robots-Tag HTTP header specifications to learn more about what was possible.

In short, you might tell Google a specific route or page has "no restrictions for indexing or serving" by setting the X-Robots-Tag HTTP header to all or, on the contrary, tell it to stop indexing (or saving cached versions of a page) with the noindex value.

In Laravel, the guys at Spatie made it really easy. Just install their spatie/laravel-robots-middleware composer package on your Laravel app with:

composer require spatie/laravel-robots-middleware

Let's see a few examples on how to use this.

Allow every single page to be indexed and served

Create a new middleware in your application.

// app/Http/Middleware/MyRobotsMiddleware.php

<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Spatie\RobotsMiddleware\RobotsMiddleware;

class MyRobotsMiddleware extends RobotsMiddleware
{
    /**
     * @return string|bool
     */
    protected function shouldIndex(Request $request)
    {
        return 'all';
    }
}

And then register your new in the middleware stack.

// app/Http/Kernel.php

class Kernel extends HttpKernel
{
    protected $middleware = [
        // ...
        \App\Http\Middleware\MyRobotsMiddleware::class,
    ];

    // ...
}

Forbid every single from being indexed, cached, and served

// app/Http/Middleware/BlockAllRobotsMiddleware.php

<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Spatie\RobotsMiddleware\RobotsMiddleware;

class BlockAllRobotsMiddleware extends RobotsMiddleware
{
    /**
     * @return string|bool
     */
    protected function shouldIndex(Request $request)
    {
        return 'noindex';
    }
}

Conditional robots middleware

Probably, the most interesting application of this middleware is to embed more intelligent logic to avoid indexing specific pages, but letting Google (and other search engines) crawl the pages you want to expose in search engines.

We could send a noindex header for our admin pages only, for instance.

// app/Http/Middleware/SelectiveRobotsMiddleware.php

<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Spatie\RobotsMiddleware\RobotsMiddleware;

class SelectiveRobotsMiddleware extends RobotsMiddleware
{
    protected function shouldIndex(Request $request) : string
    {
        if ($request->segment(1) === 'admin') {
            return 'noindex';
        }
        return 'all';
    }
}

Remember that you need to add all of your new middlewares to the app/Http/Kernel.php file in order for them to be called before each request. This method can be handing to block search indexing with noindex or to customize the way search engines are allow to process your pages. Here are other directives you can use in the x-robots-tag HTTP header and what they mean.

  • all - There are no restrictions for indexing or serving. Note: this directive is the default value and has no effect if explicitly listed.
  • noindex - Do not show this page in search results and do not show a "Cached" link in search results.
  • nofollow - Do not follow the links on this page
  • none - Equivalent to noindex, nofollow
  • noarchive - Do not show a "Cached" link in search results.
  • nosnippet - Do not show a text snippet or video preview in the search results for this page. A static thumbnail (if available) will still be visible.
  • notranslate - Do not offer translation of this page in search results.
  • noimageindex - Do not index images on this page.
  • unavailable_after: [RFC-850 date/time] - Do not show this page in search results after the specified date/time. The date/time must be specified in the RFC 850 format.

Thanks!

I hope you found this useful. Feel free to ping me at @nonoesp or join the mailing list. Here are some other Laravel posts and code-related posts.

APRIL 5, 2018

Laravel ships with the laravel-mix npm module installed. Laravel Mix is a wrapper around Webpack that simplifies the process of compiling your web assets (which seems to be useful for "80% of the use cases").

Still, if all you want is to use it for compiling your assets (say, compile your SCSS or SASS or Less styles to minified CSS, or compile and minify your JavaScript assets) it is not a trivial process to follow. I hope this notes help remove any problems you might find to get going.

Setting Up Your Project

Let's assume we are starting from scratch; a new empty folder. We'll want to initialize our npm directory as follows.

npm init

You can accept all the defaults of the npm init command. This will create a package.json in your directory.

Install Laravel Mix

Next, we need to install the following node packages: laravel-mix, webpack, and cross-env.

npm install laravel-mix cross-env

You can expect this command to take several minutes to install and compile all of the required dependencies. (It will also install webpack as it is a dependency of laravel-mix.)

Create Your webpack.mix.js File

Now, create the webpack.mix.js file, which serves as a configuration to specify via laravel-mix what you want webpack to do. Places this contents inside it:

let mix = require('laravel-mix');

mix.sass('assets/style.scss', 'dist')
   .js('assets/app.js', 'dist');

This will compile your SCSS assets (style.scss) to CSS (style.css) and place it inside the dist folder, and compile your JavaScript assets (app.js) also into the dist folder (app.js). (Make sure that you do place those files style.scs and app.js inside the assets folder (or specify what files you'd like to compile.

Add npm Commands to Your package.json

The only piece we are missing is a command to tell Webpack to process our operations. Place this command inside the "scripts" dictionary of your package.json file (that should have been created when you ran the npm init command.

"scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},

Compile Your Assets

Now you can compile your assets for development (no minifying but faster).

npm run development

Or for production (slower but minified and less file size).

npm run production

Note that you can use npm run dev and npm run prod as shorthands instead of npm run development and npm run production.


You can also run the watch command while you are editing your assets during development — Laravel Mix will re-compile everything you make changes to one of your asset files and save. This will make your development experience even better. Just remember to compile in production before deploying your application so your assets get minified.

npm run watch

You are all set!

SEPTEMBER 16, 2017

To make sure your Laravel application doesn't break when you are applying changes to your database, it's a good practice to check wether a table exists or not before doing any calls.

\Schema::hasTable('users');

MARCH 2, 2017

When using Laravel, it is common to sort Eloquent models obtained with the query builder by calling ->orderBy('created_at', 'DESC'), for instance. But this is not always possible when arranging an Eloquent Collection (Illuminate\Database\Eloquent\Collection). To do this, we need to pass a sorting closure to the ->sortBy() method. (An example would be that our collection has the property order.) In that case, we could just call the following:

$items = $items->sortBy(function($item) {
  return -$item->order;
});

JUNE 15, 2015

Laravel is a powerful PHP framework. Like many other PHP systems, it benefits from the use of Composer to manage its dependencies, making the use of open-source libraries extremely simple.

What follows is a list of the packages (or dependencies) I am using in most of my current projects—let me explain you why.

dimsav/laravel-translatable

A package I discovered a few weeks ago. It gives your Laravel app the possibility of adding translations for your SQL tables to various different languages, with a really flexible structure. You can, for instance, have the articles in your blog written in English by default, and only translate to certain languages the ones you want.

Then, you can show those translated languages for users that have selected that locale on their browser, but fallback to the default language if an article is not available in their language.

Check it on Github.

jenssegers/laravel-date

A package based in Carbon. It makes ridiculously simple working with dates, with support for all languages.

Some of the features I use the most are: parsing database dates to human-readable ones (2015-06-14 could be translated to Sunday 14, June 2015); expressing how long ago a content was created (posted 2 minutes ago, for instance); calculating dates in the past or in the future, by adding or substracting days, weeks, months (or whatever unit) to a date object.

Possibilities are unlimited, and this library makes it even easier that before.

Check it on Github.

rtconner/laravel-tagging

With this package, you can use the Taggable trait to any of your models, and start tagging them. Then, you can use the query builder with its own methods to filter your content depending on tags.

I have been using it for articles and projects, to organize content and allow users to navigate by article categories.

Check it on Github.

panique/laravel-sass

If you are designing with SCSS, you need a parser o automate the generation of your CSS files. This package does the job for me pretty well.

It allows you to run inline PHP functions specifying what SCSS folder to parse, and where to save the CSS. Also, it has an in-built function to minify your CSS files, compressing them a lot, so you don’t have to worry about it.

For development purposes, I tend to set a GET variable on the App::before() filter function (located on app/filters.php) to force generate new CSS files. Running the URL /home/?scss=1, for instance, would regenerate all my CSS files.

Check it on Github

vtalbot/markdown

Based on Michelf’s PHP parser, this package implements methods to parse Markdown text from strings or files directly.

One example would be calling Markdown::string($string) in your code to parse the $string from markdown to HTML.

Check it on Github

If you know other PHP packages that I should know of, please drop me a tweet! Thanks for reading.

NOVEMBER 18, 2014

Following the series of Laravel posts, here is how to make a Laravel app adapt to whatever language the visitor has set as a preference on its browser, or how to show a default language in case your website does not support your visitor's language.

When localizing a website, I usually use the following process:

  1. Set the locale to the user's preferred language.
  2. Fallback to English when the user's preferred language is not supported by your site.

To achieve this, the first thing we need to do is add the following lines inside the App::before method, on the file app/filters.php:

App::before(function($request)
{
    // Set the locale of the app to the user's browser language
    $browser_lang = substr(Request::server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
    App::setLocale($browser_lang);  
});

This will set the language to whatever first language the user browser has selected.

Then, set the fallback_locale variable inside the app/config/app.php to 'en', which will do for the falling back.

And that's it. Now just use the lang/ folder to add different language files in subfolders with their language code (i.e. lang/en/help.php for English, and lang/es/help.php for Spanish).

The strings inside the file should be wrapped in a PHP array, as follows:

<?php
return array(
  'terms' => 'términos',
  'help' => 'ayuda',
  'items' => 'artículos',
);

Lastly, you can use anywhere in your Laravel app the strings inside the help.php file, just by writing trans('help.terms'), for instance—which is a shorthand for Lang::get('help.terms'). That code, will get the terms value corresponding to the user’s language, or to the fallback language if the user’s language does not exist.

OCTOBER 8, 2014

After using Laravel in my website projects for the last year, I have been exploring many of its basic features. Along the way, I have documented the important tasks — useful at the beginning and development of each app — in article-like format.

From now on, I will be sharing some of those posts, on how to create a Laravel project, do the initial setup, and interact with various aspects, as localizing a site for different languages, for instance.

Tune in on Twitter at @nonoesp to hear about the posts, or add our feed to you RSS reader.

Want to see older publications? Visit the archive.

Listen to my Podcast.