Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Laravel Cheatsheet

Related Posts

Create New Project

mkdir my-project-name
cd my-project-name
composer create-project laravel/laravel . --prefer-dist

To make sure you have the necessary packages on Ubuntu 16.04, you may need to run:

sudo apt update && \
sudo apt install -y php7.0-mbstring php7.0-xml

Running Locally

You can test locally by running:

sudo php -S localhost:80 public/index.php

Then just go to localhost in your browser.


There are several routing files under the top level routes directory:

  • api.php - routes for an API.
  • channels.php - for websockets and broadcasting.
  • console.php - routes for if you are building a CLI application.
  • web.php - routes for a traditional web application that isn't an API.

There are two main ways to define a route. The first is by actually passing a callback that gets executed.

Route::get('/', function () {
    return view('welcome');

The alternative "shorthand" is to pass a string that represents the controller and method to execute.

Route::get('/my/web/path', 'MyController@method');

Official routing docs.

Path Variables

If you have routes with variables in the path, then you can use something like the following to pick them up.

Route::get('users/{name}', function ($uuid) { $userController = new App\Http\Controllers\UserController(); return $userController->getUserByNAME($name); });


If you need to use a regular expression on the path variables, such as to match against a UUID you can do that like so:

Route::pattern('uuid', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}');

Route::get('users/{uuid}', function ($uuid) { 
    $userController = new App\Http\Controllers\UserController(); 
    return $userController->getUser($uuid);

Alternatively, you can use this alternative syntax to achieve the same result:

Route::get('users/{uuid}', function ($uuid) { 
    $userController = new App\Http\Controllers\UserController(); 
    return $userController->getUser($uuid);
})->where('uuid', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}');

Catch All

You can take the regular expression logic further, creating a "catch all" for catching all routes after a certain prefix. E.g.

# All defined routes first.
Route::get('users/{id}', function ($id) { 
    $userController = new App\Http\Controllers\UserController(); 
    return $userController->fetchUser($id);

# Put "catch-all" in last to catch any route that didnt match above but still starts with /users.
Route::pattern('path', '.*');

Route::get('users/{path}', function ($path) { 
    $userController = new App\Http\Controllers\UserController(); 
    return $userController->catchAll($path);


Apply Middleware To Specific Route

Route::get('', function () { 
    $controller = new \App\Http\Controllers\AccountController(); 
    return $controller->getAccounts();

... or if you want to run multiple middlware:

Route::get('', function () { 
    $controller = new \App\Http\Controllers\AccountController(); 
    return $controller->getAccounts();
})->middleware([\App\Http\Middleware\MiddlewareClass1::class, \App\Http\Middleware\MiddlewareClass2::class]);

Apply Middleware To Group Of Routes

Route::middleware([\App\Http\Middleware\MiddlewareClass1::class, \App\Http\Middleware\MiddlewareClass2::class])->group(function () {
    Route::get('/', function () {

    Route::get('user/profile', function () {
        // ...

Apply MIddleware and Prefix To Group Of Routes

Route::group(['prefix' => 'admin', 'middleware' => \App\Http\Middleware\MiddlewareLoggedInAsAdminAuth::class], function(){

    // admin view for viewing posts in the system
    Route::get('articles', function () {
        $controller = new \App\Http\Controllers\ArticleController();
        return $controller->showCreateArticlePage();

    // admin view for editing/viewing a particular post
    Route::get('articles/{uuid}', function ($uuid) {
        $controller = new \App\Http\Controllers\ArticleController();
        return $controller->editArticle($uuid);


Apply Middleware To All Routes In Controller Except Specific Ones

class Controller extends BaseController
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
    public function __construct(){
        $this->middleware('auth',['except' => ['login','setup','setupSomethingElse']]);

Apply Middleware To Every Route

Open your app/Http/Kernel.php file and add your middleware to the $middleware property of the class like so:

protected $middleware = [

If you apply middleware this way, you cannot rely on getting the route name for an "exceptions list", as the route will not have been evaluated yet. E.g. $request->route() will return null from within the middleware. See here for more info.

Apply Middleware To All Routes Except Those In Exception List

Unfortunately, there is not a built-in "Laravel way" to do this right now. I found that the solution for me was to apply the middleware to every route as shown above, and then add logic to the middleware class'es body like so:

public function handle($request, Closure $next)
    $authPassed = false;
    $path = $_SERVER['REQUEST_URI'];

    foreach (PATHS_WHERE_HEADERS_NOT_POSSIBLE as $pattern)
        $match = preg_match($pattern, $path);

        if ($match === 1)
            $authPassed = true;

    // ... other checks here if authPassed is false

    if ($authPassed === true)
        $response = $next($request);

    return $response;

I defined my exception paths like so:

$uuidRegexp = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';

    '|^' . $uuidRegexp . '/resource/my-action$|'

I am using | character to represent the start and end of the regular expression because I needed to use / in the path. However, if you need | for a regexp OR, then you will need to use something else.

Artisan CLI Tool

Create A Controller

php artisan make:controller MyController

Create a RESTful Resource Controller

php artisan make:controller MyController --resource

Create Exception

php artisan make:exception NameOfMyExceptionClass

Create Middleware

php artisan make:middleware MyMiddlewareClass

Create A new App Key

head /dev/urandom | head -c 32 | base64 | awk '$0="base64:"$0'

... or if you have openssl installed:

openssl rand -base64 32 | awk '$0="base64:"$0

... or if you have want to use Laravel's artisan tool:

php artisan key:generate --show

This will output something like:


You need to include the whole thing as the value. E.g. including the base64: part.

Database Migrations

  • Database migrations can be found under database/migrations.
  • By default, you will have two migrations in there that create the users and password_resets tables.
  • Migration filenames are prefixed with the year, month, day, and time in order for the migration tool to know which order to run the migrations.
    • Using the date/time rather than an incrementing integer should hopefully reduce the likelihood of an issue arising when merging two different branches that each created a migration script.

Create A Migration

The following command will create a migration script in your migrations table for creating a table called x.

php artisan make:migration create_x_table

If you don't use create_tableName_table naming convention, then you won't get the starting code within the up/down methods for creating/destroying the table.

Using Raw SQL

If you need use raw SQL, you can just use DB::statement() like below:

public function up()
    $createTableQuery = 
        "CREATE TABLE `broker` (
            `id` int unsigned NOT NULL AUTO_INCREMENT,
            `name` varchar(255) NOT NULL,
            `redirect_url` text NOT NULL,
            `secret` varchar(30) NOT NULL,
            `modified_timestamp` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (`id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8";


If you need to get data out of the database though, you will need to use something like below:

$query = 
    "SELECT * FROM score_history WHERE user_id IN (" . 
        "SELECT uuid FROM users WHERE account_id= :accountUuid" . 

$result = \DB::select($query, ['accountUuid' => $accountUuid]);

The trouble with using \DB::select() is that you will be returned an array of stdClass objects instead of objects of your model. In order to get an array of your model objects, you would need to use the hydrate method like:

$query = "SELECT * FROM scores WHERE someColumnName = :someValue";
return Score::hydrate(\DB::select($query, ['someValue' => $someValue]))->all();

Laravel Style Migration Example

The following example will create a table that links sections to user-groups and will automatically delete rows in the table when either user-groups or content items are deleted.

public function up()
    Schema::create('content_user_group', function (Blueprint $table) {

Run Migrations

You can execute migrations with:

php artisan migrate

If you're just getting started, don't forget to edit the .env file with your database connection details.

API - Returning Null Attributes

If you are building an API and you have a model whose attributes may have a null value, then those attributes will not be returned in requests by default. If you would prefer to get the attribute back in your JSON, but with a value of null, then you need to override the toArray() method like so:

public function toArray() : array
    return array(
        'uuid' => $this->uuid,
        'name' => $this->name,
        'email' => $this->email,
        'status' => $this->status,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
        'deleted_at' => $this->deleted_at,

Make Hidden Data Visible

Sometimes you need to return data in a JSON response that is usually hidden (and thus in the $hidden member variable of a model). This might include a user's email or password etc. To make this data get returned, make use of the makeVisible() method. Refer here.

Create Model Objects

Once you have created your model class, you can instantiate objects with:

$newModelObject = new \App\Models\MyModel([
    'name' => 'Programster',
    'age' => '93',


Alternatively, you can technically do this as well:

$newModelObject = new \App\Models\MyModel();

// set the attributes
$newModelObject->name = "Programster";
$newModelObject->age = 93;

// save to the database.

Re-Inserting Models

Laravel models have an exists attribute. If you have a model in your variables, you can re-save it to your database after deletion if you change it's exists value to false.

For example:

$account = Account::findOrFail($id);
$accountDupe = Account::findOrFail($id);

$accountDupe->exists = false;

It's beyond the scope of this tutorial to explain when this is useful, but worth remembering that often models are composed of other models and that sometimes you need to cast some models to other models.

Mass Creating

    ['name' => 'Timmy', 'age' => 40],
    ['name' => 'Jimmy', 'age' => 50],
    ['name' => 'Kimmy', 'age' => 60],

Mass Inserting

    ['name' => 'Timmy', 'age' => 40],
    ['name' => 'Jimmy', 'age' => 50],
    ['name' => 'Kimmy', 'age' => 60],

Insert vs Create

"Create" will create new model objects and save them to the database whereas "Insert" is just responsible for building and sending a query (Eloquent Query Builder) to the database to insert some rows. Thus, when using "create", one will need to set the $fillable attribute on the attributes you wish to mass create objects with before one can use them, which you won't need to do if using "insert". This also means that any logic that derives fields as part of the model logic will not get executed if using "insert" like it would with "create". The most noticeable result of this is that if one uses "insert", the timestamp fields will be set to null, instead of having values.

Thus, the best rule of thumb in my opinion, is to use the "create" method instead of "insert", wherever possible.

More info

Mass Inserting Existing Model Objects

If you have created a bunch of model objects that have not yet been inserted into the database, you can do them in one go like so:

$insertRows = array();

foreach ($models as $myModel)
    $insertRows[] = $myModel->attributesToArray();



Error Bags

When working with Blade templates you may come across using $errors like so:

@if ($errors->has('email'))
    <span class="help-block">
        <strong>{{ $errors->first('email') }}</strong>

The $errors will be an instance of the \Illuminate\Support\MessageBag or the \Illuminate\Support\ViewErrorBag classes.


Here is a snippet example of something that would go in a controller. It will verify that:

  • if an id is supplied, it is a UUID, but it doesn't have to be provided.
  • a name is required and must be a string no longer than 255 characters
  • a gender string is required and must be male, female, or other (enum in the database).
$validationRules = [
    'id' => 'uuid',
    'name' => 'required|max:255',
    'gender' => 'required|in:male,female,other',

$data = request()->all();
$validator = \Validator::make($data, $validationRules);

if ($validator->fails())
    $messageBag = $validator->getMessageBag();
    // do something with it here.

Validation support for uuid was apparently added in Laravel 5.7.

Required But Nullable

If you require a field to be sent across, but null is a valid value for it, Laravel can get a bit "confused" and won't work as you might expect if you were to use: required|nullable, instead, just use present. E.g.

$validationRules = [
    'id' => 'uuid',
    'name' => 'required|max:255',
    'date_of_birth' => 'required',
    'date_of_death' => 'present', // Required, but should be null if not dead yet.

Github thread on this issue.

Further Resources

Here is a link to all of the available validation rules.

Using Regular Expressions

Here is an example rule that uses a regular expression to validate that the id field is provided, and consists of 9 numbers (possibly staring with 0).

$validationRules = [
    'id' => ['required','regex:/^[0-9]{9}$/'],

Handling Forms

Redirect Back With Errors

If you had a form that was posting somewhere else, but there were validation failures etc, then you can just redirect back with the inputs that were provided and the error messages like so:

catch (\App\Exceptions\SomeCustomException $e)
    $response = \redirect()->back()->withInput()->withErrors(["Something custom I checked for went wrong"]);

If Laravel validation failed, then you can use the validator's message bag:

catch (\App\Exceptions\ExceptionLaravelValidationFailed $validationFailedException)
    $response = \redirect()->back()->withInput()->withErrors($validationFailedException->getValidator()->getMessageBag());

HTML To Show Errors

If you add snippets like this below your form input fields:

@if ($errors->has('form_input_name'))
    <span class="help-block">
        <strong>{{ $errors->first('form_input_name') }}</strong>

... then your errors from laravel validation failing will show up by the input fields they relate to.


If you are working with a paginated resource, you may find it easier if you typehint it like so:

/* @var $paginatedAssets \Illuminate\Pagination\AbstractPaginator */

Creating Paginated Object

Sometimes you may have an array of objects that you need to paginate. For this, you may find the LengthAwarePaginator useful.

$paginatedAssets = new \Illuminate\Pagination\LengthAwarePaginator(
    $assets, // array of asset objects
    ['path' => '/assets']


Store Session Data

$request->session()->put('key', 'value');

Retrieve Session Data

$value = $request->session()->get('key');




Run testing with this command from inside your application where the vendor directory is under.



Remember that all test filenames need to end with Test. E.g. MyTest.php, and not TestUsers.php.

Disabling CSRF

If you need to disable CSRF on certain routes, edit the file that should already exist at:


Then fill in the routes in the $except array in the block that should look like this:

class VerifyCsrfToken extends Middleware
     * The URIs that should be excluded from CSRF verification.
     * @var array
    protected $except = [


Custom Exception And Missing Route Handling

If you're building an API and you want unhandled exceptions/errors to be returned in JSON, or want to do something custom for when routes are not found (404 pages), then edit the app/Exceptions/Handler.php file according to these Stack Overflow posts:

Generate Random String

$randomString = \Illuminate\Support\Str::random($length=16)

Disable Throttling

If you are building an API that is going to hit more than 60 requests per second, you will want to remove or increase the default rate-limiting of requests. You can do this by finding the following text in the /app/Http/Kernel.php file and commenting out or increasting the throttle line.

        'api' => [

Generate UUID


CRSF - 419 Expired

If you get a 419 "Page Expired" message after posting a form, make sure you have a hidden input field with the CRSF token like so:

 <input type="hidden" name="_token" id="csrf-token" value="<?= csrf_token(); ?>">

Debugging / Gotchas


I had a table that had a column for visible that was true/false for whether the item should be visible or not. Unfortunately visibility is also something built into Laravel, to do with whether an attribute should be returned in a JSON response. This causes random issues, especially when I created the getVisible() accessor, which was overriding Laravel's getVisible() method. The solution here was to change to is_visible and change the accessor to getIsVisible().


Last updated: 8th October 2021
First published: 26th August 2018