Laravel Tips
Awesome Laravel tips and tricks for all artisans. PR and ideas are welcome!
An idea by PovilasKorop and MarceauKa.
Hey, like these tips? Also check out my premium Laravel courses
Update 13 August 2021: Currently there are 153 tips divided into 14 sections.
Table of Contents
- DB Models and Eloquent (37 tips)
- Models Relations (25 tips)
- Migrations (9 tips)
- Views (8 tips)
- Routing (16 tips)
- Validation (9 tips)
- Collections (6 tips)
- Auth (5 tips)
- Mail (4 tips)
- Artisan (5 tips)
- Factories (3 tips)
- Log and debug (3 tips)
- API (2 tips)
- Other (21 tips)
DB Models and Eloquent
- Reuse or clone query
- Eloquent where date methods
- Increments and decrements
- No timestamp columns
- Soft-deletes: multiple restore
- Model all: columns
- To Fail or not to Fail
- Column name change
- Map query results
- Change Default Timestamp Fields
- Quick Order by created_at
- Automatic Column Value When Creating Records
- DB Raw Query Calculations Run Faster
- More than One Scope
- No Need to Convert Carbon
- Grouping by First Letter
- Never Update the Column
- Find Many
- Find by Key
- Use UUID instead of auto-increment
- Sub-selects in Laravel Way
- Hide Some Columns
- Exact DB Error
- Soft-Deletes with Query Builder
- Good Old SQL Query
- Use DB Transactions
- Update or Create
- Forget Cache on Save
- Change Format of Created_at and Updated_at
- Storing Array Type into JSON
- Make a Copy of the Model
- Reduce Memory
- Force query without $fillable/$guarded
- 3-level structure of parent-children
- Use find to search multiple records
- Perform any action on failure
- Check if record exists or show 404
Reuse or clone query()
Typically, we need to query multiple time from a filtered query. So, most of the time we use query()
method,
let's write a query for getting today created active and inactive products
$query = Product::query();
$today = request()->q_date ?? today();
if($today){
$query->where('created_at', $today);
}
// lets get active and inactive products
$active_products = $query->where('status', 1)->get(); // this line modified the $query object variable
$inactive_products = $query->where('status', 0)->get(); // so here we will not find any incative products
But, after getting $active products
the$query
will be modified. So, $inactive_products
will not find any inactive products from $query
and that will return blank collection every time. Cause, that will try to find inactive products from $active_products
($query
will return active products only).
For solve this issue, we can query multiple time by reusing this $query
object. So, We need to clone this $query
before doing any $query
modification action.
$active_products = (clone $query)->where('status', 1)->get(); // it will not modify the $query
$inactive_products = (clone $query)->where('status', 0)->get(); // so we will get inactive products from $query
Eloquent where date methods
In Eloquent, check the date with functions whereDay()
, whereMonth()
, whereYear()
, whereDate()
and whereTime()
.
$products = Product::whereDate('created_at', '2018-01-31')->get();
$products = Product::whereMonth('created_at', '12')->get();
$products = Product::whereDay('created_at', '31')->get();
$products = Product::whereYear('created_at', date('Y'))->get();
$products = Product::whereTime('created_at', '=', '14:13:58')->get();
Increments and decrements
If you want to increment some DB column in some table, just use increment()
function. Oh, and you can increment not only by 1, but also by some number, like 50.
Post::find($post_id)->increment('view_count');
User::find($user_id)->increment('points', 50);
No timestamp columns
If your DB table doesn't contain timestamp fields created_at
and updated_at
, you can specify that Eloquent model wouldn't use them, with $timestamps = false
property.
class Company extends Model
{
public $timestamps = false;
}
Soft-deletes: multiple restore
When using soft-deletes, you can restore multiple rows in one sentence.
Post::onlyTrashed()->where('author_id', 1)->restore();
Model all: columns
When calling Eloquent's Model::all()
, you can specify which columns to return.
$users = User::all(['id', 'name', 'email']);
To Fail or not to Fail
In addition to findOrFail()
, there's also Eloquent method firstOrFail()
which will return 404 page if no records for query are found.
$user = User::where('email', '[email protected]')->firstOrFail();
Column name change
In Eloquent Query Builder, you can specify "as" to return any column with a different name, just like in plain SQL query.
$users = DB::table('users')->select('name', 'email as user_email')->get();
Map query results
After Eloquent query you can modify rows by using map()
function in Collections.
$users = User::where('role_id', 1)->get()->map(function (User $user) {
$user->some_column = some_function($user);
return $user;
});
Change Default Timestamp Fields
What if you’re working with non-Laravel database and your timestamp columns are named differently? Maybe, you have create_time and update_time. Luckily, you can specify them in the model, too:
class Role extends Model
{
const CREATED_AT = 'create_time';
const UPDATED_AT = 'update_time';
}
Quick Order by created_at
Instead of:
User::orderBy('created_at', 'desc')->get();
You can do it quicker:
User::latest()->get();
By default, latest()
will order by created_at
.
There is an opposite method oldest()
which would order by created_at
ascending:
User::oldest()->get();
Also, you can specify another column to order by. For example, if you want to use updated_at
, you can do this:
$lastUpdatedUser = User::latest('updated_at')->first();
Automatic Column Value When Creating Records
If you want to generate some DB column value when creating record, add it to model's boot()
method. For example, if you have a field "position" and want to assign the next available position to the new record (like Country::max('position') + 1)
, do this:
class Country extends Model {
protected static function boot()
{
parent::boot();
Country::creating(function($model) {
$model->position = Country::max('position') + 1;
});
}
}
DB Raw Query Calculations Run Faster
Use SQL raw queries like whereRaw()
method, to make some DB-specific calculations directly in query, and not in Laravel, usually the result will be faster. Like, if you want to get users that were active 30+ days after their registration, here's the code:
User::where('active', 1)
->whereRaw('TIMESTAMPDIFF(DAY, created_at, updated_at) > ?', 30)
->get();
More than One Scope
You can combine and chain Query Scopes in Eloquent, using more than one scope in a query.
Model:
public function scopeActive($query) {
return $query->where('active', 1);
}
public function scopeRegisteredWithinDays($query, $days) {
return $query->where('created_at', '>=', now()->subDays($days));
}
Some Controller:
$users = User::registeredWithinDays(30)->active()->get();
No Need to Convert Carbon
If you're performing whereDate()
and check today's records, you can use Carbon's now()
and it will automatically be transformed to date. No need to do ->toDateString()
.
// Instead of
$todayUsers = User::whereDate('created_at', now()->toDateString())->get();
// No need to convert, just use now()
$todayUsers = User::whereDate('created_at', now())->get();
Grouping by First Letter
You can group Eloquent results by any custom condition, here's how to group by first letter of user's name:
$users = User::all()->groupBy(function($item) {
return $item->name[0];
});
Never Update the Column
If you have DB column which you want to be set only once and never updated again, you can set that restriction on Eloquent Model, with a mutator:
class User extends Model
{
public function setEmailAttribute($value)
{
if ($this->email) {
return;
}
$this->attributes['email'] = $value;
}
}
Find Many
Eloquent method find()
may accept multiple parameters, and then it returns a Collection of all records found, not just one Model:
// Will return Eloquent Model
$user = User::find(1);
// Will return Eloquent Collection
$users = User::find([1,2,3]);
Find by Key
You can also find multiple records with whereKey()
method which takes care of which field is exactly your primary key (id
is the default but you may override it in Eloquent model):
$users = User::whereKey([1,2,3])->get();
Use UUID instead of auto-increment
You don't want to use auto incrementing ID in your model?
Migration:
Schema::create('users', function (Blueprint $table) {
// $table->increments('id');
$table->uuid('id')->unique();
});
Model:
class User extends Model
{
public $incrementing = false;
protected $keyType = 'string';
protected static function boot()
{
parent::boot();
User::creating(function ($model) {
$model->setId();
});
}
public function setId()
{
$this->attributes['id'] = Str::uuid();
}
}
Sub-selects in Laravel Way
From Laravel 6, you can use addSelect() in Eloquent statement, and do some calculation to that added column.
return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->limit(1)
])->get();
Hide Some Columns
When doing Eloquent query, if you want to hide specific field from being returned, one of the quickest ways is to add ->makeHidden()
on Collection result.
$users = User::all()->makeHidden(['email_verified_at', 'deleted_at']);
Exact DB Error
If you want to catch Eloquent Query exceptions, use specific QueryException
instead default Exception class, and you will be able to get the exact SQL code of the error.
try {
// Some Eloquent/SQL statement
} catch (\Illuminate\Database\QueryException $e) {
if ($e->getCode() === '23000') { // integrity constraint violation
return back()->withError('Invalid data');
}
}
Soft-Deletes with Query Builder
Don't forget that soft-deletes will exclude entries when you use Eloquent, but won't work if you use Query Builder.
// Will exclude soft-deleted entries
$users = User::all();
// Will NOT exclude soft-deleted entries
$users = User::withTrashed()->get();
// Will NOT exclude soft-deleted entries
$users = DB::table('users')->get();
Good Old SQL Query
If you need to execute a simple SQL query, without getting any results - like changing something in DB schema, you can just do DB::statement()
.
DB::statement('DROP TABLE users');
DB::statement('ALTER TABLE projects AUTO_INCREMENT=123');
Use DB Transactions
If you have two DB operations performed, and second may get an error, then you should rollback the first one, right?
For that, I suggest to use DB Transactions, it's really easy in Laravel:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});
Update or Create
If you need to check if the record exists, and then update it, or create a new record otherwise, you can do it in one sentence - use Eloquent method updateOrCreate()
:
// Instead of this
$flight = Flight::where('departure', 'Oakland')
->where('destination', 'San Diego')
->first();
if ($flight) {
$flight->update(['price' => 99, 'discounted' => 1]);
} else {
$flight = Flight::create([
'departure' => 'Oakland',
'destination' => 'San Diego',
'price' => 99,
'discounted' => 1
]);
}
// Do it in ONE sentence
$flight = Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99, 'discounted' => 1]
);
Forget Cache on Save
Tip given by @pratiksh404
If you have cache key like posts
that gives collection, and you want to forget that cache key on new store or update, you can call static saving
function on your model:
class Post extends Model
{
// Forget cache key on storing or updating
public static function boot()
{
parent::boot();
static::saving(function () {
Cache::forget('posts');
});
}
}
Change Format Of Created_at and Updated_at
Tip given by @syofyanzuhad
To change the format of created_at
you can add a method in your model like this:
public function getCreatedAtFormattedAttribute()
{
return $this->created_at->format('H:i d, M Y');
}
So you can use it $entry->created_at_formatted
when it's needed. It will return the created_at
attribute like this: 04:19 23, Aug 2020
.
And also for changing format of updated_at
attribute, you can add this method :
public function getUpdatedAtFormattedAttribute()
{
return $this->updated_at->format('H:i d, M Y');
}
So you can use it $entry->updated_at_formatted
when it's needed. It will return the updated_at
attribute like this: 04:19 23, Aug 2020
.
Storing Array Type into JSON
Tip given by @pratiksh404
If you have input field which takes an array and you have to store it as a JSON, you can use $casts
property in your model. Here images
is a JSON attribute.
protected $casts = [
'images' => 'array',
];
So you can store it as a JSON, but when retrieved from DB, it can be used as an array.
Make a Copy of the Model
If you have two very similar Models (like shipping address and billing address) and you need to make a copy of one to another, you can use replicate()
method and change some properties after that.
Example from the official docs:
$shipping = Address::create([
'type' => 'shipping',
'line_1' => '123 Example Street',
'city' => 'Victorville',
'state' => 'CA',
'postcode' => '90001',
]);
$billing = $shipping->replicate()->fill([
'type' => 'billing'
]);
$billing->save();
Reduce Memory
Sometimes we need to load a huge amount of data into memory. For example:
$orders = Order::all();
But this can be slow if we have really huge data, because Laravel prepares objects of the Model class. In such cases, Laravel has a handy function toBase()
$orders = Order::toBase()->get();
//$orders will contain `Illuminate\Support\Collection` with objects `StdClass`.
By calling this method, it will fetch the data from the database, but it will not prepare the Model class. Keep in mind it is often a good idea to pass an array of fields to the get method, preventing all fields to be fetched from the database.
Force query without $fillable/$guarded
If you create a Laravel boilerplate as a "starter" for other devs, and you're not in control of what THEY would later fill in Model's $fillable/$guarded, you may use forceFill()
$team->update(['name' => $request->name])
What if "name" is not in Team model's $fillable
? Or what if there's no $fillable/$guarded
at all?
$team->forceFill(['name' => $request->name])
This will "ignore" the $fillable
for that one query and will execute no matter what.
3-level structure of parent-children
If you have a 3-level structure of parent-children, like categories in an e-shop, and you want to show the number of products on the third level, you can use with('yyy.yyy')
and then add withCount()
as a condition
class HomeController extend Controller
{
public function index()
{
$categories = Category::query()
->whereNull('category_id')
->with(['subcategories.subcategories' => function($query) {
$query->withCount('products');
}])->get();
}
}
class Category extends Model
{
public function subcategories()
{
return $this->hasMany(Category::class);
}
public function products()
{
return $this->hasMany(Product::class);
}
}
-
@foreach($categories as $category)
-
{{ $category->name }}
@if ($category->subcategories)
-
@foreach($category->subcategories as $subcategory)
-
{{ $subcategory->name }}
@if ($subcategory->subcategories)
-
@foreach ($subcategory->subcategories as $subcategory)
- {{ $subcategory->name }} ({{ $subcategory->product_count }}) @endforeach
@endforeach
@endforeach
-
{{ $subcategory->name }}
@if ($subcategory->subcategories)
Use find to search multiple records
You can use Eloquent find()
not only to search for one record but also to return a collection of multiple records by their IDs. Instead of
return Product::whereIn('id', $this->productIDs)->get();
You can do this
return Product::find($this->productIDs)
Perform any action on failure
When looking for a record, you may want to perform some actions if it's not found. In addition to ->firstOrFail()
which just throws 404, you can perform any action on failure, just do ->firstOr(function() { ... })
$model = Flight::where('legs', '>', 3)->firstOr(function () {
// ...
})
Check if record exists or show 404
Don't use find() and then check if the record exists. Use findOrFail() or optional().
$product = Product::find($id);
if ($product) {
$product->update($productDataArray);
}
Shorter way
$product = Product::findOrFail($id); // shows 404 if not found
$product->update($productDataArray);
Even shorter
optional(Product::find($id))->update($productDataArray);
Models Relations
- OrderBy on Eloquent relationships
- Conditional relationships
- Raw DB Queries: havingRaw()
- Eloquent has() deeper
- Has Many. How many exactly?
- Default model
- Use hasMany to create Many
- Multi level Eager Loading
- Eager Loading with Exact Columns
- Touch parent updated_at easily
- Always Check if Relationship Exists
- Use withCount() to Calculate Child Relationships Records
- Extra Filter Query on Relationships
- Load Relationships Always, but Dynamically
- Instead of belongsTo, use hasMany
- Rename Pivot Table
- Update Parent in One Line
- Laravel 7+ Foreign Keys
- Combine Two "whereHas"
- Check if Relationship Method Exists
- Pivot Table with Extra Relations
- Load Count on-the-fly
- Randomize Relationship Order
- Filter hasMany relationships
- Filter by many-to-many relationship pivot column
OrderBy on Eloquent relationships
You can specify orderBy() directly on your Eloquent relationships.
public function products()
{
return $this->hasMany(Product::class);
}
public function productsByName()
{
return $this->hasMany(Product::class)->orderBy('name');
}
Conditional relationships
If you notice that you use same relationship often with additional "where" condition, you can create a separate relationship method.
Model:
public function comments()
{
return $this->hasMany(Comment::class);
}
public function approved_comments()
{
return $this->hasMany(Comment::class)->where('approved', 1);
}
Raw DB Queries: havingRaw()
You can use RAW DB queries in various places, including havingRaw()
function after groupBy()
.
Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();
Eloquent has() deeper
You can use Eloquent has()
function to query relationships even two layers deep!
// Author -> hasMany(Book::class);
// Book -> hasMany(Rating::class);
$authors = Author::has('books.ratings')->get();
Has Many. How many exactly?
In Eloquent hasMany()
relationships, you can filter out records that have X amount of children records.
// Author -> hasMany(Book::class)
$authors = Author::has('books', '>', 5)->get();
Default model
You can assign a default model in belongsTo
relationship, to avoid fatal errors when calling it like {{ $post->user->name }}
if $post->user doesn't exist.
public function user()
{
return $this->belongsTo('App\User')->withDefault();
}
Use hasMany to create Many
If you have hasMany()
relationship, you can use saveMany()
to save multiple "child" entries from your "parent" object, all in one sentence.
$post = Post::find(1);
$post->comments()->saveMany([
new Comment(['message' => 'First comment']),
new Comment(['message' => 'Second comment']),
]);
Multi level Eager Loading
In Laravel you can Eager Load multiple levels in one statement, in this example we not only load the author relation but also the country relation on the author model.
$users = App\Book::with('author.country')->get();
Eager Loading with Exact Columns
You can do Laravel Eager Loading and specify the exact columns you want to get from the relationship.
$users = App\Book::with('author:id,name')->get();
You can do that even in deeper, second level relationships:
$users = App\Book::with('author.country:id,name')->get();
Touch parent updated_at easily
If you are updating a record and want to update the updated_at
column of parent relationship (like, you add new post comment and want posts.updated_at
to renew), just use $touches = ['post'];
property on child model.
class Comment extends Model
{
protected $touches = ['post'];
}
Always Check if Relationship Exists
Never ever do $model->relationship->field
without checking if relationship object still exists.
It may be deleted for whatever reason, outside your code, by someone else's queued job etc. Do if-else
, or {{ $model->relationship->field ?? '' }}
in Blade, or {{ optional($model->relationship)->field }}
. With php8 you can even use the nullsafe operator {{ $model->relationship?->field) }}
Use withCount() to Calculate Child Relationships Records
If you have hasMany()
relationship, and you want to calculate “children” entries, don’t write a special query. For example, if you have posts and comments on your User model, write this withCount()
:
public function index()
{
$users = User::withCount(['posts', 'comments'])->get();
return view('users', compact('users'));
}
And then, in your Blade file, you will access those number with {relationship}_count
properties:
@foreach ($users as $user)
<tr>
<td>{{ $user->name }}td>
<td class="text-center">{{ $user->posts_count }}td>
<td class="text-center">{{ $user->comments_count }}td>
tr>
@endforeach
You may also order by that field:
User::withCount('comments')->orderBy('comments_count', 'desc')->get();
Extra Filter Query on Relationships
If you want to load relationship data, you can specify some limitations or ordering in a closure function. For example, if you want to get Countries with only three of their biggest cities, here's the code.
$countries = Country::with(['cities' => function($query) {
$query->orderBy('population', 'desc');
$query->take(3);
}])->get();
Load Relationships Always, but Dynamically
You can not only specify what relationships to ALWAYS load with the model, but you can do it dynamically, in the constructor method:
class ProductTag extends Model
{
protected $with = ['product'];
public function __construct() {
parent::__construct();
$this->with = ['product'];
if (auth()->check()) {
$this->with[] = 'user';
}
}
}
Instead of belongsTo, use hasMany
For belongsTo
relationship, instead of passing parent's ID when creating child record, use hasMany
relationship to make a shorter sentence.
// if Post -> belongsTo(User), and User -> hasMany(Post)...
// Then instead of passing user_id...
Post::create([
'user_id' => auth()->id(),
'title' => request()->input('title'),
'post_text' => request()->input('post_text'),
]);
// Do this
auth()->user()->posts()->create([
'title' => request()->input('title'),
'post_text' => request()->input('post_text'),
]);
Rename Pivot Table
If you want to rename "pivot" word and call your relationship something else, you just use ->as('name')
in your relationship.
Model:
public function podcasts() {
return $this->belongsToMany('App\Podcast')
->as('subscription')
->withTimestamps();
}
Controller:
$podcasts = $user->podcasts();
foreach ($podcasts as $podcast) {
// instead of $podcast->pivot->created_at ...
echo $podcast->subscription->created_at;
}
Update Parent in One Line
If you have a belongsTo()
relationship, you can update the Eloquent relationship data in the same sentence:
// if Project -> belongsTo(User::class)
$project->user->update(['email' => '[email protected]']);
Laravel 7+ Foreign Keys
From Laravel 7, in migrations you don't need to write two lines for relationship field - one for the field and one for foreign key. Use method foreignId()
.
// Before Laravel 7
Schema::table('posts', function (Blueprint $table)) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
}
// From Laravel 7
Schema::table('posts', function (Blueprint $table)) {
$table->foreignId('user_id')->constrained();
}
// Or, if your field is different from the table reference
Schema::table('posts', function (Blueprint $table)) {
$table->foreignId('created_by_id')->constrained('users', 'column');
}
Combine Two "whereHas"
In Eloquent, you can combine whereHas()
and orDoesntHave()
in one sentence.
User::whereHas('roles', function($query) {
$query->where('id', 1);
})
->orDoesntHave('roles')
->get();
Check if Relationship Method Exists
If your Eloquent relationship names are dynamic and you need to check if relationship with such name exists on the object, use PHP function method_exists($object, $methodName)
$user = User::first();
if (method_exists($user, 'roles')) {
// Do something with $user->roles()->...
}
Pivot Table with Extra Relations
In many-to-many relationship, your pivot table may contain extra fields, and even extra relationships to other Model.
Then generate a separate Pivot Model:
php artisan make:model RoleUser --pivot
Next, specify it in belongsToMany()
with ->using()
method. Then you could do magic, like in the example.
// in app/Models/User.php
public function roles()
{
return $this->belongsToMany(Role::class)
->using(RoleUser::class)
->withPivot(['team_id']);
}
// app/Models/RoleUser.php: notice extends Pivot, not Model
use Illuminate\Database\Eloquent\Relations\Pivot;
class RoleUser extends Pivot
{
public function team()
{
return $this->belongsTo(Team::class);
}
}
// Then, in Controller, you can do:
$firstTeam = auth()->user()->roles()->first()->pivot->team->name;
Load Count on-the-fly
In addition to Eloquent's withCount()
method to count related records, you can also load the count on-the-fly, with loadCount()
:
// if your Book hasMany Reviews...
$book = App\Book::first();
$book->loadCount('reviews');
// Then you get access to $book->reviews_count;
// Or even with extra condition
$book->loadCount(['reviews' => function ($query) {
$query->where('rating', 5);
}]);
Randomize Relationship Order
You can use inRandomOrder()
to randomize Eloquent query result, but also you can use it to randomize the relationship entries you're loading with query.
// If you have a quiz and want to randomize questions...
// 1. If you want to get questions in random order:
$questions = Question::inRandomOrder()->get();
// 2. If you want to also get question options in random order:
$questions = Question::with(['answers' => function($q) {
$q->inRandomOrder();
}])->inRandomOrder()->get();
Filter hasMany relationships
Just a code example from my project, showing the possibility of filtering hasMany relationships.
TagTypes -> hasMany Tags -> hasMany Examples
And you wanna query all the types, with their tags, but only those that have examples, ordering by most examples.
$tag_types = TagType::with(['tags' => function ($query) {
$query->has('examples')
->withCount('examples')
->orderBy('examples_count', 'desc');
}])->get();
Filter by many-to-many relationship pivot column
If you have a many-to-many relationship, and you add an extra column to the pivot table, here's how you can order by it when querying the list.
class Tournament extends Model
{
public function countries()
{
return $this->belongsToMany(Country::class)->withPivot(['position']);
}
}
class TournamentsController extends Controller
public function whatever_method() {
$tournaments = Tournament::with(['countries' => function($query) {
$query->orderBy('position');
}])->latest()->get();
}
Migrations
- Unsigned Integer
- Order of Migrations
- Migration fields with timezones
- Database migrations column types
- Default Timestamp
- Migration Status
- Create Migration with Spaces
- Create Column after Another Column
- Make migration for existing table
Unsigned Integer
For foreign key migrations instead of integer()
use unsignedInteger()
type or integer()->unsigned()
, otherwise you may get SQL errors.
Schema::create('employees', function (Blueprint $table) {
$table->unsignedInteger('company_id');
$table->foreign('company_id')->references('id')->on('companies');
// ...
});
You can also use unsignedBigInteger()
if that other column is bigInteger()
type.
Schema::create('employees', function (Blueprint $table) {
$table->unsignedBigInteger('company_id');
});
Order of Migrations
If you want to change the order of DB migrations, just rename the file's timestamp, like from 2018_08_04_070443_create_posts_table.php
to2018_07_04_070443_create_posts_table.php
(changed from 2018_08_04
to 2018_07_04
).
They run in alphabetical order.
Migration fields with timezones
Did you know that in migrations there's not only timestamps()
but also timestampsTz()
, for the timezone?
Schema::create('employees', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email');
$table->timestampsTz();
});
Also, there are columns dateTimeTz()
, timeTz()
, timestampTz()
, softDeletesTz()
.
Database migrations column types
There are interesting column types for migrations, here are a few examples.
$table->geometry('positions');
$table->ipAddress('visitor');
$table->macAddress('device');
$table->point('position');
$table->uuid('id');
See all column types on the official documentation.
Default Timestamp
While creating migrations, you can use timestamp()
column type with option useCurrent()
and useCurrentOnUpdate()
, it will set CURRENT_TIMESTAMP
as default value.
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrentOnUpdate();
Migration Status
If you want to check what migrations are executed or not yet, no need to look at the database "migrations" table, you can launch php artisan migrate:status
command.
Example result:
+------+------------------------------------------------+-------+
| Ran? | Migration | Batch |
+------+------------------------------------------------+-------+
| Yes | 2014_10_12_000000_create_users_table | 1 |
| Yes | 2014_10_12_100000_create_password_resets_table | 1 |
| No | 2019_08_19_000000_create_failed_jobs_table | |
+------+------------------------------------------------+-------+
Create Migration with Spaces
When typing make:migration
command, you don't necessarily have to use underscore _
symbol between parts, like create_transactions_table
. You can put the name into quotes and then use spaces instead of underscores.
// This works
php artisan make:migration create_transactions_table
// But this works too
php artisan make:migration "create transactions table"
Source: Steve O on Twitter
Create Column after Another Column
Notice: Only MySQL
If you're adding a new column to the existing table, it doesn't necessarily have to become the last in the list. You can specify after which column it should be created:
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->after('email');
});
If you're adding a new column to the existing table, it doesn't necessarily have to become the last in the list. You can specify before which column it should be created:
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->before('created_at');
});
If you want your column to be the first in your table , then use the first method.
Schema::table('users', function (Blueprint $table) {
$table->string('uuid')->first();
});
Make migration for existing table
If you make a migration for existing table, and you want Laravel to generate the Schema::table() for you, then add "_in_xxxxx_table" at the end, or specify "--table" parameter. php artisan change_fields_products_table
generates empty class
class ChangeFieldsProductsTable extends Migration
{
public function up()
{
//
}
}
But add in_xxxxx_table
php artisan make:migration change_fields_in_products_table
and it generates class with Schemma::table()
pre-fileed
class ChangeFieldsProductsTable extends Migration
{
public function up()
{
Schema::table('products', function (Blueprint $table) {
//
})
};
}
Also you can specify --table
parameter php artisan make:migration whatever_you_want --table=products
class WhateverYouWant extends Migration
{
public function up()
{
Schema::table('products', function (Blueprint $table) {
//
})
};
}
Views
- $loop variable in foreach
- Does view file exist?
- Error code Blade pages
- View without controllers
- Blade @auth
- Two-level $loop variable in Blade
- Create Your Own Blade Directive
- Blade Directives: IncludeIf, IncludeWhen, IncludeFirst
$loop variable in foreach
Inside of foreach loop, check if current entry is first/last by just using $loop
variable.
@foreach ($users as $user)
@if ($loop->first)
This is the first iteration.
@endif
@if ($loop->last)
This is the last iteration.
@endif
<p>This is user {{ $user->id }}p>
@endforeach
There are also other properties like $loop->iteration
or $loop->count
. Learn more on the official documentation.
Does view file exist?
You can check if View file exists before actually loading it.
if (view()->exists('custom.page')) {
// Load the view
}
You can even load an array of views and only the first existing will be actually loaded.
return view()->first(['custom.dashboard', 'dashboard'], $data);
Error code Blade pages
If you want to create a specific error page for some HTTP code, like 500 - just create a blade file with this code as filename, in resources/views/errors/500.blade.php
, or 403.blade.php
etc, and it will automatically be loaded in case of that error code.
View without controllers
If you want route to just show a certain view, don't create a Controller method, just use Route::view()
function.
// Instead of this
Route::get('about', 'TextsController@about');
// And this
class TextsController extends Controller
{
public function about()
{
return view('texts.about');
}
}
// Do this
Route::view('about', 'texts.about');
Blade @auth
Instead of if-statement to check logged in user, use @auth
directive.
Typical way:
@if(auth()->user())
// The user is authenticated.
@endif
Shorter:
@auth
// The user is authenticated.
@endauth
The opposite is @guest
directive:
@guest
// The user is not authenticated.
@endguest
Two-level $loop variable in Blade
In Blade's foreach you can use $loop variable even in two-level loop to reach parent variable.
@foreach ($users as $user)
@foreach ($user->posts as $post)
@if ($loop->parent->first)
This is first iteration of the parent loop.
@endif
@endforeach
@endforeach
Create Your Own Blade Directive
It’s very easy - just add your own method in app/Providers/AppServiceProvider.php
. For example, if you want to have this for replace
tags with new lines:
Comments
-
Can the content be translated into other languages and provided?
Thanks for providing good documentation.
I would like to provide this document translated into Korean.
Is this an acceptable behavior?
Is there any recommended method if possible?
-
Pivot Table with Extra Relations (https://github.com/LaravelDaily/laravel-tips#pivot-table-with-extra-relations)
Thank you for such usefull information. It would be nice if you add advice that tells how to eager load relations on a pivot table to avoid "n + 1 queries" problem. There's a usefull package which resolve this problem . See for more information - https://github.com/ajcastro/eager-load-pivot-relations
-
Http concurrent calls tip idea
I am not talking about Http::pool(). This just does all given calls at once. I am talking about crawler situations where you are crawling 100s of urls and want a concurrency of 10 requests at a time without creating a new Pool every time 10 are done. You could use the following text I wrote as an answer for a question at Laravel's github discussions page. See: https://github.com/laravel/framework/discussions/43063#discussioncomment-3521639
-
Adding a new tip to discover all events fired in one request
These days I needed to find out the name of an event fired in a certain request and I found this method available for that. So i leave my contribution here if it helps =D
-
Fix Various Spelling Error, Syntax Highlighting and inconsistent code formatting
Hi Povilas!
I found some spelling errors when i visiting the tips ...
So i decide to clone the repository and ask PhpStorm to find all the spelling errors and fix it for this PR...While i reading some tips, i found out that some syntax highlighting is a bit off due to incorrect syntax, so i manually fix it and put under one PR.
AND when i try to write this description... I realize i also contribute to this repo almost same time last year, so i guess its a one year anniversary ? 🥳
Please let me know if any changes need to be made 😉
As always, thanks for maintaining this tips collection
基于 swoole 的多进程队列系统,低延时(最低毫秒级)、低资源占用, 支持一键化协程、超时控制、失败重试。可与 laravel thinkphp 等框架配合使用
multi-process-queue 基于swoole的多进程队列系统,manage进程管理子进程,master进程监听队列分发任务,worker进程执行任务, 多进程、低延时(最低毫秒级)、低资源占用。可与 laravel thinkphp 等框架配合使用 版本要求: php>=7.1 swoo
This package provides some basic methods to implement a self updating functionality for your Laravel application. Already bundled are some methods to provide a self-update mechanism via Github or some private repository via http.
This package provides some basic methods to implement a self updating functionality for your Laravel 5 application. Already bundled are some methods to provide a self-update mechanism via Github.
A magic PHP framework. Build reactive web apps without writing HTML, CSS, or JavaScript! Powered by Tailwind, Alpine, Laravel, & Livewire.
Malzahar A magic PHP framework. Build reactive web apps without writing HTML, CSS, or JavaScript! Powered by Tailwind, Alpine, Laravel, & Livewire. Re
Supercharge your Laravel application's performance.
Introduction Laravel Octane supercharges your application's performance by serving your application using high-powered application servers, including
I made my own simple php framework inspired from laravel framework.
Simple MVC About Since 2019, I started learning the php programming language and have worked on many projects using the php framework. Laravel is one
A set of ready-made regex helper methods for use in your Laravel application.
Regex A set of ready-made regex helper methods for use in your Laravel application. Installation composer require hotmeteor/regex Usage Regex comes wi
An intelligent code generator for Laravel framework that will save you time
An intelligent code generator for Laravel framework that will save you time! This awesome tool will help you generate resources like views, controllers, routes, migrations, languages and/or form-requests! It is extremely flexible and customizable to cover many of the use cases. It is shipped with cross-browsers compatible template, along with a client-side validation to modernize your application.
A modified version of the Laravel Framework
Hexavel Framework Hexavel is a restructured version of Laravel, with the purpose of providing better work flows which will simplify the development pr
RoadRunner ⇆ Laravel bridge
RoadRunner ⇆ Laravel bridge Easy way for connecting RoadRunner and Laravel applications. ?? If you want to see an example of a laravel application in
Laravel 5 nested category/menu generator
Laravel 5 Nestable Laravel Nestable to work with recursive logic. Category level there is no limit but this may vary depending on your server performa
Laravel 8 Project Restrict User Access From IP Addresses. prevent other ip address that want to access over secure api or urls.
block-ip-address-laravel Laravel 8 Project Restrict User Access From IP Addresses. prevent other ip address that want to access over secure api or url
💡 Mudrock is a MVC PHP framework, which was inspired by the Laravel and CodeIgniter frameworks.
?? Mudrock is a MVC PHP framework, which was inspired by the Laravel and CodeIgniter frameworks
Trabajo 06 Laravel y el modelo MVC
About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie
Files Course Laravel Microservice E-mail
Curso Laravel Microservices com RabbitMQ (micro e-mail) Saiba Mais Sobre o Curso Requisitos Este micro e-mail depende do microservice 01, portanto, pr
LaravelS is an out-of-the-box adapter between Swoole and Laravel/Lumen.
?? LaravelS is an out-of-the-box adapter between Swoole and Laravel/Lumen.
Generate auto numbers for your Laravel Model.
Generate Autonumbers for your Laravel Model This package can help you in creating autonumbers for your laravel model. You can create autonumbers using
I made my own simple php framework inspired from laravel framework.
Simple MVC About Since 2019, I started learning the php programming language and have worked on many projects using the php framework. Laravel is one
This package provides a high performance HTTP server to speed up your Laravel/Lumen application based on Swoole.
This package provides a high performance HTTP server to speed up your Laravel/Lumen application based on Swoole.
Rori-PHP is custom non production web application framework inspired by Laravel syntax
Rori-PHP is custom non production web application framework inspired by Laravel syntax. A web framework provides a structure and starting point for your application allowing you to focus on creating something amazing.