Laravel is a framework for backend development for websites. It is written in PHP programming language. We use PHP to write website backend code in Laravel framework.

A list of operators on Eloquent’s where() method

When you use Eloquent’s where() method, by default it will use the = operator (i.e. ->where('fieldname','value') will generate ... WHERE fieldname = 'value'....

However you are not limited to just =. You can do something like this:

$posts = Post::where("id","!=",123)->get()

Any of the following may be used as the second parameter (and use the third param for the value)

=, <, >, <=, >=, <>, !=, LIKE, NOT LIKE, BETWEEN, ILIKE

(ILIKE = case insensitive like, I believe this is just for Postgre)

How do Invokable Controllers work in Laravel?

If a controller in Laravel has just one action then you simplify the controller by using the __invoke() method. Create a controller with a __invoke() method, then in your routes files you can just do the following:

Route::get('home','HomeController');

The controller code for HomeController could look something like this:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
    public function __invoke(Request $request)
    {
        return "Welcome to our homepage"
    }
}

Create the controller using this artisan command:

php artisan make:controller HomeController --invokable

How to access the Laravel’s route parameters outside of the controller?

If you want to read the route params (that are normally passed to the controller) from somewhere else, you can use Route::current()->parameters().

For example:

$request_params = Route::current()->parameters();

How to add a name prefix to all routes in a group?

You can use Route Name Prefixes. If you wanted to have a group of Laravel routes all with names like ‘admin.users’, ‘admin.news’, etc then you can use a route name prefix to prepend ‘admin.’ to the start of all of the names

Route::name('admin.')->group(function () {
    Route::get('users', function () {
         })->name('users'); // Route will have the name "admin.users"...
 
});

However I do not like doing this, as it means I can’t easily search for a particular route. But it does have the advantage of enforcing all in a group to have the same naming structure.

How to add the CSRF (Cross-site request forgery) token in Laravel?

While there are a few ways to do this, the easiest way for a normal <form> is to use (inside the form).

BTW, make sure you have the VerifyCsrfToken middleware enabled to make use of the CSRF protection!

How to change the order that migrations happen?

Rename the migration file, as it is sorted alphabetically

For example if you change database/migrations/2014_10_12_000000_create_users_table.php to something like database/migrations/2018_10_11_000000_create_users_table.php then it will be the most recent one processed when doing php artisan migrate.

How to check if a (blade) view file exists

Checking if a blade view file exists is very easy.

if (\View::exists('some.view')) { ... }

Or if in a blade view:

@if(\View::exists('some.view'))
  ...
@endif

Some related things to be aware of:

@includeIf – include a view from within blade, if the view exists

@includeIf('view.name', ['some' => 'data'])

@includeFirst – Include the first view that exists (the final one would be the default shown if no others exist). In this example it would try and see if custom.admin existed (/resources/views/custom/admin.blade.php), but if it didn’t then it would try admin.

@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])

@includeWhen – Used to include a view when a boolean condition is true

@includeWhen($boolean, 'view.name', ['some' => 'data'])

How to check if a relation was loaded on an Eloquent model already?

Checking if a relation was loaded (maybe by a with() function call when using the Eloquent query builder) is easy.

From inside your model

If you want to do this within your model, you can use $this->relationLoaded():

// from inside your model:
if ($this->relationLoaded("comments")) {
        //..
}

From outside of your model

$user = User::first();
//
if ($user->relationLoaded("comments")) {
  //
}

How to check if a user is logged in, inside a blade file?

You can use the @auth directive.

@auth
             Hello, logged in user!
@endauth

Related: @guest to check if user is a guest (not logged in)

@guest
            Hello guest, do you want to register?
@endguest

How to do comments in Blade files?

Comments in Blade are very simple!

You can either do normal PHP comments:

<? /* some comment here */
// or single line comments
# or these :)
?>

Or blade comments:

{{-- Blade comments that wil not appear in the rendered HTML output --}}

If you use an IDE that supports blade formatting (such as PHPStorm) then you can get it to output blade comments in the same style as normal comments.

How to eager load multiple levels of relationships in Eloquent?

You can use the ‘dot notation’ to eager load multiple levels of relationships in Eloquent

$posts = Posts::with("comments.author")->get();

This will load the comments relationship, and load the authors for each comment. Of course this assumes that you have set up the relationships correctly in your models

How to exclude URLs from the Laravel CSRF protection?

Sometimes you have to disable the CSRF protection. A common reason for this is because you have an incoming API webhook.

You can exclude URLs from the CSRF middleware by editing app/Http/Middleware/VerifyCsrfToken.

Edit the $except property.

protected $except = [
  "incoming/api/*",
];

How to find an item by Primary Key in Eloquent, or throw a ModelNotFoundException exception if it isn’t found?

Use Eloquent’s findOrFail($id) method – this will find a model by its primary key or throw an exception.

