January 4, 2016
Posted by funa : 12:29 PM | Gadget | Comment (0) | Trackback (0)
January 4, 2016
https://coinbaby8.com/laravel-php-dekirukoto.html
https://laravel10.wordpress.com/
https://paiza.jp/works/laravel/primer
ルーティング: URLと対応 .phpで終わせず処理をひとつのファイルやクラスにまとめる
Blade: テンプレートエンジン
ミドルウェア: URL前後に処理を付加
エラーハンドラ: 例外やエラーが発生した際の処理
DI : サービスコンテナというのを用いクラスインスタンスの依存度を極力下げて、実行時に外部から与えてもらえるように
バリデーション: 入力値のチェックを設定のみで自動的に
データベース連携
認証の自動化
■PHPフレームワーク Laravel入門 サンプルファイルのダウンロード
https://www.shuwasystem.co.jp/support/7980html/5258.html
■XAMPP 7.4.1 インスコ(X-platform/Apache/MySQL/PHP/Perl)
https://www.apachefriends.org/jp/index.html
Win用Exeでインスコ C:\xampp\htdocs ← http://localhost/
xamppコンパネのショートカットをデスクトップに作成
Composer PHPのパッケージ管理システム
https://getcomposer.org/download/
Win用Exeで通常(devでなく)でインスコ
PHPはC:\xampp\php\php.exe、ユーザパスはC:\xampp\php
Laravel インスコ(プロジェクト作成)
コマンドを打つと自動でインスコ
cd C:\xampp\htdocs
composer create-project laravel/laravel prj_laravel --prefer-dist
5分位掛かる
Xampp(appach, mysql)起動し、Laravelプロジェクト起動はコマンドを打つ
cd C:\xampp\htdocs\prj_laravel
php artisan serve
次のURLへアクセスする http://localhost:8000/
8000のルートはここ C:\xampp\htdocs\prj_laravel\public
http://localhost では:80
php artisan serve --port=8000 がデフォ、Xamppは80
netstat -an でリスナーを見れる(XAMPPコンパネでもOK)
C:\xampp\apache\conf\httpd.conf でDocumentRootを変更できる
Alias / "C:\xampp\htdocs\prj_laravel\public"でエイリアス?
自由に使えるか?
1)C:\xampp\htdocs\prj_laravel\public\direct_test1.php を置くとhttp://localhost:8000/direct_test1.php でPHPが動くページにアクセスできる
2)ビューで自由にPHPを動かせるか?→例えばtest.blade.phpに<?php --- ?>でコードを書けば動く
http://localhost:8000/_test でアクセスすれば下記ルートとビューが使われtest.blade.phpだけで動く
routes/web.php
C:\xampp\htdocs\prj_laravel\app\Http\Controllers 無し
config/app.php ファサード無し サービスプロバイダ無し
C:\xampp\htdocs\prj_laravel\app\Http\Middleware フィルタ無し
C:\xampp\htdocs\prj_laravel\app\Http/Kernel.php ミドルウェア無し
C:\xampp\htdocs\prj_laravel\resources\views\test.blade.php
http://localhost:8000/fun/
php artisan make:controller FunController --resource
MySQLにDB:test ID:test/testtestを設定しテーブルを作成
CREATE TABLE `fun_inquiry` (
`no` bigint(20) NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
`inquiry` text,
`title_ex` varchar(255) NOT NULL default '',
`inquiry_ex` text,
`date_latest` datetime NOT NULL default '1000-01-01 00:00:00',
`date_2ndlast` datetime NOT NULL default '1000-01-01 00:00:00',
`date_first` datetime NOT NULL default '1000-01-01 00:00:00',
`ip` varchar(255) NOT NULL default '',
`flag_who` tinyint(4) NOT NULL default '0',
`flag_active` tinyint(4) NOT NULL default '0',
PRIMARY KEY (`no`)
) ENGINE=InnoDB
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci;
/*
flag_who 1:customer,2:admin
flag_active 1:有効,2:削除
*/
ダミーデータ挿入
INSERT INTO `fun_inquiry`(`title`, `inquiry`, `date_lastest`, `date_first`, `ip`, `flag_who`, `flag_active`) VALUES ('あああ', 'いいい', now(), now(), '192.168.56.1', '2', '1')
.env とconfig/database.phpに DB情報を記入
変更後は php artisan config:cache
C:\xampp\htdocs\prj_laravel\routes\web.php にコントローラ渡し記述
index crate store show($id) edit($id) update(Request $request, $id) destroy($id)
C:\xampp\htdocs\prj_laravel\app\Http\Controllers\FunController.php にView渡し記述
C:\xampp\htdocs\prj_laravel\resources\views\index.blade.php など
index crate store show edit update destroyのViewファイルを作成し リンク設定
href=/でルートからリンクを指定
パスはルート/が安定する、相対だと理由不明で階層が崩れる事があった、Form methodを入れる
情報を表示させたい
コントローラに
$param = ['items' => $items,
'msg' => 'データを追加しました',
'request' => $request,
'response' => $response];
return view('index', $param);
ビューに
<?php dump($items);
dump($msg);
dump($request);
dump($response); ?>
バリデーションするのに同カラム保持のpostsテーブルが必要であったので作成(多分ダミー)
テーブル作成方法: php artisan make:model posts をCMDしSQL流し込み
CREATE TABLE `posts` (
`no` bigint(20) NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
`inquiry` text,
`title_ex` varchar(255) NOT NULL default '',
`inquiry_ex` text,
`date_latest` datetime NOT NULL default '1000-01-01 00:00:00',
`date_2ndlast` datetime NOT NULL default '1000-01-01 00:00:00',
`date_first` datetime NOT NULL default '1000-01-01 00:00:00',
`ip` varchar(255) NOT NULL default '',
`flag_who` tinyint(4) NOT NULL default '0',
`flag_active` tinyint(4) NOT NULL default '0',
PRIMARY KEY (`no`)
) ENGINE=InnoDB
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci;
エラー後は元のページに戻るが元の値とエラーを出すには
<input name="title" value="{{old('title')}}">
@if($errors->has('title'))
@foreach($errors->get('title') as $message)
<br><red>{{ $message }}</red>
@endforeach
@endif
//バリデーション例
https://qiita.com/fagai/items/9904409d3703ef6f79a2
https://blog.capilano-fw.com/?p=341#digitsdigits_between
$validate_rule = [
'title' => 'required|unique:posts|max:255',
'inquiry' => 'required',
'title_ex' => 'required|unique:posts|max:255',
'inquiry_ex' => 'required',
'date_latest' => 'required|date_format:Y-m-d H:i:s',
'date_2ndlast' => 'date_format:Y-m-d H:i:s',
'date_first' => 'required|date_format:Y-m-d H:i:s',
'ip' => 'required|ip',
'flag_who' => 'required|integer|between:1,2',
'flag_active' => 'required|integer|between:1,2'];
$this->validate($request, $validate_rule);
自分で命名したデータベースをLaravelに参照させたいときは、テーブル名をモデルファイル内で指定しなければいけない
php artisan make:model DbTblFunInquiry をCMDし
app/DbTblFunInquiry.php を編集
namespace App;
use Illuminate\Database\Eloquent\Model;
class DbTblFunInquiry extends Model{
protected $table = 'fun_inquiry';
}
コントローラでDB追加
$now = date('Y-m-d H:i:s');
$input = ['title' => $request->title,
'inquiry' => $request->inquiry,
'date_latest' => $now,
'date_first' => $now,
'ip' => $request->ip(),
'flag_who' => '1',
'flag_active' => '1'];
$insert = DB::insert('insert into fun_inquiry(title, inquiry, date_latest, date_first, ip, flag_who, flag_active) values (:title, :inquiry, :date_latest, :date_first, :ip, :flag_who, :flag_active)', $input);
DB操作で同じパラメータを使おうとしてもSQLで数が合わないとだめで$input作り直した
→エラーはrequest/responseインスタンスをダンプしキッチリと見ると原因がわかる
$update = DB::update('update fun_inquiry set
title = :title,
inquiry = :inquiry,
title_ex = :title_ex,
inquiry_ex = :inquiry_ex,
date_latest = :date_latest,
date_2ndlast = :date_2ndlast,
ip = :ip,
flag_who = :flag_who,
flag_active = :flag_active
where no = :no', $input);
$input = ['no' => $request->no];
$items = DB::select('select * from fun_inquiry where no = :no', $input);
■ララベルの基本
gitの管理対象から外す
.gitignore ファイルに追加
環境毎に変更したい情報
.env ファイルにステージング環境、本番環境の情報をまとめる
設定情報は下記以下、DB接続/メール/サービスプロバイダ登録/ファサード登録等
config/
バリデーションメッセージの日本語化
resources/lang/ja/validation.php
===============
├── app
│ └── Article.php
│ └── Http
│ └── Controllers
├── resources
│ └── views
└── routes
//基本構成
routes/web.php
C:\xampp\htdocs\prj_laravel\app\Http\Controllers ある程度処理をする?モデル化?
config/app.php ファサード サービスプロバイダ
C:\xampp\htdocs\prj_laravel\app\Http\Middleware フィルタ
C:\xampp\htdocs\prj_laravel\app\Http/Kernel.php ミドルウェア
C:\xampp\htdocs\prj_laravel\resources\views\test.blade.php
CRUDはリソースコントローラで一気作成ができる
php artisan make:controller PostsController --resource
モデルを作成cmd EloquentでDB接続 app/Article.php
php artisan make:model Article
ファサード
対象となるクラスの作成 class Payment {
サービスプロバイダの作成 php artisan make:provider PaymentServiceProvider
サービスコンテナに paymentキーでPaymentクラスをバインド
config/app.php に PaymentServiceProviderと エリアスを追加
認証用ビューとルートを作成(認証機能はプロジェクト作成時点で既成)
php artisan make:auth
//php artisanコマンド(独自作成も可)
何ができるかリスト確認cmd
php artisan list
使い方確認cmd
php artisan help コマンド名
cmdでララベル機能が使える
php artisan tinker
古いパッケージをチェック
composer update --dry-run
古いパッケージをチェック(グローバルの場合)
composer global update --dry-run
.env変更後は
php artisan config:cache
コントローラを作成cmd
php artisan make:controller WelcomeController
モデルを作成cmd
php artisan make:model Article
Form Request を生成
php artisan make:request ArticleRequest
CRUDはリソースコントローラで一気作成ができる
php artisan make:controller PostsController --resource
認証用ビューとルートを作成(認証機能はプロジェクト作成時点で既成)
php artisan make:auth
ルーティングのリストを表示
php artisan route:list
//jsファイルやcssファイルはpublicフォルダ配下に入れる、HTMLやIMGも
public
|__ css
|__ js
|__ img
|__ html
asset('ファイルパス')はpublicディレクトリのパスを返す関数、SSLならsecure_assset()
<script src="{{ asset(mix('js/app.js')) }}" defer></script>
<link href="{{ asset(mix('css/app.css')) }}" rel="stylesheet">
<img alt="ロゴ" src="{{ asset('/img/logo.png') }}">
url()で完全なURL、SSLならsecure_url( )
.hoge::before { background: url("../img/hoge.svg") no-repeat center center; }
レスポンスでHTMLファイルを返したい時
Route::get('fun/html', function() {
return File::get(public_path() . '/html/test_direct.html');
});
//ルーティング routes/web.php
必須パラメータ(値がないとエラー)
Route::get('login/{id]/{pass}', function($id, $pass){
任意パラメータ
Route::get('login/{id?]/{pass?}', function($id='noname', $pass='unknown'){
login/taro/aaa でアクセスするときRouteにlogin/taro/{pass?}とlogin/{id?]/{pass?}があればどうなる?
通常 http://url/コントローラ/アクション と設計され Route::get('パス', 'コントローラ@アクション' (アクションはコントローラ内のメソッド)
Route::get('/', 'WelcomeController@index');
Route::get('contact', 'WelcomeController@contact');
正規表現を配列にして、複数指定
Route::get('foo/{id}/{name?}', function($id, $name = 'init') {
return "パラメータ $id, $name";
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
下のようにnamed rootで名付けも
Route::get('articles', 'ArticlesController@index')->name('articles.index');
Route::get('articles/{id}', 'ArticlesController@show');
Route::post('articles', 'ArticlesController@store')->name('articles.store');
//コントローラ app/Http/Controllers/WelcomeController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class WelcomeController extends Controller{
public function index(){
return view('welcome');
}
public function contact(){
return view('contact');
}
}
class ArticlesController extends Controller {
public function create() {
return view('articles.create');
}
public function store(ArticleRequest $request) {
//コントローラはメソッドの引数にタイプヒントでクラスを記述するとインスタンスを自動生成して渡してくれます
//$inputs = \Request::all(); //フォームの入力値を取得
//dd($inputs); //デバッグ: $inputs の内容確認
Article::create($request->validated());//マスアサインメントで記事をDBに作成
return redirect()->route('articles.index')->with('message', '作成!'); //記事一覧へリダイレクト
}
}
//ビュー resouces/views/welcome.blade.php
resources/view/contact.blade.php
view('aaa')の場合、ビューはaaa.blade.phpが読まれる、なければaaa.php
blade では PHP で評価した結果を表示する場合、ダブルカーリー {{ }}
{{!! XXXX !!} はPHP評価をエスケープ処理を行わず表示(htmlタグがでる)、{{ XXXX }} のエスケープ(htmlタグがでない)
@csrfでCSRFトークン(hidden)を挿入
{{-- コメント文 --}}
ビューテンプレ
親ビューですべきこと
大まかレイアウトを記述し、各子ビュー固有のパーツをどこの@yieldで反映させたいかを指定
<html><body>
@yield('body')
</html>
子ビューですべきこと
@extendsで親ビュー継承、@sectionで自分固有のパーツを定義
@extends('common.layout')//resources/views/common/layout.blade.php dotはフォルダの事
@section('body')
<p>表示したい内容<p>
@endsection
@extends('layout')
<h1>About Me: {{ $first_name }} {{ $last_name }}</h1>
{{-- エラーの表示を追加 --}}
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
{!! Form::open() !!}
<div class="form-group">
{!! Form::label('title', 'Title:') !!}
{!! Form::text('title', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('body', 'Body:') !!}
{!! Form::textarea('body', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('published_at', 'Publish On:') !!}
{!! Form::input('date', 'published_at', $published_at, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::submit($submitButton, ['class' => 'btn btn-primary form-control']) !!}
</div>
大元のレイアウトビュー resouces/views/layout.blade.php
<!DOCTYPE HTML>
<html lang="ja">
<body>
@if (session('message'))
<div class="alert alert-success">{{ session('message') }}</div>
@endif
@yield('content')
</body>
</html>
変数を渡す場合
ビューファサードは第二引数へ配列でパラメータを渡す
Route::view('sample/view', 'sampleview', ['number' => 123456789]);
コントローラでは配列で渡す
public function create(Request $request, Response $response){
$items = DB::select('select * from fun_inquiry');
$param = ['items' => $items,
'msg' => 'データを追加するにはログインが必要です',
'request' => $request,
'response' => $response];
return view('index', $param);
他にはcompact関数又はwithメソッドで送信
public function test() {
$test_1 = "テスト1";
$test_2 = "テスト2";
return view('test.normal',compact('test_1','test_2'));
}
public function test() {
$test_1 = "テスト1";
$test_2 = "テスト2";
return view('test.normal')->with([
"test_1" => "テスト1",
"test_2" => "テスト2",
]);
}
フォーム
<input type="text" name="textbox" value="">
<input type="radio" name="radio-btn" value="選択1">
<input type="radio" name="radio-btn" value="選択2">
テキストボックスは{{$post_data['textbox']}}
ラジオボタンは{{$post_data['radio-btn']}}
処理系ディレクティブ
@isset($msg) {{$msg}} @else 今何してる? @endisset
@for($i=1;$i<10;$i++;) {{$i}} @endfor
@while($msg=='') 今何してる? @endwhile
@break @continueも
@foreach($db_data as $recode)
{{$recode->id}}
{{$recode->name}}
{{$recode->old}}
@endforeach
{{$db_data[0]->name}} 0番目
$count = $db_data->count(); カウント
$avg = $db_data->avg('old'); 平均
//モデル app/Article.php
DBとモデルオブジェクトを対応付ける機能を Eloquent という
Eloquent の機能を継承しビジネスロジックを加えたクラスがモデル
ORM(Object-relational mapping)でDBアクセスをする
$items = DbTblFunInquiry::all(); //モデルを作成しているのでコレでDBアクセス可
$items = DbTblFunInquiry::where(no, '>=', 3)->get();
Eloquentのリレーションには、1対n、1対1やn対n等が
$this->hasMany('App\Article');
$this->belongsTo('App\User');
//バリデーション
エラーが出て前のページに戻る
public function update(Request $request, Response $response){
$validate_rule = [
'title' => 'required|unique:posts|max:255',
'inquiry' => 'required'];
$this->validate($request, $validate_rule);
作り方、まずコントローラでは
$upfileRequest = new upfileRequest();
$rules = $upfileRequest->rules();
$errorMsg = $upfileRequest->messages();
$result = $this->validate($request, $rules, $errorMsg);
cmdでリクエストクラスを生成
$ php artisan make:request upfileRequest
下記のように
class upfileRequest extends Request{
public function rules(){
return [
'title' => 'required',
'address' => 'required',
'url' => 'url',
'img' => 'file|image|mimes:jpeg,jpg,png,gif|max:' . config('const.validate_limits.upload_image_size'),
'img_update_flag' => 'sometimes|accepted',
];
}
public function messages(){
return [
'title.required' => 'タイトルは必須です',
'address.required' => '住所は必須です',
'url.url' => 'このURLは不正です(http://またはhttps://から記述してください)',
'img.mimes' => '選択できる画像はJPEG・GIF・PNG形式のみです',
'img.max' => '1MB以下のファイルを選択してください',
'img_update_flag.accepted' => '1MB以下のファイルを選択してください',
];
}
}
//ミドルウェアでフィルタリングを実行
記事の作成や編集、削除はログインしていないと実行出来ないように制限する等
app/Http/Middleware/ にミドルウェアがある(vendor/laravel/framework 以下にも多数ある様)
├── CheckForMaintenanceMode.php
├── EncryptCookies.php
├── RedirectIfAuthenticated.php
├── TrimStrings.php
├── TrustProxies.php
└── VerifyCsrfToken.php
app/Html/Kernel.php の中でミドルウェアをシステムに登録
1)グローバルミドルウェア(全ての HTTP リクエストに適用)
2)ルートミドルウェア(Routeで使用)
3)グループ(Web等)で登録可
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
ミドルウェアの使用
routes/web.phpで定義したルートには全てwebミドルウェアが適用される
ルートミドルウェアを使う場合(Routeに配列で登録)
Route::get('admin/profile', function () {
//処理
})->middleware('auth', '2つ目', ...);
// ホーム(ログインしていないと見れないよう)
Route::group(['middleware' => 'auth'], function() {
Route::get('/home', function () {
return view('home');
});
});
コントローラで使う場合
ログインをしていなくてもindexとshowの表示が可能
class ArticlesController extends Controller{
public function __construct(){
$this->middleware('auth')
->except(['index', 'show']);
}
ビューでの使用
@auth
ログインしています
@endauth
Middleware の新規作成(基本的なものは元々ある)
php artisan make:middleware MyMiddleware
登録確認メールの確認が済んでいるかミドルウェアで
https://laravel10.wordpress.com/2015/05/05/laravel5
//ファサード
サービスコンテナで利用可能なクラスへのstaticインターフェースを提供
サービスコンテナからオブジェクトへのアクセスを提供するクラス
Hoge::ぶらぶら とシンプルにコードが書けるようになる
Route::get('/', 'WelcomeController@index'); はファサードがあり実際は下記
$this->app->make('router')->get('/', 'WelcomeController@index');
<?php namespace Illuminate\Support\Facades;
class Route extends Facade {
protected static function getFacadeAccessor() {
return 'router';
}
}
実際に作成↓
対象となるクラスの作成 class Payment {
サービスプロバイダの作成 php artisan make:provider PaymentServiceProvider
サービスコンテナに paymentキーでPaymentクラスをバインド
class PaymentServiceProvider extends ServiceProvider {
public function boot(){ }
public function register() {
$this->app->bind(
);
}
}
config/app.php に PaymentServiceProviderを追加
ファサードクラスを作成
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Payment extends Facade {
protected static function getFacadeAccessor() {
return 'payment';
}
}
config/app.php に Paymentファサードのエリアスを追加
'aliases' => [
'Payment' => App\Facades\Payment::class,
],
app/Http/route.php 内で Paymentファサードを使用
Route::get('pay/{money}', function($money){
return \Payment::pay($money);
})->where('money', '[0-9]+');
この場合はここへアクセス http://localhost:8000/pay/10000
'payemnt', 'App\Services\Payment'
//セッションはキーと値 https://qiita.com/reflet/items/5638ab18fd7cededed17
$requet->session()->put(key, value); 値を保存
$v = $request->session()->get(key); 値を取得
$request->session()->flush(); セッション破棄 session()->forget('key');個別
$request->session()->all(); 全取得
//クッキー
\Cookie::queue('testcookie', "aaa", 60); 書き込み60分
$test = \Cookie::get('testcookie');取得
setcookie('testcookie');削除
//httpヘッダー
以下を入れて見れる
Controllerで
use Illuminate/http/Request;
use Illuminate/http/Response;
public function create(Request $request, Response $response){
$param = ['msg' => 'データを追加します',
'request' => $request,
'response' => $response];
return view('create', $param);
Viewで
<?php
dump($msg);
dump($request);
dump($response);
?>
下記メソッドも
$request->url() クエリ変数がつかないURL
$request->fullUrl() クエリ変数つきフルURL
$request->path() ドメインがないパス部分
$response->status()
$response->content()
$response->setContent(値)
//認証
https://reffect.co.jp/laravel/laravel-authentication-understand
https://qiita.com/apricotcomic/items/d7407d4b12f41e2ff5ed
http://recipes.laravel.jp/recipe/64
https://takahashi-it.com/php/laravel54-auth-customize/
https://saba.omnioo.com/note/6246/laravel6-0-makeauthが無くなった/
基本ページと認証仕組みをcmdで入れ込む
(users/pw_resetsテーブル等はmigrationで作成しておく必要)
php artisan make:auth はv6から使えない様
vue省略型、React性能高
composer require laravel/ui
php artisan ui vue --auth
Nodeを入れて下記が必要のようだが(管理者権限が要るCMD)
cd C:\Program Files\nodejs
npm init --yes
npm install
npm run dev
下記ページができる
http://localhost:8000/login
http://localhost:8000/register
http://localhost:8000/password/reset
ルーティング関連(コントローラ)
C:\xampp\htdocs\prj_laravel\app\Http\Controllers\HomeController.php
C:\xampp\htdocs\prj_laravel\app\Http\Controllers\Auth
ルーティングAuth::routes();から下記へ
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Support\Facades\Auth.php
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Routing\Router.php
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Foundation\Auth
migration するとデータは消えるのか? php artisan migrate ではDropされない、migrate:flushだと消える
Auth自動生成ページ系の遷移設定
protected $redirectTo = RouteServiceProvider::HOME;
HOMEは定数(C:\xampp\htdocs\prj_laravel\app\Providers\RouteServiceProvider.php で
public const HOME = '/fun';に設定
コントローラ類に下記を追加することで制御が可能だがコントローラを分ける必要がありそう
public function __construct(){ $this->middleware('auth'); }
public function __construct(){ $this->middleware('guest'); }
public function __construct(){ $this->middleware('guest')->except('logout'); }
ビューでログイン判定可
<?php
$user = \Auth::user();
if ($user) {
echo 'ログイン中: ' . $user->name;
?>
| <a href={{ route('logout') }} onclick="event.preventDefault();document.getElementById('logout-form').submit();">ログアウト</a>
<form id='logout-form' action={{ route('logout')}} method="POST" style="display: none;">
@csrf
</form>
<?php
}else{
?>
<a href="/login">Login</a> |
<a href="/register">Register</a>
<?php
}
?>
ビューにこんな感じでも
@if(Auth::check())
{{ Auth::id() }}
@endif
@auth
<p>ログインユーザーに表示する。</p>
@guest
<p>ログインしていないユーザーに表示する。</p>
@endguest
編集機能ページ等はコントローラでログイン判定しMSG表示とページ変遷(ログインするとCreateとUpdate可)
public function edit(Request $request, Response $response)
{
$user = \Auth::user();
if ($user) {
$input = ['no' => $request->no];
$items = DB::select('select * from fun_inquiry where no = :no', $input);
$param = ['items' => $items,
'msg' => '#' . $request->no . 'を編集できます',
'request' => $request,
'response' => $response];
return view('edit', $param);
}else{
$input = ['no' => $request->no];
$items = DB::select('select * from fun_inquiry where no = :no', $input);
$param = ['items' => $items,
'msg' => '#' . $request->no . 'を編集するにはログインが必要です',
'request' => $request,
'response' => $response];
return view('show', $param);
}
}
コントローラでユーザ判定
use Illuminate\Support\Facades\Auth;
class モデル名Controller extends Controller
{
public function ブレード名(){
$auths = Auth::user(); // ログイン中のユーザー情報
$user_no = Auth::id(); // ユーザーIDのみ
if (Auth::check()) {
if($a==1){ Auth::logout(); }
ログアウト時の変遷
logoutメソッドの本体は、AuthenticatesUsers にあるのでHOMEへ変更
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Foundation\Auth
//return $this->loggedOut($request) ?: redirect('/');
use App\Providers\RouteServiceProvider;
return $this->loggedOut($request) ?: redirect(RouteServiceProvider::HOME . '?fr=logout');
https://takahashi-it.com/php/laravel-login-authenticated-override/
/vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php の
中に、ログイン処理のリダイレクト直前で実行される authenticated() メソッドが書かれているが空で
LoginController.php でオーバーライドする形で実装
use Illuminate\Foundation\Auth\AuthenticatesUsers;
protected function authenticated()
{
Session::put('session_start_time', date('H:i'));
}
Session にログイン時間を入れる
use Session;//これは場合によって不要なようである
Session::put('session_start_time', date('H:i'));
$session_start_time = Session::get('session_start_time');
@if (Session::has('session_start_time'))
{{ Session::get('session_start_time') }}
@endif
Authと連動しログアウトするとSessionがなくなる
//サービスプロバイダー ServiceProvider
処理や表示したいビューを登録しておける(初期処理用、カウンターのようにインクリできない)
クラスを作りboot()に付与して、例えばいつでもその処理とメッセージをビューに呼び出す
MVCでビューにビジネスロジックを書く必要がある矛盾を解消するもの?
クラス作成 C:\xampp\htdocs\prj_laravel\app\Http\Gadget\Lucky.php
namespace App\Http\Gadget;
class Lucky
{
public $count = 0;
public $rate = 0;
public function addupCounter(){
$this->count++;
}
public function getCounter(){
$this->count++;
return $this->count;
}
public function getLucky(){
$this->rate = rand(1, 100);
return $this->rate;
}
}
サービスプロバイダの作成 php artisan make:provider GadgetServiceProvider
app/Providers/AppServiceProvider.php に追記でもいい
config/app.php に GadgetServiceProviderを追加
GadgetServiceProviderのbootに追記
public function boot(){
\View::composer(
'index', function($view){
$LuckyInstance = new \App\Http\Gadget\Lucky;
$view->with('lucky', $LuckyInstance->getLucky());
});
index.bladeのビューに追記 {{ $lucky }}
//ユニットテスト(Laravel PHPunit)
リファレンス https://readouble.com/laravel/5.7/ja/http-tests.html#assert-see
https://qiita.com/rev84/items/12fbd16d210d6a86eff9
処理を全部書かないと駄目か https://qiita.com/shindex512/items/4f28f8e06ef2d10e8d2b
PHPUnitが入っていてTestsフォルダに
TestCaseクラスにあるメソッドはtestで始まる名前のメソッドと判断し実行する、testABC()とか
DB_DATABASEが使用されるのでDBに用意する、設定等
database/factoriesにダミーデータ作成ファクトリーがある、必要な形式のデータが作られるよう調整する
$factory->define(App\User::class, function (Faker\Generator $faker) {
static $password;
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
];
});
$factory->define(App\Person::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'mail' => $faker->safeEmail,
'age' => random_int(1,99),
];
});
テストクラス作成 php artisan make:test LuckyTest
use Tests\TestCase;
use App\Http\Gadget\Lucky;
class LuckyTest extends TestCase{
public function testLucky(){
$response = $this->get('/fun');
$response->assertStatus(200);
$lucky = new Lucky;
$lucky_num = $lucky->getCounter();
$response->assertGreaterThanOrEqual(1, $lucky_num);
$response->assertLessThanOrEqual(100, $lucky_num);
}
}
use DatabaseMigration; を入れておくとテスト前後で自動でロールバックするらしい
テスト実行cmd vendor\bin\phpunit
//ページネーション
コントローラ側: $items = DB::table('fun_inquiry')->Paginate(7);
ビュー側: {{ $items->links() }} 合計{{ $items->total() }}
CSS側:
ul.pagination { text-align: center; margin: 0; padding: 0; }
.pagination li { display: inline; margin: 0 2px; padding: 0; display: inline-block; background:#eeeeee; width: 25px; height: 25px; text-align: center; position: relative; }
.pagination li a:hover, .pagination li a.active{ color: #000; background: #ccf; }
下記ではオブジェクトではなく配列を返しておりエラー
$items = DB::select('select * from fun_inquiry')->simplePaginate(7);
下記のようにクエリビルダかエロクエントならばOKのよう
$users = DB::table('users')->paginate(15); //query builder example
$users = User::where('votes', '>', 100)->paginate(15); //eloquent example
$users = DB::table('users as u')->select(['u.email','u.name','u.created_at'])->whereRaw("u.id in (select max(ui.id) from users ui where ui.status = 0)")->orderBy("ui.id","desc")->paginate(3)
吐き出されるソース resources/views/pagination/default.blade.phpで修正可能
<nav>
<ul class="pagination">
<li class="page-item disabled" aria-disabled="true" aria-label="pagination.previous">
<span class="page-link" aria-hidden="true">‹</span>
</li>
<li class="page-item active" aria-current="page"><span class="page-link">1</span></li>
<li class="page-item"><a class="page-link" href="http://localhost:8000/fun?page=2">2</a></li>
<li class="page-item">
<a class="page-link" href="http://localhost:8000/fun?page=2" rel="next" aria-label="pagination.next">›</a>
</li>
</ul>
</nav>
===============
■その他の機能
オートローダー
require "vendor/autoload.php";
autoload設定はcomposer.json を修正
ロガー
Monolog\Logger
エラーログ
storage/logs/*.log
メール送信
Mail::raw()
Laravel 5.3 からは artisan make:mail でMailable の派生クラス
php artisan make:mail Hello
app/Mail/Hello.php が作成される、Viewで本文
Mail::to('reciver@example.com')->send(new Hello($name));
データベース管理(migrationファイルを作成→migration実行)
php artisan make:migration create_users_table --create=users
php artisan migrate
database/migrations/2014_10_12_000000_create_users_table.php ができる
php artisan migrate:rollback でロールバック
Bootstrap
靴紐のソースを npm でダウンロードしLaravel Mixで public に配置
デバッガー
composer require barryvdh/laravel-debugbar でインスコ
config/app.php のサービス・プロバイダーとファサードに以下の設定を追加
Barryvdh\Debugbar\ServiceProvider::class,
'Debugbar' => Barryvdh\Debugbar\Facade::class,
デバッグ
dd($articles->first()); // dump and die ダンプして停止
Log::debug("incoming: GET hello");
Log::info("incoming: GET hello");
Log::warning("incoming: GET hello");
debug,info,notice,warning,error,critical,alertの7つ、storage/logs/に出力
全件
$articles = Article::all();
作成日の降順に記事をソート
$articles = Article::orderBy('published_at', 'desc')->orderBy('created_at', 'desc')->get();
$articles = Article::latest('published_at')->latest('created_at')->get();
現在より以前
$articles = Article::latest('published_at')->latest('created_at')->where('published_at', '<=', Carbon::now())->get();
フラッシュメッセージ
composer require laracasts/flash
Named rootはURLでなくルーティングに別名をつける
return redirect()->route('articles.index')
CRUDはリソースコントローラで一気作成ができる
php artisan make:controller PostsController --resource
// routes/web.php
Route::resource('posts', 'PostsController')->only(['index', 'show']);
Route::resource('posts', 'PostsController')->expect(['create', 'store', 'update', 'destroy']);
IDEでファサードの補完を行う
composer require barryvdh/laravel-ide-helper
php artisan ide-helper:generate
ページネーションで1ページに表示するデータ数を指定
$articles = Article::latest('published_at')->paginate(15);
render() でページネーションリンクをビューに生成 {!! $articles->render() !!}
ダミーデータ生成
seeder/factory/fakerで
サービスコンテナ
インスタンス化を管理する
サービスコンテナへクラスをバインドすると(キー名とクラスの紐付け)、クラス間の依存性を管理しやすい
インターフェイスでバインドとタイプヒントで依存性注入
$this->app->bind('SenderInterface', 'MailSender');
singleton()でバインドすると何度コンテナが呼び出されても同じインスタンスが返されメモリ効率が良い
$this->app->singleton('sender_single', 'MailSender');
Route::get('send/{message?}', function(Messenger $messenger, $message = '合格') {
return $messenger->send($message);
});
シングルトン(Singleton)パターンは
あるクラスのインスタンスを一つだけにする
同じクラスを使って新しいオブジェクトを再度作成すると最初に作ったオブジェクトの参照になる
function Singleton () {
// すでにSingleton.instance が存在する場合にはSingleton.instance を返す
if(typeof Singleton.instance === 'object') {
return Singleton.instance;
}
サービスプロバイダー
config/app.php にリストアップされ起動時に読込
Composerを使ってパッケージをインストールしたもの
vendor/laravel/framework/src/illuminate/Auth\AuthServiceProvider等を見ると
register()に登録を実装、boot()でそのサービス固有の初期処理を自由に実装
作成は php artisan make:provider MessengerProvider
エリクサー
Elixirはnode.jsのgulpをラッピングした自動化ツール
SassをCSSに変換、複数のファイルを1ファイルに結合、ミニファイ(余計な空白や改行を削る)、ファイルの変更を監視してタスクを実行、リロード用にCSSやJavaScriptのファイル名にバージョンを付与
ファイルアップロード
https://reffect.co.jp/laravel/how_to_upload_file_in_laravel
https://team-lab.github.io/skillup/step2/07-upload.html
https://laraweb.net/tutorial/2707/
https://qiita.com/mashirou_yuguchi/items/14d3614173c114c30f02
php.iniで定義: upload_max_filesize post_max_size等
windowsはパーミッションの設定は不要、XamppのTMPはここ C:\xampp\tmp\
$request->file('upfile')->getRealPath();//C:\xampp\tmp\php103B.tmp
dump($request->file('upfile'));
vendor\symfony\http-foundation\Request.phpにまつわるもの
$request->file('file')->store($path);
$request->file('file')->storePublicly($path);
$request->file('file')->storePubliclyAs($path);
$request->file('file')->storeAs($path,$filename);
$pathにtestならstorage/app/testに保存される
vendor\laravel\framework\src\Illuminate\Http\Request.phpにまつわるもの
$request->file('file')->move($destinationPath);
echo $request->file('upfile')->getPathname() . '<br>'; //C:\xampp\tmp\php76B8.tmp
echo $request->file('upfile')->getClientOriginalName() . '<br>'; //kanoe.jpg
echo $request->file('upfile')->getClientMimeType() . '<br>'; //image/jpeg
echo $request->file('upfile')->guessClientExtension() . '<br>'; //jpeg
echo $request->file('upfile')->getClientSize() . '<br>'; //20367
echo $request->file('upfile')->getError() . '<br>'; //0
echo $request->file('upfile')->isValid() . '<br>'; //1
echo $request->file('upfile')->getMaxFilesize() . '<br>'; //41943040
echo $request->file('upfile')->getErrorMessage() . '<br>'; //The file "kanoe.jpg" was not uploaded due to an unknown error.
こういうのもあるが、、、
echo $request->file('upfile')->getRealPath() . '<br>'; //C:\xampp\tmp\php9EA6.tmp
echo $request->hasFile('upfile') . '<br>'; //1
echo $request->file('upfile')->path() . '<br>'; //C:\xampp\tmp\php9EA6.tmp
echo $request->file('upfile')->extension() . '<br>'; //jpeg
ビューでは
<form action="{{ url('upload') }}" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}
<input type="file" name="upfile">
<input type="submit">
</form>
@if ($errors->any())
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
@isset ($filename)
<div>
<img src="{{ asset('storage/' . $filename) }}">
</div>
@endisset
コントローラでは
public function upload(Request $request){
$this->validate($request, [
'file' => [
'required',
'file',
'image',
'mimes:jpeg,png',
]//1行だと上手くいかんかった
]);
if ($request->file('file')->isValid([])) {
$path = $request->file('file')->store('public');//適当な名前でstorage/app/publicに保存
return view('home')->with('filename', basename($path));
} else {
return redirect()
->back()
->withInput()
->withErrors();
}
}
名前をつけたいのであれば
$new_filename = 'up_' . $request->file('file')->getClientOriginalName();
$request->file('file')->storeAs('public', $new_filename);
storage/app/publicに保存されるからアクセスするにはpublic/storageからシンボリックリンクを張る
cmdのphp artisan storage:link
ストレージ
https://reffect.co.jp/laravel/laravel-storage-manipulation-master
config/filesystems.php に設定があり
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
storage/app/publicがpublic diskになっておりファイルが保存されるが
アクセスするにはpublic/storageからシンボリックリンクを張る必要がある
ララベルでは/publicに通常アクセスさせるから
php artisan storage:link
URLメソッド
https://blog.capilano-fw.com/?p=2537
echo url('/'); //url()の引数に空白もしくは/を指定するとトップページを取得
定数 const
https://qiita.com/clustfe/items/4fa169c6d5114a9b6f4e
https://hiroto-k.hatenablog.com/entry/2018/03/28/213000
config/*.phpにenv()の値を入れてconfig()から参照
config/const.phpを作り下記を入れCache更新で読まれる
<?php
return [
'validate_limits' => [
'MAX_UPLOAD_SIZE' => 4032,
],
];
呼び出しconfig('const.validate_limits.MAX_UPLOAD_SIZE')
■依存性の注入という概念を核とするフレームワーク
依存性の注入,Dependency Injection(DI),Inversion of Control(制御の反転)とも言われ(IoC)
DI コンテナでクラスの生成を1箇所に集約、保守性、柔軟性、テスト性が上がる
composerでカレントディレクトリにPimpleをインストール
composer require pimple/pimple:~3.0
Illiminate\Foundation\Application クラスが DI コンテナにあたります
<?php
require "vendor/autoload.php";
interface SenderInterface {
public function send($message);
}
class MailSender implements SenderInterface {
public function send($message) {
return "メールで送りました。";
}
}
class GMailSender implements SenderInterface {
public function send($message) {
return "GMailで送りました。";
}
}
class Messenger {
protected $sender;
public function __construct(SenderInterface $sender) {
$this->sender = $sender;
}
public function send($message) {
return $this->sender->send($message);
}
}
//Config(DIコンテナにバインドすると言う)
$container = new Pimple\Container();
$container['mail'] = function($container) {
// return new MailSender();
return new GMailSender();
};
// メールで送る
$messenger = new Messenger($container['mail']);
echo $messenger->send("合格通知") . "\n";
?>
■ジョブキュー(Job Busというのもあるらしい)
時間の掛かる処理を非同期で実行、下記の6種類くらい
sync: デフォルト設定で、実際には同期処理として動きます
database: データベースをジョブキューとして使います
beanstalkd: beanstalkd オープンソースのジョブキューです
sqs: Amazon Simple Queue Service 有料サービスです
データベースの場合
.env、config/queue.phpを編集
ジョブテーブルが必要
php artisan queue:table
php artisan queue:failed-table
php artisan migrate
ジョブの作成
php artisan make:job SendReminderEmail --queued
app/Jobs/SendReminderEmail.php にできるので処理
コンストラクタでこのコマンドに必要なデータを受け取る
handle() メソッドでこのコマンドがやることを実装
routes.phpでQueue::push()やコントローラを作成しdispatch()を使う
データベースの jobs テーブルを確認
select * from jobs;
キューの中のジョブを実行するには、キューリスナーを動かす必要がある
php artisan queue:listen
キューの最初のジョブだけ実行したい場合(リスナーならずっと動くから)
php artisan queue:work
■タスクスケジューラ(Cronの代わり)
app/Console/Commands/Kernel.phpに記載
$schedule->command('auth:clear-reminders')->daily();
$schedule->call('YourClass@someMethod')->hourly();
$schedule->exec('cp oldThing newThing')->weekly()->mondays()->at('13:00');
毎分のcronエントリー1つだけ必要
* * * * * php /path/to/artisan schedule:run 1>> /dev/null 2>&1
■イベントとリスナー
app/Providers/EventServiceProvider.phpに登録
class EventServiceProvider extends ServiceProvider {
protected $listen = [
'App\Events\UserWasRegistered' => [ //イベント
'App\Listeners\SendWelcomeMail', //リスナー
],
];
}
イベントとリスナーの生成
php artisan event:generate
event:generateは、a
Posted by funa : 12:00 AM | Web | Comment (0) | Trackback (0)
< January 2016 > | ||||||
Sun | Mon | Tue | Wed | Thi | Fri | Sat |
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |