16 of laravel's pro tips and tricks

16 Laravel Pro Tips and Tricks

Spread the love

1: Auto Model Validation

Automatically validate model or anything you want to perform before save, update or create.

class Post extends Eloquent
{
	public staic $autoValidates = true;

	protected static $rules = [];

	protected static function boot()
	{
		parent::boot();

		// or static::creating, or static::updating
		static::saving(function($model)
		{
			if ($model::$autoValidates) {
				return $model->validate();
			}
		});
	}

	public function validate()
	{

	}
}

2: Prevent Update

Some times you want to prevent update on any model, for this purpose you can use code written below:

class Post extends Eloquent
{
	protected static function boot()
	{
		parent::boot();

		static::updating(function($model)
		{
			return false;
		});
	}
}

3: Get Random Rows

Get random rows from a table using Eloquent:

$questions = Question::orderByRaw('RAND()')->take(10)->get();

4: Make UUID as Primary Key

By default the primary key is integer, but some times you want primary key as UUID, can be achieved by following code:

use Ramsey\Uuid\Uuid;

trait UUIDModel
{
	public $incrementing = false;

	protected static function boot()
	{
		parent::boot();

		static::creating(function ($model)
		{
			$key = $model->getKeyName();

			if (empty($model->{$key})) {
				$model->{$key} = (string) $model->generateNewUuid();
			}
		});
	}

	public function generateNewUuid()
	{
		return Uuid::uuid4();
	}
}

4: Append Mutated Property

Mutated properties can be appended by following way:

function getFullNameAttribute() 
{
	return $this->first_name . ' ' . $this->last_name;
}

class User extends Model
{
	protected $appends = ['full_name'];
}

5: Return Relationship on Model Save

In normal case when data is saved on specific model it will return that updated model, but in some cases you expect some thing different. For example on save return some relationship:

public function store()
{
	$post = new Post;
	$post->fill(Input::all());
	$post->user_id = Auth::user()->user_id;

	$post->user;

	return $post->save();
}

6: Dynamic With

// eloquent
Post::whereSlug('slug')->get();

// instead of
View::make('posts.index')->with('posts', $posts);

// do this
View::make('posts.index')->withPosts($posts);

7: Collection Filters

It will keep the item in collection if the closure returns true:

$customers = Customer::all();

$us_customers = $customers->filter(function($customer)
{
	return $customer->country == 'United States';
});

8: Call implode on Collection

I am sure that you have used php’s implode many times, but do you know you can call implode directly on Laravel’s collection?

$collection = Person::all();

$names = $collection->implode('first_name', ',');

9: Laravel’s Collection Sorting With Closure

$sorted = $collection->sortBy(function($product, $key)
{
 return array_search($product['name'], [1=>'Bookcase', 2=>'Desk', 3=>'Chair']);
});

10: Laravel Collection Unions

// the point is to actually combine results from different models
$collection = new Collection;

$all = $collection->merge($programmers)->merge($critics)->merge($engineers);

11: Share Cookies Between Domains

// app/Http/Middleware/EncryptCookies.php
protected $except = [
	'shared_cookie',
];

Cookie::queue('shared_cookie', 'my_shared_value', 10080, null, '.example.com');

12: Customize Default Error Page

<?php namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\Debug\ExceptionHandler as SymfonyDisplayer;

class Handler extends ExceptionHandler
{
	protected function convertExceptionToResponse(Exception $e)
	{
		$debug = config('app.debug', false);
		
		return $debug
			? (new SymfonyDisplayer($debug))->createResponse($e)
			: response()->view('errors.default', ['exception' => $e], 500);
	}
}

13: Conditional Service Providers

// app/Providers/AppServiceProvider.php
public function register()
{
	$this->app->bind(
		\Illuminate\Contracts\Auth\Registrar::class,
		\App\Services\Registrar::class
	);

	if ($this->app->environment('production')) {
		$this->app->register(\App\Providers\ProductionErrorHandlerServiceProvider::class);
	}
	else {
		$this->app->register(\App\Providers\VerboseErrorHandlerServiceProvider::class);
	}
}

14: Capture Queries

Event::listen('illuminate.query', function($query)
{
	var_dump($query);
});

\DB::listen(function($query, $bindings, $time)
{
	var_dump( $query, $bindings, $time);

});

15: Authorization Without Models

// app/Policies/AdminPolicy.php
class AdminPolicy
{
	public function managePages($user)
	{
		return $user->hasRole(['Administrator', 'Content Editor']);
	}
}

// app/Providers/AuthServiceProvider.php
public function boot( \Illuminate\Contracts\Auth\Access\GateContract $gate)
{
	foreach (get_class_methods(new \App\Policies\AdminPolicy) as $method) {
		$gate->define($method, \App\Policies\AdminPolicy::class . "@{$method}");
	}
	$this->registerPolicies($gate);
}

$this->authorize('managePages'); // in Controllers
@can('managePages') // in Blade
$user->can('managePages'); // via Eloquent

16: Avoid Logs Over Flow

$schedule->call(function()
{
	Storage::delete($logfile);
})->weekly();

3 thoughts to “16 Laravel Pro Tips and Tricks”

  1. Bad Practices:

    1: Auto Model Validation (do it on the controller)
    4: Make UUID as Primary Key (add a new column called uuid instead)
    4: Append Mutated Property (add a new column called full_name)
    6: Dynamic With (no need, be consistent and use ->with([‘posts’ => $posts]))
    13: Conditional Service Providers (Disable APP_DEBUG on production environment)
    16: Avoid Logs Over Flow (use daily logging and log the last 7 days)

  2. Hi,

    First i’d like to say it’s nice to see you want to help other developers with tips and tricks. However some of them don’t make sense to me or are basicly wrong.

    1:
    It’s fine if you choose to auto validate models, but i would strongly advise against it, validation shouldn’t be the models Job and FormRequests are the answer to seperate that logic. Your example is also incomplete because what should the method validate() do?

    2:
    This one doesn’t make sense to me, why adding this to the model if you can simply not create an update endpoint? You expect the update() method to update a model, it will cause confusion if you overwrite this functionality. If you don’t want to update a model, simply don’t update it.

    3:
    You can simply use https://laravel.com/api/5.8/Illuminate/Database/Query/Builder.html#method_inRandomOrder

    4: Make UUID as Primary Key
    Looks fine

    4: (duplicate) : Append Mutated Property
    You should move the method inside the class

    5: Return Relationship on Model Save
    The only thing you will get returned is a boolean since save will always return a boolean:
    https://github.com/laravel/framework/blob/5.8/src/Illuminate/Database/Eloquent/Model.php#L644

    I would do something like this (considering user has a hasMany posts relationship):
    public function store()
    {
    $post = Auth::user()->posts()->create(
    Input::all()
    );

    return $post->user; // If you only want the user

    // If you want the post with user relationship:
    $post->load([‘user’]);
    return $post;
    }

    15: Authorization Without Models
    Looks fine but have some pointers, i would have my AuthServiceProvider like so:

    use Gate;
    use App\Policies\AdminPolicy;

    class AuthServiceProvider extends ServiceProvider
    {
    public function boot()
    {
    foreach (get_class_methods(AdminPolicy::class) as $method) {
    Gate::define($method, AdminPolicy::class . “@{$method}”);
    }

    $this->registerPolicies();
    }
    }

    I hope this will help you, and other developers, i’m always open for discussions if you don’t agree with me on some points.

Comments are closed.