$user_id=123;
$user = User::findOrFail($user_id);
// if it cannot find a row with $user_id as the primary key, it will throw a \Illuminate\Database\Eloquent\ModelNotFoundException\ModelNotFoundException exception

If you don’t want to throw an exception if none was found then you should just use find() (which will return null if nothing is found.

How to find out what version of Laravel you are using?

  1. The artisan command: php artisan --version
  2. You can also find it in the file vendor/laravel/framework/src/Illuminate/Foundation/Application.php
class Application extends Container implements ApplicationContract, HttpKernelInterface
{
    /**
     * The Laravel framework version.
     *
     * @var string
     */
    const VERSION = '5.6.29';

How to find the average value of items in a Laravel Collection?

Use the avg() method. You can provide a value indicating which key to average (first example) or not (2nd example).

$average = collect(
        [
                ['foo' => 10],
                ['foo' => 10],
                ['foo' => 20],
                ['foo' => 40]
        ]
        )->avg('foo');
 
// 20
 
$average = collect(
        [1, 1, 2, 4]
        )->avg();
 
// 2

This is a common problem (especially if you use a local development environment such as XAMPP).

The error will look something like this:

Sample Output
[Illuminate\Database\QueryException] SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
[PDOException] SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

Luckily the fix is simple. Add the following to the boot() method of your app/Providers/AppServiceProvider.php file:

Schema::defaultStringLength(191);

How to generate an array for a dropdown (with [‘key’ => ‘value’]) suitable for a dropdown, from a Laravel collection of Eloquent objects?

The answer used to be list(), but now the answer is pluck()

$posts = Post::all();
 
echo Form::select("post_id", $posts->pluck("title","id"));

// $posts->pluck("title","id") will produce something like this:
// [
//   1 => "post title 1",
//   5 => "Another post",
// ...
// ]

The first param is the actual value you want to ‘pluck’, and the second value is how you want it keyed. For most cases the second param will be ‘id’.

You can also use pluck with just 1 param like this:

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);
 
$plucked = $collection->pluck('name');
 
$plucked->all();
 
// ['Desk', 'Chair']

But if more than one item with the same key exists, the last matching one will be used. For example:

$collection = collect([
    ['brand' => 'Tesla',  'color' => 'red'],
    ['brand' => 'Pagani', 'color' => 'white'],
    ['brand' => 'Tesla',  'color' => 'black'],
    ['brand' => 'Pagani', 'color' => 'orange'],
]);
 
$plucked = $collection->pluck('color', 'brand');
 
$plucked->all();
 
// ['Tesla' => 'black', 'Pagani' => 'orange']

How to get a route to directly show a view?

If you have a simple controller method that is just:

public function about_me() {
                return view('static.about_me');
                }

Then you can do the following in your routes file:

Route::view('/about','static.about_me');

This makes it a bit quicker to code. Sometimes it is common to end up with a bunch of functions (in a controller named something like StaticPagesController) that don’t do anything apart from return a view. Using the Route::view method in your routes file means you can skip making that function.

How to get table column names from a database table in Eloquent?

There are a few methods to get the table column info in Eloquent

\Schema::getColumnListing($this->table)
class User extends Model {
    public function getTableColumns() {
        return $this
            ->getConnection()
            ->getSchemaBuilder()
            ->getColumnListing($this->getTable());
    }
}

How to get the first row that matches some where queries, or create it if it doesn’t exist (in Laravel’s Eloquent)?

You can use the very useful firstOrCreate() to try and find a row, and create it if it doesn’t exist.

// Retrieve flight by name, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
 
// Retrieve flight by name, or create it with the name and delayed attributes...
$flight = App\Flight::firstOrCreate(
    ['name' => 'Flight 10'], ['delayed' => 1]
);
 
// Retrieve by name, or instantiate...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
 
// Retrieve by name, or instantiate with the name and delayed attributes...
$flight = App\Flight::firstOrNew(
    ['name' => 'Flight 10'], ['delayed' => 1]
);

There is also the firstOrNew which works in the same way, however it will provide an unsaved object (i.e. you will have the model object returned from the method call, but it won’t be saved in the DB). There is also the updateOrCreate if you need to update models, or create it if none exist.

How to group a SQL statement in brackets/parenthesis

It is very easy to chain where() methods together in Laravel like this:

$posts = Posts::where("category",1)->where("published",true)->where("active",1)->get()

But this will create a long list of AND WHERE statements (You can also use orWhere for OR WHERE).

But what if you need to group your where statements in brackets (parenthesis)?

If you want something like this (with one part of the WHERE grouped by brackets (parenthesis):

SELECT *
FROM `orders`
WHERE
    category = 1

    AND (
        featured = 1
        OR
        discounted IS NOT NULL
     )

Then you will have to do something called parameter grouping.

Wrap those grouped parts of the where statement in something like this:

...
   ->where(function ($query) {
            // put your grouped ->where() method calls here
    }) ...

Real world example:

DB::table('users')
    ->where('name', '=', 'John')
    ->where(function ($query) {
    // Everything within this closure will be grouped together
        $query->where('votes', '>', 100)
              ->orWhere('title', '=', 'Admin');
    })
    ->get();

This would output:

select * from users where name = 'John' and (votes > 100 or title = 'Admin')

How to increment a value in the database

You can just use the ::increment methods to ‘plus one’ a value. You can also send how many to increment in the 2nd param.

\App\User::findOrFail($user_id)->increment("profile_view_count");
// or to increment by 5
\App\User::findOrFail($user_id)->increment("profile_score_count",5);

You can also of course use the ::decrement method too.

If you use this as part of the query builder you will face some problems chaining this. It will return an int, not the query builder object. You have to do it like this:

$query = \App\User::where("id",1);
 
$query->decrement("profile_view_count",5);
$query->increment("profile_rating",1);

// this will result in an error:
 \App\User::where("id",1)->decrement("profile_view_count",5)->increment("profile_rating",1);
 
//although you could do it with just one:
$num = \App\User::where("id",1)->decrement("profile_view_count",5);

How to make multiple routes share the same URL structure or URL parameters

If you have the following URLs:

/control-panel/{team_id}/
/control-panel/{team_id}/schedule
/control-panel/{team_id}/delete
        etc...

(They all share the first part of the url – /control-panel/{team_id})

Then you don’t have to write out the routes like this:

Route::get("control-panel/{team_id}","TeamController@index");
Route::get("control-panel/{team_id}/schedule","TeamController@schedule");
Route::delete("control-panel/{team_id}/delete","TeamController@destroy");

Instead you can group the routes and add a prefix:

Route::group(["prefix"=>"control-panel/{team_id}"], function() {
    Route::get("/","TeamController@index");
    Route::get("schedule","TeamController@schedule");
    Route::delete("delete","TeamController@destroy");
});

Putting a group within a group

You can also put a Route::group() inside another one.

Route::group(["prefix"=>"control-panel/{team_id}"], function() {
    Route::get("/","TeamController@index");
 
    Route::group(["prefix"=>"schedule"],function() {
        Route::get("/","TeamController@schedule");
        Route::post("/add_new","TeamController@store");
    }
    Route::delete("delete","TeamController@destroy");
});

How to namespace a Laravel route group?

You can add a namespace for all items within a route group. If your controller (or controllers) are in app/Http/Controllers/AdminPanel then you could use the following code in your routes file (web.php):

Route::group(["namespace"=>"AdminPanel"],function() {
    Route::get("/","AdminController@index"); // actually calls \App\Http\Controllers\AdminPanel\AdminControllers because of the namespace
});

You can use relative (relative to the normal controller namespace – \App\Http\Controllers) or absolute (\App\Admin\Controllers)

How to order a Laravel hasMany relationship?

You can simply add a ->orderBy() to the hasMany relationship

return $this->hasMany(Post::class)->orderBy('updated_at');

How to prevent Eloquent from adding created_at or updated_at timestamps?

If you want to disable both created_at and updated_at then add this to your model:

const UPDATED_AT = null;
const CREATED_AT = null;

If you want to disable just one of those fields (i.e. turn off created_at but keep updated_at, or keep created_at but disable the updated_at field) then just add the one line as required.

Also remember to remove this from the migrations:

$table->timestamps()

Note: There is also the DELETED_AT const, if you use SoftDeletes.

How to provide a default model object for relationships?

If you have a relationship (such as a belongsTo()) relationship, it might not always return a result.

This will then mean that every time you do something like this:

$post = Post::first();
$author = $post->author; // what if the relationship in author() returns nothing?
echo $author->name; // $author might have been null, so this will cause an error

There are three main options to handling this:

  1. wrap everything in optional() (which will let you do anything to that variable and it will return null if there was nothing set).

  2. Wrap everything in if ($author) { ... } to make sure $author isn’t a null value

  3. or set a default model. If nothing is found for a relationship then it will create an empty object (of the same type as the relationship defines – in the case below it will be \App\User).

/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault();
}
 
// you can also define some defaults for the default!
 
/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault([
        'name' => 'Guest Author',
    ]);
}
 
/**
 * Get the author of the post.
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault(function ($user) {
        $user->name = 'Guest Author';
    });
}

How to return an item in Eloquent, or throw a ModelNotFoundException exception if it isn’t found?

Use Eloquent’s firstOrFail(). This is similar to findOrFail(), however findOrFail() does a ‘WHERE id = ?’ (hassuming id is the primary key). With firstOrFail() it will return the first row based on whatever WHERE statements you have.

$user = User::where("email","test@example.com"->firstOrFail()

If you don’t nt to throw an exception if none was found then you should just use first() (which will return null if nothing is found.

How to return JSON data to the user in Laravel?

The correct way to do it in Laravel is returning response()->json(...) such as:

return response()->json(['foo'=>'bar']);