Open takanori-matsushita opened 4 years ago
Laravelのデバッグはデバッグバーを入れると便利らしい。
cd [Laravei-project]
composer require barryvdh/laravel-debugbar
config/app.php
'providers' => [
:
Barryvdh\Debugbar\ServiceProvider::class,
],
'aliases' => [
:
'Debugbar' => Barryvdh\Debugbar\Facade::class,
],
.env
APP_DEBUG=true
.envファイルを編集後はphp artisan config:clear
で再読み込み
こんな感じ感じのバーが下部に出てきたら完了。
リスト 7.1:, 7.2 省略
演習
省略
$ php artisan tinker
>>> User::count()
=> 1
>>> User::first()
=> App\User {#3118
id: 1,
name: "Michael Hartl",
email: "mhartl@example.com",
email_verified_at: null,
created_at: "2020-04-16 17:46:38",
updated_at: "2020-04-16 17:46:38",
}
リスト 7.3: Usersリソースをroutesファイルに追加する
Route::get('/', 'StaticPagesController@home')->name('root');
Route::get('/help', 'StaticPagesController@help')->name('help');
Route::get('/about', 'StaticPagesController@about')->name('about');
Route::get('/contact', 'StaticPagesController@contact')->name('contact');
Route::get('users/signup', 'UsersController@new')->name('users.signup');
Route::resource('users', 'UsersController'); //追加
resourceを使った場合のルート一覧
| | GET|HEAD | users | users.index | App\Http\Controllers\UsersController@index | web |
| | POST | users | users.store | App\Http\Controllers\UsersController@store | web |
| | GET|HEAD | users/create | users.create | App\Http\Controllers\UsersController@create | web |
| | GET|HEAD | users/{user} | users.show | App\Http\Controllers\UsersController@show | web |
| | PUT|PATCH | users/{user} | users.update | App\Http\Controllers\UsersController@update | web |
| | DELETE | users/{user} | users.destroy | App\Http\Controllers\UsersController@destroy | web |
| | GET|HEAD | users/{user}/edit | users.edit | App\Http\Controllers\UsersController@edit | web |
リスト 7.4: ユーザー情報を表示するための仮のビュー
resources/views/users/show.blade.php
を作成
@php
$title = ''
@endphp
@extends('layouts.layout')
@section('content')
{{$user->name}},{{$user->email}}
@endsection
リスト 7.5: Usersコントローラのshowアクション app/Http/Controllers/UsersController.php
use App\User;
:
public function show($id)
{
$user = User::find($id);
return view('users.show', ['user' => $user]);
}
演習
@php
$title = ''
@endphp
@extends('layouts.layout')
@section('content')
{{$user->name}},{{$user->email}},{{$user->created_at}},{{$user->updated_at}}
@endsection
現在時刻:{{date("Y-m-d H:i:s")}}
リスト 7.6: eval(\Psy\sh())をUsersコントローラに差し込む
public function show($id)
{
$user = User::find($id);
eval(\Psy\sh()); //追加
return view('users.show', ['user' => $user]);
}
/users/1 をリロードしたら以下のようになる。
$user->name
=> "Michael Hartl"
$user->email
=> "mhartl@example.com"
$id
=> "1"
リスト 7.7: eval(\Psy\sh());をUsersコントローラーから取り外す
public function show($id)
{
$user = User::find($id);
return view('users.show', ['user' => $user]);
}
演習
省略
$user
PHP Notice: Undefined variable: user in /Users/matsushitatakanori/Desktop/codebase/tech-traning/laravel-practiceeval()'d code on line 3
=> null
リスト 7.8: ユーザー表示ビューに名前とGravatarを表示する resources/views/users/show.blade.php
@php
$title = $user->name
@endphp
@extends('layouts.layout')
@section('content')
<img src={{gravator_for($user)}}>
{{$user->name}}
@endsection
リスト 7.9: gravatar_forヘルパーメソッドを定義する app/Helpers/UsersHelper.php を作成
<?php
function gravator_for($user)
{
$gravator_id = md5(strtolower(trim($user->email)));
return "http://www.gravatar.com/avatar/" . $gravator_id;
}
Helperを作成したら、composer.jsonに以下を追加
"autoload": {
:
"files": [
:
"app/helpers/UsersHelper.php"
]
}
ターミナルで以下を実行。
composer dump-autoload
データベース情報の更新
$ php artisan tinker
=> "Example User"
>>> $user->email = "example@railstutorial.org"
=> "example@railstutorial.org"
>>> $user->password = "foobar"
=> "foobar"
>>> $user->save()
=> true
リスト 7.10: ユーザーのshowビューにサイドバーを追加する resources/views/users/show.blade.php
@php
$title = $user->name
@endphp
@extends('layouts.layout')
@section('content')
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<img src={{gravator_for($user)}}>
{{$user->name}}
</h1>
</section>
</aside>
</div>
@endsection
**リスト 7.11: SCSSを使ってサイドバーなどのユーザー表示ページにスタイルを与える
resources/sass/_custom.scss
そのままコピペした後に以下のコマンドを実行
yarn dev
演習
省略
リスト 7.12: gravatar_forヘルパーにオプション引数を追加する app/Helpers/UsersHelper.php
<?php
function gravator_for($user, $options = ["size" => 80])
{
$gravator_id = md5(strtolower(trim($user->email)));
$size = $options["size"];
return "http://www.gravatar.com/avatar/" . $gravator_id . "?s=" . $size;
}
resources/views/users/show.blade.php
<img src={{gravator_for($user, $options = ["size"=>50])}}>
省略
リスト 7.14: newアクションに@user変数を追加する app/Http/Controllers/UsersController.php
public function new()
{
$user = new User();
return view('users.new', ["user"=>$user]);
}
Laravelでは、すでに用意されているUserモデルに対応する登録フォーム等があるので、それを導入する。
まずは、larabel/ui をインストールする。
composer require laravel/ui --dev
インストールが完了したら、以下のコマンドを実行。
php artisan ui bootstrap --auth
以下のファイルが生成される。
app/Http/Controllers/Auth/
app/Http/Controllers/HomeController.php
database/migrations/2014_10_12_100000_create_password_resets_table.php
resources/sass/_variables.scss
resources/views/auth/
resources/views/home.blade.php
resources/views/layouts/app.blade.php
※『Please run "npm install && npm run dev" to compile your fresh scaffolding.』と言われた場合は以下のコマンド実行
npm install
or yarn install
resources/sass/app.scss
ファイルが変更されているので、一番下の行に以下を追加。
@import "custom";
以下のコマンドを実行し、scssをビルドする。
npm run dev
or yarn dev
usersのルート一覧
php artisan route:list
| | GET|HEAD | api/user | | Closure | api,auth:api |
| | GET|HEAD | home | home | App\Http\Controllers\HomeController@index | web,auth |
| | GET|HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest |
| | POST | login | | App\Http\Controllers\Auth\LoginController@login | web,guest |
| | POST | logout | logout | App\Http\Controllers\Auth\LoginController@logout | web |
| | GET|HEAD | password/confirm | password.confirm | App\Http\Controllers\Auth\ConfirmPasswordController@showConfirmForm | web,auth |
| | POST | password/confirm | | App\Http\Controllers\Auth\ConfirmPasswordController@confirm | web,auth |
| | POST | password/email | password.email | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web |
| | GET|HEAD | password/reset | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web |
| | POST | password/reset | password.update | App\Http\Controllers\Auth\ResetPasswordController@reset | web |
| | GET|HEAD | password/reset/{token} | password.reset | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web |
| | GET|HEAD | register | register | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest |
| | POST | register | | App\Http\Controllers\Auth\RegisterController@register | web,guest |
リスト 7.15: 新規ユーザーのためのユーザー登録フォーム
php artisan ui bootstrap --auth
で生成された登録フォームを以下のように変更する。
resources/views/auth/register.blade.php
@php
$title = 'Sign up';
@endphp
@extends('layouts.layout')
@section('content')
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 offset-md-3">
<form method="POST" action="{{ route('users.create') }}">
@csrf
@include('shared.error_messages')
<label for="name">Name</label>
<input type="text" id="user_name" name="name" class="form-control @error('name') is-invalid @enderror" value="{{old('name')}}">
<label for="email">Email</label>
<input type="email" id="user_email" name="email" class="form-control @error('email') is-invalid @enderror" value="{{old('email')}}">
<label for="password">Password</label>
<input type="password" id="user_password" name="password" class="form-control @error('password') is-invalid @enderror">
<label for="password_confirmation">Confirmation</label>
<input type="password" id="user_password_confirmation" name="password_confirmation" class="form-control">
<input type="submit" class="btn btn-primary" value="Create my account">
</form>
</div>
</div>
@endsection
form actionのルートが存在しないため、エラーで怒られる。そのため、ルートに以下を追加。
Route::post('/users', 'Auth\RegisterController@register')->name('users.create');
リスト 7.16: ユーザー登録フォームのCSS
resources/sass/_custom.scss
そのままコピペし、以下のコマンドを実行。
yarn dev
リスト 7.17: 図 7.12のフォームのHTMLソース 省略
演習
リスト 7.18: ユーザー登録の失敗に対応できるcreateアクション
app/Http/Controllers/Auth/RegisterController.php
use RegistersUsers;
をたどると、
vendor/laravel/ui/auth-backend/RegistersUsers.php
がtraitとしてファイル分割されており、その中にrgisterアクションが用意されているため、そちらを利用する。
省略
リスト 7.20: ユーザー登録失敗時にエラーメッセージが表示されるようにする resources/views/auth/register.blade.php
@php
$title = 'Sign up';
@endphp
@extends('layouts.layout')
@section('content')
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 offset-md-3">
<form method="POST" action="{{ route('users.create') }}">
@csrf
@include('shared.error_messages') //追加・以下それぞれクラス追加
<label for="name">Name</label>
<input type="text" id="user_name" name="name" class="form-control">
<label for="email">Email</label>
<input type="email" id="user_email" name="email" class="form-control">
<label for="password">Password</label>
<input type="password" id="user_password" name="password" class="form-control">
<label for="password_confirmation">Confirmation</label>
<input type="password" id="user_password_confirmation" name="password_confirmation" class="form-control">
<input type="submit" class="btn btn-primary" value="Create my account">
</form>
</div>
</div>
@endsection
リスト 7.21: フォーム送信時にエラーメッセージを表示するためのパーシャル resources/views/shared/error_messages.blade.php
@if ($errors->any())
<div id="error_explanation">
<div class="alert alert-danger">
@if (count($errors) == 1)
The form contains 1 error
@elseif (count($errors) > 1)
The form contains {{count($errors)}} errors
@endif
</div>
<ul>
@foreach ($errors->all() as $error)
<li>{{$error}}</li>
@endforeach
</ul>
</div>
@endif
リスト 7.22: エラーメッセージにスタイルを与えるためのCSS resources/sass/_custom.scss
#error_explanation {
color: red;
ul {
color: red;
margin: 0 0 30px 0;
}
}
.field_with_errors {
@extend .invalid-feedback;
.form-control {
color: $red;
}
}
以下のコマンドを実行
yarn dev
演習
app/Http/Controllers/Auth/RegisterController.php
のvalidatorメソッドを以下のように変更する。
:
'password' => ['required', 'string', 'min:5', 'confirmed'], //min:5に変更
php artisan dusk:make UsersSignupTest
リスト 7.23: 無効なユーザー登録に対するテストgreen tests/Browser/UsersSignupTest.php
public function testInvalidSignupInformation()
{
$this->browse(function (Browser $browser) {
$browser->visit(route('users.signup'))
->type('name', '')
->type('email', 'user@invalid')
->type('password', 'foo')
->type('password_confirmation', 'bar')
->press('Create my account')
->assertPathIs('/signup')
->assertSee('The form contains 3 errors');
});
}
リスト 7.24: green
php artisan dusk
演習
public function testInvalidSignupInformation()
{
$this->browse(function (Browser $browser) {
:
->assertSee('The name field is required')
->assertSee('The password must be at least 8 characters.')
->assertSee('The password confirmation does not match.');
});
}
リスト 7.28: 保存とリダイレクトを行う、userのcreateアクション 保存のコードはLaravel Authで実装されているので、リダイレクト先の設定を行う。 [参考]リダイレクト先変更 app/Http/Controllers/Auth/RegisterController.php
protected $redirectTo = RouteServiceProvider::HOME; //この行を削除
//redirectTOメソッドを実装
protected function redirectTo()
{
return route('users.show', ['user' => \Auth::id()]);
}
リスト 7.29: ユーザー登録ページにフラッシュメッセージを追加する app/Http/Controllers/Auth/RegisterController.php
protected function redirectTo()
{
session()->flash('success', 'Welcome to the Sample App!');
return route('users.show', ['user' => \Auth::id()]);
}
リスト 7.30: コンソールでflashハッシュをイテレート (each do ... end) する
$ php artisan tinker
>>> $flash = ["success"=>"It worked!", "danger"=>"It failed."]
=> [
"success" => "It worked!",
"danger" => "It failed.",
]
>>> foreach($flash as $key => $value) {
var_dump($key);
var_dump($value);
}
string(7) "success"
string(10) "It worked!"
string(6) "danger"
string(10) "It failed."
リスト 7.31: flash変数の内容をWebサイトのレイアウトに追加する resources/views/layouts/flash.blade.php を作成
@if (Session::has('success'))
<div class="alert alert-success">{{session('success')}}</div>
@endif
resources/views/layouts/layout.blade.php
<!DOCTYPE html>
<html>
<head>
<title>{{fullTitle($title)}}</title>
@include('layouts.laravel_default')
@include('layouts.shim')
</head>
<body>
@include('layouts.header')
<div class="container">
@include('layouts.flash')
@yield('content')
@include('layouts.footer')
</div>
</body>
</html>
データベースのリセット
php artisan migrate:refresh
演習
$ php artisan tinker
>>> User::where("email", "example@railstutorial.org")->first()
=> App\User {#3136
id: 1,
name: "Rails Tutorial",
email: "example@railstutorial.org",
email_verified_at: null,
created_at: "2020-04-18 23:03:03",
updated_at: "2020-04-18 23:03:03",
}
リスト 7.33: 有効なユーザー登録に対するテストgreen tests/Browser/UsersSignupTest.php
public function testValidSignupInformation()
{
$this->browse(function (Browser $browser) {
$browser->visit(route('users.signup'))
->type('name', 'Example User')
->type('email', 'user@example.com')
->type('password', 'password')
->type('password_confirmation', 'password')
->press('Create my account')
->assertPathIs('/users/1')
->assertSee('Welcome to the Sample App!')
->assertSee('Example User')
->visit('/users/1')
->assertDontSee('Welcome to the Sample App!');
});
}
テスト後にテストデータを削除するため、クラスの最初の行に以下を追加。
use DatabaseMigrations;
ここでDuskテストを実行してしまうと、データベースがリセットされるため、以下の設定を行ってから実行する。
今後データベースを使ったテストは、本番用とテスト用で使用するデータベースを分けたほうが、利便性が高いため、以下のように設定する。
laravel_practice_test データベースの作成
$ psql -d laravel_practice
laravel_practice=# CREATE DATABASE laravel_practice_test;
Laravelプロジェクトルートで以下を実行。
cp .env .env.dusk.local
.env.dusk.localを編集
DB_DATABASE=laravel_practice_test
php artisan config:clear
phpunitテストの設定も変更しておく。
Laravelプロジェクトルートで以下を実行。 cp .env .env.testing
.env.testingを編集
APP_ENV=testing
DB_DATABASE=laravel_practice_test
phpunit.xmlの編集 以下の2行を削除
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
これに伴い、UserTestを一部編集する。 tests/Feature/UserTest.php
:
use Illuminate\Foundation\Testing\DatabaseMigrations;
class UserTest extends TestCase
{
use DatabaseMigrations;
private $attributes;
public function setUp(): void //各テストで初めに実行する処理を記述する。
{
parent::setUp();
$this->attributes = [
'name' => 'Laravel User',
'email' => 'laravel@example.com',
'password' => bcrypt('password'),
];
}
:
}
use DatabaseMigrations;
は各テストごとにデータベースのマイグレーションを実行する。
そして、それぞれのテスト・データベースプロバイダをを修正する。
public function testShouldBeValid($name, $email, $expect)
{
User::create($this->attributes); //追加
:
}
private function stringUpper($emailUpper)
{
User::create($this->attributes); //追加
:
}
private function stringLower($emailUpper)
{
User::create($this->attributes); //追加
:
}
public function userDataProvider()
{
:
'email unique error' => ["Laravel User", "laravel@example.com", false], //変更
}
public function emailDataProvider()
{
:
'email upper lower error' => ["laravel@example.com", true], //変更
}
vendor/bin/phpunit
これでテストがgreenになる。
演習 上記で実装したため省略
branch: sign-up