Tips and Tricks of Laravel

Tips and Tricks of Laravel - Laravel Best Practises tips and technique

Tips and Tricks of Laravel - Laravel Best Practises tips and technique

In this blog series, I will show you some Tips and Tricks of Laravel. Every Laravel developer should know how to write clean code and not write unnecessary code. We look at some tips and tricks at Laravel for writing better code to help and optimize our app to get better performance.

Laravel 6 tips and tricks

Tip 1. Invokable Controllers

From Laravel 5.6.28 – if you want to create a controller with just one action, you can use __invoke() method and even create “invokable” controller

namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;

class ShowProfile extends Controller
{

  public function __invoke($id)
  {
    return view('user.profile', ['user' => User::findOrFail($id)]);
  }
}

Routes:

Route::get('user/{id}', 'ShowProfile');

Artisan command to generate this controller

php artisan make:controller ShowProfile --invokable

Tip 2. 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'); //if primary id Increments
   $table-> unsignedBigInteger ('company_id'); //if primary id BigIncrements
   $table->foreign('company_id')->references('id')->on('companies');

});

Tip 3. 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');
}

Tip 4 :  Raw DB Queries

You can use RAW DB queries in various places, including havingRaw() function after groupBy().

Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();

Tip 5 . $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

  This is user {{ $user->id }}
@endforeach

There are also other properties like $loop->iteration or $loop->count . 

Tip 6. 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();

Tip 7. Route group within a group

in Routes, you can create a group within a group, assigning a certain middleware only to some URLs in the “parent” group.

Route::group(['prefix' => 'account', 'as' => 'account.'], function() {

 Route::get('login', 'AccountController@login');
 Route::get('register', 'AccountController@register');

  Route::group(['middleware' => 'auth'], function() {
    Route::get('edit', 'AccountController@edit');
  });

});

Tip 8. 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);

Tip 9. Does view file exist?

if (view()->exists('custom.page')) {

// Load the view

}

Tip 10. 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;
}

Tip 11. 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');

Tip 12. Soft-deletes: multiple restore

When using soft-deletes, you can restore multiple rows in one sentence

Post::withTrashed()->where('author_id', 1)->restore();

Tip 13. Image validation

While validating uploaded images, you can specify the dimensions you require.

'photo' => 'dimensions:max_width=4096,max_height=4096'

Tip 14 Testing email into laravel.log

If you want to test email contents in your app but unable or unwilling to set up something like Mailgun, use .env parameter MAIL_DRIVER=log and all the email will be saved into storage/logs/laravel.log file, instead of actually being sent.

Tip 15. Don’t create 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

// Do this
Route::view('about', 'texts.about');

Tip 16. 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

Tip 17  Model all: columns

When calling Eloquent’s Model::all() , you can specify which columns to return.

$users = User::all(['id', 'name', 'email']);

Tip 18. 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','codechief@gmail.com')->firstOrFail();

Tip 19. 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']),

]);

Tip 20. More convenient DD

Instead of doing dd($result); you can put ->dd() as a method directly at the end of your Eloquent sentence, or any Collection.

// Instead of
$users = User::where('name', 'Taylor')->get();
dd($users);

// Do this
$users = User::where('name', 'Taylor')->get()->dd();

Tip 21. How to avoid error in {{ $post->user->name }} if user is deleted?

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.

/**
* Get the author of the post.
*/
public function user()
{
   return $this->belongsTo('App\User')->withDefault();
}

Tip 22. Route Model Binding: You can define a key

You can do Route model binding like Route::get(‘api/users/{user}’, function (App\User $user) { … } – but not only by ID field. If you want {user} to be a username
field, put this in the model:

public function getRouteKeyName() {

   return 'username';

}

Tip 23. Redirect to Specific Controller Method

You can redirect() not only to URL or specific route, but to a specific Controller’s specific method, and even pass the parameters. Use this:

return redirect()->action('SomeController@method',['param' => $value]);

Tip 24. 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
{
 /**
  * All of the relationships to be touched.
  *
  * @var array
  */

 protected $touches = ['post'];

}

Tip 25. 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

Tip 26. Blade Directives: IncludeIf, IncludeWhen, IncludeFirst

If you are not sure whether your Blade partial file actually would exist, you may use these condition commands

This will load header only if Blade file exists

@includeIf('partials.header')

This will load header only for user with role_id 1

@includeWhen(auth()->user()->role_id == 1, 'partials.header')

This will try to load adminlte.header, if missing – will load default.header

@includeWhen(auth()->user()->role_id == 1, 'partials.header')

This will try to load adminlte.header, if missing – will load default.header

@includeFirst('adminlte.header', 'default.header')

Hope this laravel tips and trcks tutorial will be helpful for you.

About Post Author