Talk: PG-13
Created Basecode podcast, Laravel Shift
Today, sharing code samples from shift analytics
Casting
Not much attribute casting done (e.g. $casts = ['user_id' => 'integer', 'active' => 'boolean'];
)
Can matter when the underlying data structure doesn't store it in that type (e.g. MySQL storing a boolean as tinyint) or when setting the thing directly on the model
Can also cast as an array!
Can also set up getXAttribute/setXAttribute methods on a model
Gotcha: Array union. Use a temporary
Model Relationships
// Direct mapping
$setting->user_id = $user->id;
// Indirect mapping
$setting->user()->associate($user);
$setting->user()->disassociate($user);
// Handy for many-to-many
$user->settings()->attach($setting);
$user->settings()->detach($setting);
Pivots
Intermediary tables for many-to-many associations
Example: Team can have many users, users can be on many teams
Say there's an approval process for a team.
public function teams()
{
return $this->belongsToMany(Team::class)->wherePivot('approved', 1);
}
Can do pivot class!
class Membership extends Pivot {
protected $table = 'team_user';
public $incrementing = true;
// Binds
protected $with = ['user', 'team'];
public function user() { return $this->belongsTo(User::class); }
public function team() { return $this->belongsTo(Team::class); }
}
In RoR, when reaching for complex relationships, can also define it
MorphMap
Custom Polymorphic Types
Decoupling database from internal application structure
Can define it yourself
Relation::morphMap([
'posts' => 'Model\Post',
'videos' => 'Model\Video'
]);
Views
@if/@endif's is common, but there's also...
- @isset($thing)
- @empty($thing)
- @auth
- @guest
Also, Blade directives like @csrf
(beats csrf_token()
and csrf_method()
)
$loop also has index, iteraiton, remaining, count, first, last properties
Performance
When you have a View composer, you can share settings everywhere. Quick, easy, great...but runs for every single view, including partials, sidebars, headers...could run multiple times!
Instead, target high-level (e.g. layout), not wildcard
Responses
try {
if ($connection->isGitLab()) {
GitLabClient::addCollaborator($connection->access_token);
}
} catch (GitLabClientException $e) {
Log::error();
return redirect()->back()->withInput($request->input());
}
Instead, extend a custom Exception, then override the render method and to do the catch stuff.
Form Requests
There are redirection properties like $redirect, $redirectRoute, $redirectAccess for URIs/routers/controller actions to redirect to when an action fails
API Responses
Can extend JsonResource and implement toArray, withResponse...
Authentication
Laravel provides tons of different hooks. Instead of replacing/rewriting, you can just replace authenticated for additional login acctions and change response
Authorization
Might have $this->ensureUserCanViewVideo($user, $video)
call that either returns or abort(403)'s.
Instead, use gates/policies. Policies map better to models
Gate::define('watch-video', function ($user, $lesson) {
return $lesson->isFree();
})
abort_unless(Gate::allows('watch-video', ...))
Also has blade directives! @can
Signed URLs and Temporary Signed URLs
Prevent someone from changing user_id, team_id, etc. ($this->middleware('signed')
)
Response chains
If you're not authorized, respond with response(null, 403); Instead, do a chain (return response()->noContent(403);
) or just abort(403)
Or abort_if
, abort_unless
, throw_if
, throw_unless
@gonedark on Twitter