明日から使えるLaravel テクニック
InnoCafe vol.18
@localdisk
自己紹介
松尾 大(まつお まさる)
- http://twitter.com/localdisk
- Laravelエンジニア養成読本
- Laravelリファレンス
前置き
本スライドははLaravel 5.2を対象にしてます
http://slides.com/masarumatsuo/innocafe-18#/
JSON を返す
配列を返す
Route::get('/', function() {
return ['foo', 'bar'];
});
Content-Type がちゃんと
application/json になる
Model を返す
Route::get('users', function() {
// モデルファクトリー便利
$user = factory(\App\User::class)->make();
return $user;
});
解説
returnしてJSONでレスポンスさせるには以下の条件のいずれかに該当させる必要があります。
- Jsonableを実装する
- ArrayObjectを継承する
- JsonSerializableを実装する
- is_arrayがtrue
補足
- 他のクラスもJSONで返したい
- Response::jsonメソッドを使おう
- ゴニョゴニョしたいならJsonableを実装してtoJsonメソッド実装しよう
- XMLで返したい
- Responseマクロを使おう
イベントあれこれ
イベントの基本
-
イベントを発生(fire)させるところと実行(listen)させるところが分かれてる
- 前者を 'Event' 、後者を 'Listner' と呼ぶ
- 双方用意されて初めて効果を発揮する
- この特性を利用して、LaravelにはModelやAuthとかに仕込まれている。便利。
既存のイベントを使う
# ロールバックされた時のリスナを作る
$ php artisan make:listener RollbackListner
--event=Illuminate\Database\Events\TransactionRolledBack
<?php
namespace App\Listeners;
use Illuminate\Database\Events\TransactionRolledBack;
class RollbackListner
{
public function handle(TransactionRolledBack $event)
{
// ロールバックされたクエリを参照できる
dd($event->connection->getQueryLog());
}
}
イベント + キュー
非同期イベント
- イベントを非同期に処理する
- メール配信諸々(ユーザー登録、エラー通知)
- 画像がアップロードされたらリサイズしてクラウドストレージに保存
- 重くて急がない処理に使う
- 最近流行のマイクロサービス(サービス間の連携)とか
- ドライバはSQSとかRedisとかが手軽だと思う
非同期イベント
php artisan make:event AsyncEvent
php artisan make:listener AsyncLister
--event=App\\Events\\AsyncEvent
// ShouldQueue を implements するのがポイント
class AsyncLister implements ShouldQueue
{
}
認証と認可
Laravelの認証と認可
- Laravel 5.0 までは色々機能が足らなかった
- 5.1/5.2 でほとんど作りこまなくていいレベルまで来た
- 5.1.11 で認可
- 5.2 で MultiAuth、TokenGuard
- TokenGuardは簡易的すぎるのでJWTのほうがよさげ
認証のセットアップ
php artisan make:auth
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/auth/login.blade.php
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/auth/register.blade.php
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/auth/passwords/email.blade.php
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/auth/passwords/reset.blade.php
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/auth/emails/password.blade.php
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/layouts/app.blade.php
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/home.blade.php
Created View: /Users/localdisk/NetBeansProjects/five-point-two/resources/views/welcome.blade.php
Installed HomeController.
Updated Routes File.
MultiAuth
-
サービスを運用するにあたりテーブルは分けたい
- 一般ユーザーと管理者では持つ情報がぜんぜん違う
- 認証するテーブルを別にできる
- 一般ユーザーは `users` 管理者は `admins` とか
MultiAuthやってみる
# -m つけるとマイグレーションファイルも作ってくれる
php artisan make:model Admin -m
class CreateAdminsTable extends Migration
{
public function up()
{
Schema::create('admins', function (Blueprint $table) {
// CreateUsersTable からコピペ
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
}
MultiAuthやってみる
<?php
return [
'guards' => [
// 追加
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
// 追加
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
],
MultiAuthやってみる
// モデルファクトリを追加
// database/factories/ModelFactory.php
$factory->define(App\Admin::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
];
});
➜ five-point-two php artisan tinker
Psy Shell v0.7.2 (PHP 7.0.4 — cli) by Justin Hileman
>>> factory(App\Admin::class)->create(['password' => bcrypt('secret')]);
=> App\Admin {#719
name: "Mr. Sage McDermott",
email: "kFeest@yahoo.com",
updated_at: "2016-03-29 06:45:52",
created_at: "2016-03-29 06:45:52",
id: 2,
}
MultiAuthやってみる
// http://localhost:8000/admin
Route::group(['prefix' => 'admin'], function() {
Route::get('login', function() {
// ビューはコピる
return view('admin.login');
});
Route::post('login', function(\Illuminate\Http\Request $request) {
$credentials = $request->only(['email', 'password']);
// guard メソッドの引数に `admin` を入れるのがポイント
$result = Auth::guard('admin')->attempt($credentials);
dd($result);
});
});
認証と認可
認証…ネットワークやサーバへ接続する際に本人性をチェックし、正規の利用者であることを確認する方法。
認可…認証によって確認された利用者を識別して、アクセス権限の制御を行い、利用者ごとに固有のサービスを提供すること。
- http://www.atmarkit.co.jp/ait/articles/0401/01/news067.html
- http://www.atmarkit.co.jp/ait/articles/0401/01/news068.html
Laravelの認可
Gateファサードを使ってみよう
➜ five-point-two php artisan make:model Profile -m
Model created successfully.
Created Migration: 2016_03_29_083825_create_profiles_table
➜ five-point-two php artisan migrate
Migrated: 2016_03_29_083825_create_profiles_table
$factory->define(App\Profile::class, function (Faker\Generator $faker) {
return [
'nickname' => $faker->name,
'user_id' => factory(\App\User::class)->create()->id,
];
});
Laravelの認可
➜ five-point-two php artisan tinker
>>> factory(App\Profile::class)->create();
=> App\Profile {#708
nickname: "Delbert Rau",
user_id: 2,
updated_at: "2016-03-29 08:44:30",
created_at: "2016-03-29 08:44:30",
id: 1,
}
Laravelの認可
Gateファサードを使ってみよう
<?php
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
// ユーザーIDとプロフィールIDが一致すればOK
\Gate::define('update-profile', function($user, $profile){
return $user->id === $profile->user_id;
});
}
}
Laravelの認可
Gateファサードを使ってみよう
<?php
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
// ユーザーIDとプロフィールIDが一致すればOK
\Gate::define('update-profile', function($user, $profile){
return $user->id === $profile->user_id;
});
}
}
Demo
明日から使えるLaravelテクニック
By Masaru MATSUO
明日から使えるLaravelテクニック
明日から使えるLaravelテクニック
- 3,495