Laravel – Documentation and Code Snippets
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? 🔗
- The artisan command:
php artisan --version
- 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
How to fix the MySQL related “Specified key was too long error” error in Laravel 🔗
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:
wrap everything in
optional()
(which will let you do anything to that variable and it will return null if there was nothing set).Wrap everything in
if ($author) { ... }
to make sure $author isn’t a null valueor 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","[email protected]"->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']);