人気のPHP WEBアプリケーションフレームワークLaravelのTipsを記録していきます

Laravelでフォームパラメーター($request)の自動トリムをoffにする

● フォームパラメーター($request)の自動トリムをoff

1. app/Http/Kernel.php** の ミドルウェアを削除する

app/Http/Kernel.php
「TrimStrings」( フォーム入力値の前後の空白を自動的にトリムする)
「ConvertEmptyStringsToNull」( フォーム入力値の空文字をnullに自動的に変換する)
を削除します。

    protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        // コメントアウト \App\Http\Middleware\TrimStrings::class,
        // コメントアウト \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
    ];
No.1464
03/19 13:36

edit

Laravel Mix を使用する

● Laravel Mix を使用する

1. Laravel アプリを作成する

composer create-project "laravel/laravel" my_app
cd my_app

2. package.json の確認

cat package.json

このような感じで自動生成されます

{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.18",
        "bootstrap": "^4.0.0",
        "cross-env": "^5.1",
        "jquery": "^3.2",
        "laravel-mix": "^4.0.7",
        "lodash": "^4.17.5",
        "popper.js": "^1.12",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.15.2",
        "sass-loader": "^7.1.0",
        "vue": "^2.5.17"
    }
}

3. nodeモジュールのインストール

npm install

4. ビルドする

テスト環境(ソースを圧縮せず)ビルドする

npm run dev

本番環境環境(ソースを圧縮して)ビルドする

npm run prod
No.1462
03/19 22:01

edit

Laravel で DB のバックアップを簡単にとる

● spatie/laravel-db-snapshots

composer コマンドでインストールします

composer require spatie/laravel-db-snapshots

● インストールの確認

インストールを確認します。

php artisan
 snapshot
  snapshot:create      Create a new snapshot.
  snapshot:delete      Delete a snapshot.
  snapshot:list        List all the snapshots.
  snapshot:load        Load up a snapshot.

● バックアップを取るディスクを設定する

config/filesystems.php

    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

        // ここから追加
        'snapshots' => [
            'driver' => 'local',
            'root' => database_path('snapshots'),
        ],
        // ここまで追加

(実際のディレクトリはバックアップを取るときに自動作成されます)

● バックアップを取る

テストで database/snapshots/my-first-dump.sql を作成します

php artisan snapshot:create my-first-dump

ファイル名を日付にしてもいいと思います。

php artisan snapshot:create 2019_03_12

なお 同名のファイルの場合は上書き されますので注意してください。

No.1459
03/12 15:40

edit

Laravel で back URL を持ち回る

● Laravel で back URL を持ち回る

管理画面の編集完了後にリダイレクトするページを複数にしたい時、 戻る URL を次のようにして 持ちまわると便利です。

● _back_url を(1画面だけ有効な)セッションに保存

use Illuminate\Support\Facades\Session;
Session::flash('_back_url', $request->fullUrl());

● _back_url を経過するコントローラーで(1画面だけ有効なセッションを)保持

use Illuminate\Support\Facades\Session;
if (Session::has('_back_url')) { Session::keep('_back_url'); }

● データをUPDATEするコントローラーでもセッションを保持しつつ、リダイレクト

セッションがある時とない時で処理を分けます。

use Illuminate\Support\Facades\Session;
if (Session::has('_back_url')) { Session::keep('_back_url'); }
if ( Session::get('_back_url') ){
    return redirect( Session::get('_back_url') )->with([ 'message' => 'success !' ]);
}
else {
    return redirect()->route("admin.data.index")->with([ 'message' => 'success !' ]);
}

● 全てのコントローラーに適用したい場合は

httpミドルウェアを使用しましょう。
https://readouble.com/laravel/5.8/ja/middleware.html

No.1455
03/08 12:02

edit

Laravel の バージョンをソースコード、コマンド、Bladeテンプレートから調べる

● Laravel の バージョンをソースコードから調べる

vendor/laravel/framework/src/Illuminate/Foundation/Application.php を調べます

	/**
	 * The Laravel framework version.
	 *
	 * @var string
	 */
	const VERSION = '5.0.31';

● Laravel の バージョンをコマンドから調べる

php artisan -V

● Laravel の バージョンを Blade テンプレートから調べる

{{ App::VERSION() }}
No.1454
03/07 18:22

edit

Blade
artisan

Laravel の ユーザー認証の ハッシュ方式を任意のものに変更する

● Laravel の ユーザー認証の ハッシュ方式を任意のものに変更する

例) として aes256(キー固定)に変更してみます。

● 1.CustomHasher.php の作成

app/Libs/CustomHash/CustomHasher.php を以下の内容で作成する

<?php
 namespace App\Libs\CustomHash;
 
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
 
class CustomHasher implements HasherContract {

    public function info($hashedValue)
    {
        return $this->driver()->info($hashedValue);
    }
 
    public function make($value, array $options = array()) {
        $key = env('CUSTOM_HASHER_AES256_KEY', false);
	    return openssl_encrypt($value,'aes-256-ecb',$key);
    }

    public function unmake($value, array $options = array()) {
	    $key = env('CUSTOM_HASHER_AES256_KEY', false);
	    return openssl_decrypt($value,'aes-256-ecb',$key);
    }
 
    public function check($value, $hashedValue, array $options = array()) {
        return $this->make($value) === $hashedValue;
    }
 
    public function needsRehash($hashedValue, array $options = array()) {
        return false;
    }
 
}

● 2. CustomHashServiceProvider.php の作成

app/Providers/CustomHashServiceProvider.php を以下の内容で作成する

<?php
namespace App\Providers;
 
use Illuminate\Hashing\HashServiceProvider;
use App\Libs\CustomHash\CustomHasher as CustomHasher;
 
class CustomHashServiceProvider extends HashServiceProvider
{
    public function register()
    {
        $this->app->singleton('hash', function () {
            return new CustomHasher;
        });
    }
}

● 3.config/app.php の変更

config/app.php の変更

    'providers' => [
		・・・・・
        App\Providers\CustomHashServiceProvider::class ,    // 追加
        // Illuminate\Hashing\HashServiceProvider::class,    // コメントアウト
		・・・・・

● 4. .env に追加

CUSTOM_HASHER_AES256_KEY=my_aes256key

● 5. bcrypt で記述しているシーダーがあれば修正

            'password'            => bcrypt('my-pass-word') ,

  ↓

            'password'            => \Illuminate\Support\Facades\Hash::make('my-pass-word') ,
No.1453
03/07 14:35

edit

bcrypt
Hasher
Hashing

Laravel の 多対多リレーション

● Laravel全リレーション

1対1
1対多
多対多
Has Many Through
1対1(ポリモーフィック)
1対多(ポリモーフィック)
多対多(ポリモーフィック)

これらのうち 多対多 リレーションを操作してみます。

● Laravel の 多対多リレーションのDB構造

とても簡単です。2つのテーブルをつなぐピボットテーブルを作成すればOKです。

・users
・practitioners

というテーブルを多対多でつなぐ時は
テーブル ↓

・user_practitioner

を作成します。( practitioner_user でも良い。 アルファベット順に並べると規則がはっきりして良いですね。)
中身は

テーブル「practitioner_user」の構造

id                  (primary key)
user_id             (integer,unsigned)
practitioners_id    (integer,unsigned)

とします。

● Laravel の 多対多リレーション(belongsToMany)をモデルに設定する

多対多リレーションある意味シンプルです。
これを両方のテーブルに(メソッド名は適宜変更して)定義します。
例)Userモデルに設定

    /**
     * 多対多 リレーション
     * ピボットテーブル「practitioner_user」
     *
     * @return \Illuminate\Database\Eloquent\Relations\belongsToMany
     */
    public function practitioners()
    {
        return $this->belongsToMany('App\Practitioner','practitioner_user');
    }

●多対多リレーションのIDリストを取得する

$model = User::findOrFail($id);
dump( $model->practitioners()->allRelatedIds() );   // (注意)Laravel 5.4以前は getRelatedIds() という名前でした

●多対多リレーションの項目名( カラム名 = practitioner_name )をカンマ区切りで取得する

ユーザ1 , ユーザ2 , ユーザ3 の様な文字列を取得します

$model = User::findOrFail($id);
dump( $model->practitioners()->implode('practitioner_name' , ' , ' ) );

●多対多リレーションのデータ更新(追加)

$model = User::findOrFail($id);
$model->practitioners()->attach([5,6,7]);    // ピボットテーブルに(すでにあるデータは消さずに)データを追加

●多対多リレーションのデータ更新(書き換え)

$model = User::findOrFail($id);
$model->practitioners()->sync([11,22,33]);    // ピボットテーブルを指定した配列のデータで更新(すでにあるデータを書き換え)
No.1452
03/06 12:29

edit

Laravel の 1対1リレーション

● Laravel全リレーション

1対1
1対多
多対多
Has Many Through
1対1(ポリモーフィック)
1対多(ポリモーフィック)
多対多(ポリモーフィック)

これらのうち 1対1 リレーションを操作してみます。

● Laravel の 1対1リレーション(belongsTo)

    /**
     * 1対1リレーション
     *
     */
    public function mt_branch()
    {
        return $this->belongsTo('App\MtBranch','branch_id')->withDefault();
    }

● Laravel の 1対1リレーション(hasOne)

    /**
     * 1対1リレーション
     *
     * @return \Illuminate\Database\Eloquent\Relations\hasOne
     */
    public function created_user()
    {
        return $this->hasOne('App\User', 'id', 'created_user_id')->withDefault();
    }
No.1450
03/06 11:08

edit

Laravel で fill を通さない DBデータINSERT

(管理画面で初期マスタデータをクライアントに登録してもらう時などに使用します)

● 通常の INSERT(その1)

$insert_data = [
    'name'    => '代入 太郎' ,
];
$practitioner = \App\Practicioner::create($insert_data);

● 通常の INSERT(その2)(その1と同じです)

$insert_data = [
    'name'    => '代入 太郎' ,
];
$practitioner = \App\Practicioner::fill($insert_data)->save();

● fill を通さない INSERT

$insert_data = [
    'id'      => 123456 ,
    'name'    => '代入 太郎' ,
];
$practitioner = \App\Practitioner::insert($insert_data);
No.1449
03/05 11:46

edit

Laravelで id またはメールアドレスでログインする

● Laravelで id またはメールアドレスでログインする

1. コントローラーを修正

(パラメータ名「email_or_id」を受けて、メールアドレスの場合はメールアドレスとして認証。それ以外の場合はidとして認証に行きます。)

app/Http/Controllers/Auth/LoginController.php に以下を追加します

    function username()
    {
        return 'email_or_id';
    }

    function attemptLogin(\Illuminate\Http\Request $request)
    {
        $email_or_id = $request->input($this->username());
        $password = $request->input('password');

        if (filter_var($email_or_id, \FILTER_VALIDATE_EMAIL)) {
            $credentials = ['email' => $email_or_id, 'password' => $password];
        } else {
            $credentials = ['id' => $email_or_id, 'password' => $password];
        }
        return $this->guard()->attempt($credentials, $request->filled('remember'));
    }

2. ビューを修正

パラメータ名を「email」 →「email_or_id」に変更します resources/views/auth/login.blade.php を以下のように変更します

<input id="email" type="email" class="form-control" name="email" value="{{ old('email') }}" autofocus>

<input id="email" type="text" class="form-control" name="email_or_id" value="{{ old('email_or_id') }}" autofocus>

以上で id またはメールアドレスでログインする事ができます

引用元 : https://goo.gl/Wodfh1

No.1448
02/22 09:21

edit

Laravel アプリで WordPress 自動整形機能(wpautop) を使用する

● wptrait

https://github.com/akat03/wptrait

● 準備 ( Model )

class Mymodel extends Model
{
    use WpTrait;
}

● 使い方 ( Blade テンプレート)

{!! $mymodel->wpautop($mymodel->contents)  !!}

● 使い方 ( Voyager BREAD )

カラム「text_name」にのみ適用します

@if ( $row->field == 'text_name' )
    @php
        echo $dataTypeContent->wpautop($dataTypeContent->text_name);
    @endphp
@else
   <p>{!! $dataTypeContent->{$row->field} !!}</p>
@endif
No.1445
02/15 11:47

edit

Laravel 「No application encryption key has been specified.」エラーの対処法

● Laravel 「No application encryption key has been specified.」エラー

.env.example からリネームして .env を作成した時に主に出現します。
「application encryption key」がないですよ、と言う事ですので作成しましょう。

php artisan key:generate
No.1441
02/12 10:38

edit

Laravel で lang ファイルを使って多言語化する

● 言語ファイル格納場所とファイル名

英語の場合は「resources/lang/en」ディレクトリ内に言語ファイルを格納します(元からあるはずです) 日本語の場合は「resources/lang/en」ディレクトリを作成します。

ファイル名の例(myapp)

resources/lang/ja/myapp.php

● 言語ファイルの書式

return [
    'list'        => '一覧',
    'edit'        => '編集',
    'delete'      => '削除',
    'print'       => '印刷',
];

● Bladeビューでの使い方

こちらの記法がオススメです

@lang('excrud.search')

こういう書き方もできます。

{{ __('messages.welcome') }}

● Bladeビュー @php ブロック内での使い方

@php
    $page_title = \Lang::get('myapp.edit');
@endphp
No.1439
02/09 14:51

edit

Laravel Voyager を使用する

● Voyager

オリジナルのCMSや管理画面を作りたい時に、面倒な色々の準備をやってくれるのが Voyager です。
必要最低限の機能がかなりのクォリティで用意されています。

https://github.com/the-control-group/voyager

● Voyager のインストラクションビデオ

( 必ず見るようにしましょう。 簡潔に説明してくれています。)

https://laravelvoyager.com/academy/configurations/

● Voyager のインストール

Laravel コマンドでアプリを作成した後に次のコマンドを入力します

・1. laravelコマンドでアプリを作成

composer create-project "laravel/laravel=5.7.*" my_app
cd my_app

・2. composer で Voyagerをインストール

composer require tcg/voyager

・2-B. インストールした Laravel , Voyager のバージョンを確認

composer show

リストの中の次のバージョンを確認する(何か問題が発生した時はバージョンを考慮して検索しましょう)

laravel/framework                     v5.7.28 
tcg/voyager                           v1.1.12

・3-A. .env に DB設定を書き込む

適宜変更します

https://YOUR-SERVER-NET
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

・3-B. Laravel の varcharのデフォルト文字数を191文字にして(191*4 = 764バイト) 767バイトより小さくする

app\Providers\AppServiceProvider.php

// ↓ この行を追加
use Illuminate\Support\Facades\Schema;

    public function boot()
    {
        // ↓ この行を追加
        Schema::defaultStringLength(191);
    }

・4. php artisan voyager コマンドからインストールする

php artisan voyager:install --with-dummy

(↑ このコマンドでDBデータも自動作成されます)

・5. Voyagerにアクセスします

https://<your-site>/admin

admin@admin.com
password

● nginx で Voyager を動作させる

Voyager 1.2 以降から

{{ voyager_asset('lib/css/responsive.dataTables.min.css') }}

の様な形で voyager_asset が追加されました。 「今まで public ディレクトリ以下にファイルをコピーしていた代わりに内部ファイルを返す」 といったものです。これが標準の nginx では動作しない可能性があります。

・nginx設定ファイルに以下を追加

location ~* .(js|css|jpg|png|gif|svg|woff|ttf)$ {
	try_files $uri $uri/ /index.php?$args;
}
nginx -s reload

これで読み込まれます。

 

● 管理画面の見た目のカスタマイズ

・1. 管理画面を日本語にローカライズする

右上のメニューから「Profile」 →「Edit My Profile」→「Locale を ja にセットする」

・2. 管理画面のローディングアイコンを変更する

「Settings」→「Admin」→「Admin Loader」に画像をアップロードする

・3. 管理画面のログイン画面のメイン画像を変更する

こちらの画像ファイルを変更します。

/public/vendor/tcg/voyager/assets/images/bg.jpg

デフォルトでは画像サイズ「1800ox * 1200px 」となっています。

・4. 管理画面のBREDのテンプレートビューを変更する

管理画面のBREDのテンプレートビューを変更するには次の位置に Bladeテンプレートファイルを作成します。

(詳細表示 : browse)を変更する場合

/resources/views/vendor/voyager/<テーブル名>/browse.blade.php

元の管理画面を参考に変更したい場合は次のファイルの内容をコピーします。

vendor/tcg/voyager/resources/views/bread/browse.blade.php

解説: https://laravelvoyager.com/academy/views/

・5. 管理画面のBREDのレイアウトテンプレートを変更する

vendor/tcg/voyager/resources/master.blade.php

 ↓ コピーする

resources/views/vendor/voyager/master.blade.php

・4. Voyager 管理画面のBREDのテンプレートビュー(Blade)内で権限により処理を変える

例: BREADのリスト表示で
「admin の role を持つ場合は表示させる」
「user の role の場合は Policy(別途作成が必要)により TCG\Voyager\Actions\EditAction が可能な場合は表示させる」
を Bladeテンプレートに記述します。

@if (Auth::user()->hasRole('admin'))
    <!-- admin -->
@else
    @php
        $edit_action = new TCG\Voyager\Actions\EditAction($dataType, $data);
    @endphp
    @can($edit_action->getPolicy(), $data)
        @php echo '<!-- user (edit可能です)-->'; @endphp
    @else
        @php echo '<!-- user (edit ×不可能です)-->'; @endphp
        @continue
    @endcan
@endif

・6. 管理画面のBREDのコントローラを変更する

管理画面のBREDのコントローラーを変更するには次の位置に コントローラーファイルを作成します。

例: (EstimateController)を変更する場合

app/Http/Controllers/EstimateController.php

app/Http/Controllers/EstimateController.php を次のようにします。( VoyagerBaseController を継承して中身が空のコントローラを作成 )

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use TCG\Voyager\Database\Schema\SchemaManager;
use TCG\Voyager\Events\BreadDataAdded;
use TCG\Voyager\Events\BreadDataDeleted;
use TCG\Voyager\Events\BreadDataUpdated;
use TCG\Voyager\Events\BreadImagesDeleted;
use TCG\Voyager\Facades\Voyager;
use TCG\Voyager\Http\Controllers\Traits\BreadRelationshipParser;

class  EstimateController extends \TCG\Voyager\Http\Controllers\VoyagerBaseController
{
}

 
元の管理画面を参考に変更したい場合は次のコントローラーファイルの内容をコピーします。

vendor/tcg/voyager/src/Http/Controllers/VoyagerBaseController.php

最後にVoyager の BREAD から 対象となるDBテーブルの「コントローラー名」に「\App\Http\Controllers\EstimateController」を指定します。 (必須です) これで作成したコントローラが使用されます。

● Voyager に 独自cssを追加する

1. /config/voyager.php の以下を変更します。

    'additional_css' => [
        'css/voyager_custom.css',
    ],

2. css を設置します

<My-APP>/public/css/voyager_custom.css

● Voyager チートシート

https://voyager-cheatsheet.ulties.com/

● Google Analytics API を使用する

https://goo.gl/JrtvkG

● 設定ファイル

/config/voyager-hooks.php
/config/voyager.php

● WordPressデータをインポートしたい

https://github.com/thedevdojo/wordpress-import

● 辞書ファイルの場所

辞書ファイル(日本語)はこちらにあります。

/vendor/tcg/voyager/publishable/lang/ja

● Voyager の ユーザーモデルを変更する

app/User.php

<?php
namespace App\Models;
use TCG\Voyager\Models\User as VoyagerUser;
class User extends VoyagerUser {
    // add custom mutators and other code in here
}

app/config/voyager.php

'user' => [
    'add_default_role_on_register' => true,
    'default_role'                 => 'user',
    'admin_permission'             => 'browse_admin',
    'namespace'                    => App\User::class,
],

● BREADの options を使用する

BREADのオプションに任意のパラメータを設定した場合は次のように $row->details から参照できます。

例)編集画面にコメントを表示させる
resources/views/vendor/voyager/<BREAD名>/edit-add.blade.php

{{-- コメント表示 --}}
@php 
if ( @$row->details->comment ){
    echo '<small>';
    echo $row->details->comment;
    echo '</small>';
}
@endphp
{{-- / コメント表示 --}}

なお、編集時に項目の見出しをつけるには

{
    "legend": {
        "text": "○○編集エリア"
    }
}

のように指定すると見出しが表示されます。

引用 : https://goo.gl/ydJEd6

● BREAD画面でリレーションにリンクをつける

https://github.com/the-control-group/voyager/issues/2008

● Select Dropdown を使った BREAD のリレーション設定方法

・1. 入力タイプを「Select Dropdown」を選択する

・2. オプション詳細を次のように記述する

{
    "relationship": {
        "key": "id",
        "label": "name"
    }
}
No.1438
03/19 21:26

edit

Laravel の モデルで リレーション先のカラムで親データをソートする

● Laravel の モデルで リレーション先のカラムで親データをソートする

少しややこしい表現になりますが、
リレーション先の複数のカラムをソートする のではなく、
リレーション先のカラムを使って親データをソート します

\App\Shirt::with('size')
    ->select(‘shirts.*', \DB::raw('(SELECT sort FROM sizes WHERE shirts.size_id = sizes.id limit 1 ) as sort'))
    ->orderBy('sort')
    ->get();  // または paginate( $limit ); とかですね。

注意

limit 1 をつけないと、複数行ある時に 「Subquery returns more than 1 row」エラーが返ります

● Laravelのサブクエリ用メソッド

Laravel 5.6.19 から は DB::raw を使用する代わりに joinSub()、leftJoinSub()、rightJoinSub()が追加されたようです。

DB::table('table')->joinSub('select * from "subtable"', 'sub', ...);
DB::table('table')->leftJoinSub(function ($q) { $q->from('subtable'); }, 'sub', ...);
DB::table('table')->rightJoinSub(DB::table('subtable')->where('foo', 'bar'), 'sub', ...);

引用元 : https://goo.gl/2UPi1E

No.1436
02/07 13:28

edit

Eloquent
DB

Laravel で ファイルをアップロードする

● Blade テンプレートに以下を記述してフォームタグを生成

{{ Form::file('myfile', ['class' => $class_name]) }}

( Form::text の場合は 2番目の引数に値をセットしますが、Form::file はセットしません。 )

● ファイル名を「お任せ」で保存する

コントローラーに以下を記述

$file_store_dir = 'img/';
$file_store_disk = 'local';  // local または public または s3
$file_name = $request->myfile->store($file_store_dir, $file_store_disk );

● ファイル名を指定して保存する

コントローラーに以下を記述

$ext = pathinfo($request->myfile->hashName(), PATHINFO_EXTENSION);	// ファイル名から拡張子を取得
$file_store_dir = 'img/';
$file_store_file_name = $id.".{$ext}"; // IDに拡張子をつけたものを保存ファイル名とする
$file_store_disk = 'local';  // local または public または s3
$file_name = $request->myfile->storeAs($file_store_dir, $file_store_file_name, $file_store_disk );  	// ディレクトリ, ファイル名, ディスク
No.1434
02/01 17:39

edit

Laravel の モデル で 生年月日から 和暦(昭和45年6月27日)を返すアクセサーを定義する

    /**
     * アクセサー : 「->patient_birth_date_wareki」 で 値「昭和45年6月27日」のフォーマットで誕生日を返す
     */
    public function getPatientBirthDateWarekiAttribute()
    {
        if ( $this->attributes['patient_birth_date'] != null ){
            $c = new \Carbon\Carbon($this->attributes['patient_birth_date']);
            setlocale(LC_TIME, 'ja_JP.utf8');
            $format = '%EC%Ey年%-m月%-d日';
            return $c->formatLocalized($format);
        } else {
            return 'ERROR: getPatientBirthDateWarekiNengoAttribute()';
        }
    }


    /**
     * アクセサー : 「->patient_birth_date_wareki_nengo」 で 値「昭和」を返す
     */
    public function getPatientBirthDateWarekiNengoAttribute()
    {
        if ( $this->attributes['patient_birth_date'] != null ){
            $c = new \Carbon\Carbon($this->attributes['patient_birth_date']);
            setlocale(LC_TIME, 'ja_JP.utf8');
            $format = '%EC';
            return $c->formatLocalized($format);
        } else {
            return 'ERROR: getPatientBirthDateWarekiNengoAttribute()';
        }
    }


    /**
     * アクセサー : 「->patient_birth_date_wareki_nengo」 で 年号以降の和暦の誕生日を返す
     */
    public function getPatientBirthDateWarekiNengappiAttribute()
    {
        if ( $this->attributes['patient_birth_date'] != null ){
            $c = new \Carbon\Carbon($this->attributes['patient_birth_date']);
            setlocale(LC_TIME, 'ja_JP.utf8');
            $format = '%Ey年%-m月%-d日';
            return $c->formatLocalized($format);
        } else {
            return 'ERROR: getPatientBirthDateWarekiNengoAttribute()';
        }
    }

・使い方

dump($model->patient_birth_date); // DB に入っている誕生日
dump($model->patient_birth_date_wareki);
dump($model->patient_birth_date_wareki_nengo);
dd($model->patient_birth_date_wareki_nengappi);

・結果

Carbon @1548926428 {#558 ▼
  date: 2019-01-31 18:20:28.0 Asia/Tokyo (+09:00)
}
"平成31年1月31日"
"平成"
"31年1月31日"
No.1433
01/31 18:22

edit

Laravelでリレーション先のデータを少なくとも1つ以上持つデータを取得する

https://readouble.com/laravel/5.7/ja/eloquent-relationships.html

// 最低1つのコメントを持つ全ポストの取得…
$posts = App\Post::has('comments')->get();
// 3つ以上のコメントを持つ全ポストの取得
$posts = App\Post::has('comments', '>=', 3)->get();
// 最低1つのコメントと、それに対する評価を持つポストの取得
$posts = App\Post::has('comments.votes')->get();
No.1431
01/30 17:36

edit

Laravelで日付、時刻オブジェクト Carbon を使用する

● UNIX Timestamp から Carbon オブジェクトを作成する

$carbon_obj = \Carbon\Carbon::createFromTimestamp( $v->getMTime() );

● LaravelのBlade内で直接 Carbon を呼び出して日付を表示させる

bladeテンプレートで Carbon を呼び出すには次のように記述します。

{{ \Carbon\Carbon::now() }}
{{ \Carbon\Carbon::now()->format("Y年m月d日") }}    // 2019年03月05日
{{ \Carbon\Carbon::now()->format("Y年n月j日") }}    // 2019年3月5日

format メソッドの引数は PHP の date と同じです。
http://php.net/manual/ja/function.date.php

● Carbonのリファレンス

https://carbon.nesbot.com/docs/

No.1429
03/18 23:02

edit

LaravelでDBのトランザクションを使用する

● LaravelでDBのトランザクションを使用する

これで、DB処理にエラーがあるときは ROLLBACK されます。

// ========== トランザクション ==========
DB::transaction(function () use ($params) {
    DB::table('users')->update($params);
    DB::table('posts')->delete();
});
// ========== / トランザクション ==========
No.1428
01/28 11:14

edit

Laravelのモデルで明示的にIDの値を指定して INSERT する

$insert_data = [
    'id'         => 1001 ,
    'user_name'  => 'テスト太郎' 
];

IDがガードされている場合、次のようにすると user_name のみ INSERTするSQL文が実行されます。

・ id に値をセットしないで INSERT

$model = new MyModel();
$model->fill($insert_data)->save();

 ↓ 明示的に ID にも値を入れて INSERT する場合はこのようにします。

・ id に値をセットして INSERT

$model = new MyModel();
$model->insert($insert_data);

ただし この方法では自動的に created_at にインサート時刻が入りません。 そこで明示的に現在時刻を渡してあげます。

$insert_data['created_at'] = new \Carbon\Carbon();
No.1427
02/01 14:45

edit

Eloquent
DB

Laravel の ディスク・ファイルシステム Storage を使用する

● ディスクの種類

local : ローカル(一般公開しないファイル)
public : ローカル(一般公開するファイル。コマンド aritizan storage:link を実行すると公開することができる。 )
s3 : Amazon S3
ftp :FTP (別途パッケージのインストールが必要)

など。

● ディスクの設定記述場所

config/filesystems.php

    'disks' => [
        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],
        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
        ],
        's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
        ],
    ],

● ディスク(Local )への移動の例

次のようなファイル移動を行うとします。

<アプリのトップディレクトリ>/storage/app/tmp/test.csv
 ↓
<アプリのトップディレクトリ>/storage/app/csv/123456789.csv

Laravel Storage を使って次の様に記述します。

$disk = \Storage::disk('local');
$disk->move("tmp/test.csv", "csv/12345679.csv" );

簡単ですね。 おすすめです。

● Laravel Storage を使ってファイルのパスを表示させる

dump( $disk->path(false) );    // パスのみの表示
dump( $disk->path("csv/test.csv") );    // ファイル名をフルパスで表示

 ↓ 表示例

/var/www/laravel/my_app/storage/app/
/var/www/laravel/my_app/storage/app/test.csv

● Laravel Disk を使ってローカルの pdf や画像を表示する

例えばコントローラに次のように記述するとローカルファイルのデータを表示できます。

        $pdf_file_path = 'pdf/125_01.pdf';
        $disk = \Storage::disk('local');
        $mimetype = $disk->mimeType($pdf_file_path);
        return response($disk->get($pdf_file_path))->header('Content-Type', $mimetype);

● Laravel Diskのメソッド

$contents = Storage::get('file.jpg');
$exists = Storage::disk('s3')->exists('file.jpg');

return Storage::download('file.jpg');
return Storage::download('file.jpg', $name, $headers);

// ファイル情報
$url = Storage::url('file.jpg');
$size = Storage::size('file.jpg');
$time = Storage::lastModified('file.jpg');

// ファイル操作
Storage::put('file.jpg', $contents);
Storage::copy('old/file.jpg', 'new/file.jpg');
Storage::move('old/file.jpg', 'new/file.jpg');

// 公開状態かどうか
Storage::setVisibility('file.jpg', 'public')

// ファイルの削除
Storage::delete('file.jpg');
Storage::delete(['file.jpg', 'file2.jpg']);
Storage::disk('s3')->delete('folder_path/file_name.jpg');

// ファイル/ディレクトリ一覧の取得
$files = Storage::files($directory);
$files = Storage::allFiles($directory);
$directories = Storage::directories($directory);
$directories = Storage::allDirectories($directory);

// ディレクトリ操作
Storage::makeDirectory($directory);
Storage::deleteDirectory($directory);
No.1426
02/15 15:14

edit

Laravel の ルーティングで Route::resource() で生成されるルート名の先頭に 文字列を加える

Route::group(['prefix' => 'admin', 'middleware' => 'admin', 'namespace' => 'Admin'], function () {
    Route::resource("consentforms","ConsentformController");
});

とするとルート名は

| GET|HEAD  | admin/consentforms/create              | consentforms.create  | 
| GET|HEAD  | admin/consentforms/{consentform}       | consentforms.show    | 
| PUT|PATCH | admin/consentforms/{consentform}       | consentforms.update  | 
  ... (以下続く)

と、なりますが
次の様に 'as' => 'admin.' を使うと 名前の先頭に admin. が追加されます

・'as' => 'admin. を追加

Route::group(['prefix' => 'admin', 'middleware' => 'admin', 'namespace' => 'Admin', 'as' => 'admin.'], function () {
    Route::resource("consentforms","ConsentformController");
});

 ↓ この様なルート名になります

| GET|HEAD  | admin/consentforms/create              | admin.consentforms.create  | 
| GET|HEAD  | admin/consentforms/{consentform}       | admin.consentforms.show    | 
| PUT|PATCH | admin/consentforms/{consentform}       | admin.consentforms.update  | 
  ... (以下続く)

No.1425
01/25 17:35

edit

ルーティング

Laravel の Blade でテンプレートファイルの格納ディレクトリを変更(追加する)

● Laravel の Blade でテンプレートファイルの格納ディレクトリを変更(追加する)

1. app/resources/pdf を追加し、 Pdf:: としてアクセスできるようにします

use View;
View::addNamespace('Pdf', base_path().'/resources/pdf' );

2. app/resources/pdf/my_template.blade.php を表示する

return View::make('Pdf::my_template');
No.1420
01/18 11:15

edit

Laravelで Bladeテンプレートのレンダリング結果を文字列として取得する

● Laravelで Bladeテンプレートのレンダリング結果を文字列として取得する

レンダリングするファイルが Views 以下にある場合はこちらでOKです。

$html = view('welcome', compact('user'))->render();
dd( $html );

Views 以外のディレクトリにあるテンプレートファイルをレンダリングして変数に代入するには

    /**
     * views 以外にあるbladeテンプレート( *.blade.php )を描画して変数とし受け取る
     *
     * @param   string      $template_full_path      テンプレートhtmlファイル名(フルパス)
     * @param   string      $compact                 compact() で受け取るテンプレートパラメーター
     *
     * @return  string      htmlテンプレート描画内容
     */
    private function getViewRender( string $template_full_path ,  array $compact )
    {
        $template_path     = pathinfo($template_full_path, PATHINFO_DIRNAME);
        $templatefile_name = pathinfo($template_full_path, PATHINFO_FILENAME);

        $app = app();
        $paths = [$template_path];
 
        // もとの設定を取得
        $originalFinder = \Illuminate\Support\Facades\View::getFinder();
         $finder = new \Illuminate\View\FileViewFinder($app['files'], $paths);
        \Illuminate\Support\Facades\View::setFinder($finder);
 
            $html = view($templatefile_name, $compact )->render();
            dd($html);

        // もとの設定に戻す
        \Illuminate\Support\Facades\View::setFinder($originalFinder);
 
        return $html;
    }

使い方

        $html = $this->getViewRender( $template_html, compact('param') );

引用: https://goo.gl/nTfMmR

No.1419
01/31 15:20

edit

artisan migrate コマンドを本番サーバで安易に実行しないようにする

● artisan migrate コマンドを本番サーバで安易に実行しないようにする

.env を 以下のように設定します。

APP_ENV=production

APP_ENV=production の設定がある時に、migrate コマンドを実行すると

$ artisan migrate:fresh --seed

次のような確認入力が表示されます。
これで本番環境で安易なマイグレーションの実行を抑止することができます。

**************************************
*     Application In Production!     *
**************************************
 Do you really wish to run this command? (yes/no) [no]:
No.1415
01/16 11:51

edit

artisan

Laravelでリレーション先のカラムを文字列で検索する

● Laravelでリレーション先のカラムを文字列で検索する

1対1のリレーションに有効です。
1対多のリレーションの場合は Slow Query になる可能性があるようです。必ず生成されるSQL文を確認しましょう。

● モデル

    /**
     * 1対1リレーション (従属の関係)
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user() // 単数形
    {
        return $this->belongsTo('App\User');
    }

● コントローラー

(モデルの中に記述してもいいです。お好みで。)

whereHasメソッド または orWhereHasメソッド を使用します。

// ● リレーション先のユーザー名「太郎」でも検索
$q = '太郎';
$model->orWhereHas('user', function ($query) use ($q) {	// リレーション名 user を渡す
    $query->where('name', 'LIKE', "%{$q}%");
});

● 実行されるSQL

WHERE
exists(select * from users
    where articles.user_id = users.id
    and name LIKE '%太郎%')

exists を使ってサブクエリを呼び出します。

● 1対多の場合は 最適化されないクエリで呼ばれるようです

EloquentのwhereHasメソッドは辛い - Qiita

No.1397
12/19 15:57

edit

Laravel で 全ての View でモデルのカウント数を表示する

全ての View で 何かの件数を表示したい時、ミドルウェアを作ったり、コントローラーを継承した親コントローラーに 共通処理を書いてもいいのですが、直接モデルオブジェクトを呼ぶという方法もあります。

● 全ての Bladeビューでモデルのカウント数を表示させる

Blade の ビューファイル から直接呼び出します。

自分の記事数 : {{ \App\MyArticle::count() }}
自分のユーザー数 : {{ \App\MyUser::count() }}

● 全ての Bladeビューから変数を読み込む

同様に static なメソッドを作成すれば、どこからでも呼ぶことができます。

app/Http/Controllers/MyController.php

	public static function getMyCount() {
		// ここに何かの処理
		$result = 99999;
		return $result;
	}

ビューからはこのように呼び出せます。

{{ \App\Http\Controllers\MyController::getMyCount() }}
No.1394
12/15 10:30

edit

モデル

Laravel で pdfテンプレートとhtmlを使ってpdfを出力する

● Laravel で pdfテンプレートとhtmlを使ってpdfを出力する

pdfを出力する時に、全てをhtmlで書いてもいいのですが、ロゴなどはpdfテンプレートで使い回すという方法も便利なので紹介します。

1. composer パッケージ「fpdi」「tcpdf」「html-compress 」のインストール

composer require setasign/fpdi
composer require tecnickcom/tcpdf
composer require wyrihaximus/html-compress 

2. pdfテンプレートとhtmlをディレクトリに保存

格納場所 resources/pdf を作成します。

mkdir resources/pdf

ここに pdf と html をコピーします。以下のファイル名とします。

template_01.pdf
template_01.pdf.html

3. 日本語フォントファイル「源真ゴシック」をこちらからダウンロードする

http://jikasei.me/font/genshin/

格納場所 resources/fonts を作成します。

mkdir resources/fonts

ここに 拡張子が .ttf のフォントファイルをコピーします。

4. pdfテンプレートとhtmlを読み込んで出力

Laravelのコントローラーからpdf 出力

use setasign\Fpdi;
use TCPDF_FONTS;
	public function tcpdf()
	{
        $pdf = new Fpdi\TcpdfFpdi();
		// $pdf = new \TCPDF("L", "mm", "A4", true, "UTF-8" );	// pdf テンプレートを使わない場合はこちら

		$pdf->setPrintHeader(false);
		$pdf->setPrintFooter(false);
		$pdf->AddPage();

		// テンプレートPDFファイル読み込み
		$pdf->setSourceFile(resource_path('pdf/template_01.pdf'));
		$page = $pdf->importPage(1);
		$pdf->useTemplate($page);

		// フォント
		$font = new TCPDF_FONTS();

		// フォント:源真ゴシック
		// $font_1 = $font->addTTFfont( resource_path('fonts/ipag.ttf') );
		$font_1 = $font->addTTFfont( resource_path('fonts/GenShinGothic-Medium.ttf') );
		$pdf->SetFont($font_1 , '', 10,'',true);

		// テンプレートhtmlファイル読み込み
		$html = \File::get( resource_path('pdf/template_01.pdf.html') );
		$pdf->writeHTML( $html, $ln=false, $fill=0, $reseth=false, $cell=false, $align="L" );

	 	$pdf->Output("output.pdf", "I");
	 }

5. tcpdf について調べるなら

このサイトがとても便利です

http://tcpdf.penlabo.net/

6. tcpdf の 改行や空白スペースがスペースとして認識されてずれる問題

htmlをminifyしましょう

composer require wyrihaximus/html-compress 
$parser = \WyriHaximus\HtmlCompress\Factory::construct();
$html = $parser->compress($html);

7. TCPDF で使用できるCSSプロパティ

以下のcssプロパティが使用できます。

font-family
font-size
font-weight
font-style
color
background-color
text-decoration
width
height
text-align

ではレイアウトはどうすれば良いのか? いにしえのテーブルレイアウトを使うのがいいでしょう。
例:

<html><body>
<table border="0">
	<tr>
		<td style="width:30px;"></td>
		<td style="width:350px; height:75px;"></td>
		<td></td>
	</tr>
	<tr>
		<td></td>
		<td></td>
		<td>平成31年1月25日</td>
	</tr>
</table>
</body></html>

● pdfフォームの例

https://tcpdf.org/examples/example_014/

No.1393
03/11 13:48

edit

Laravelの Blade でドロップダウンリスト(selectボックス)の任意の項目だけ選択不可能にする

● 1. Laravelの Blade でドロップダウンリスト(selectボックス)の全体を選択不可能にする

LaravelCollective の Form::select の 4番目の引数に配列を渡す事で実現できます。

{{ Form::select($name, $select_loop, $selected_value, ['class' => 'my_css_class', 'disabled' => 'disabled']) }}
{{ Form::select('size', ['L' => 'Large', 'S' => 'Small'], 'S', ['disabled' => 'disabled']) }}

引数4番目の配列に 'disabled' => 'disabled' を指定するだけでOKです。
これだけで、ドロップダウンリスト全体が disabled になります。

● 2. Laravelの Blade でドロップダウンリスト(selectボックス)の任意の項目だけ選択不可能にする

全体じゃなくて特定の <option>項目だけ選択できないようにしたいという時がたまにあります。 その場合は以下のようにフォームマクロを作成すると簡単にできます。

2-1. FormMacroServiceProvider の作成

次のコマンドを実行します

php artisan make:provider FormMacroServiceProvider

コマンドが実行されると app/Providers/FormMacroServiceProvider.php が自動生成されます。

2-2. FormMacroServiceProvider.phpにファイルを追記する

boot() メソッド内に以下を追加します

    public function boot()
    {
        // この行を追記する ↓
        require base_path() . '/resources/macros/selectbox.php';
    }

2-3. config/app.php の providers に登録する

  'providers' => [
        // この行を追記する ↓
        App\Providers\FormMacroServiceProvider::class,
  ]

2-4. macros ディレクトリを作成する

mkdir ./resources/macros

2-5. ファイル /resources/macros/selectbox.php を以下の内容で保存する

<?php
Form::macro('mySelectBox', function ($name, $list = [], $selected = null, array $selectAttributes = [], array $optionsAttributes = []) {
    $html = '<select name="' . $name . '"';
    foreach ($selectAttributes as $k => $v) {
        $html .= ' ' . $k . '="' . $v . '"';
    }
    $html .= ">\n";

    foreach ($list as $value => $text) {
        $html .= '<option value="' . $value . '"';
        if (strcmp($value, $selected) == 0) {
            $html .= ' selected="selected"';
        }
        if (isset($optionsAttributes[$value])) {
            $html .= ' ' . $optionsAttributes[$value];
        }
        $html .= '>' . $text . "</option>\n";
    }
    $html .= '</select>';
    return $html;
});

2-6. Bladeテンプレートに記述する

今まではこのように記述してドロップダウンリストを生成していたと思いますが次のように書き換えます

{{Form::select('size', ['L' => 'Large', 'M' => 'Medium', 'S' => 'Small'], 'S')}}

   ↓

{!! Form::mySelectBox('size', ['L' => 'Large', 'M' => 'Medium', 'S' => 'Small'], 'S', [], ['L' => 'disabled']) !!}

このようなドロップダウンリストが生成されます。 (Largeだけ選択出来ないようになりました)

添付ファイル1
No.1392
12/13 15:02

edit

添付ファイル

Laravel artisan の makeコマンド

● Laravel artisan の makeコマンド

コントローラーなどの各モジュールを作成するときにもちろん既存のファイルのコピペでもいいのですが、 artisan の make コマンドを使うと、エラーのない中身が空のひな形ファイルが作成されます。

● Laravel artisan でコントローラーを作成する(make:controller)

0. コントローラー作成コマンドのヘルプを表示

php artisan make:controller -h

例 : コントローラー「HomeController」を作成する

php artisan make:controller HomeController

成功すると app/Http/Controllers/HomeController.php が作成されます。

● その他のLaravel artisan の make系コマンド

以下、同様に次の make コマンドがあります。

 make:auth             Scaffold basic login and registration views and routes
  make:channel          Create a new channel class
  make:command          Create a new Artisan command
  make:controller       Create a new controller class
  make:event            Create a new event class
  make:exception        Create a new custom exception class
  make:factory          Create a new model factory
  make:job              Create a new job class
  make:listener         Create a new event listener class
  make:mail             Create a new email class
  make:middleware       Create a new middleware class
  make:migration        Create a new migration file
  make:model            Create a new Eloquent model class
  make:notification     Create a new notification class
  make:observer         Create a new observer class
  make:policy           Create a new policy class
  make:provider         Create a new service provider class
  make:request          Create a new form request class
  make:resource         Create a new resource
  make:rule             Create a new validation rule
  make:scaffold         Create a scaffold with bootstrap 3
  make:seeder           Create a new seeder class
  make:test             Create a new test class

● よく使う make系コマンド

種類 ヘルプ表示コマンド
コントローラー php artisan make:controller -h
モデル(DBデータ操作) php artisan make:model -h
マイグレーション(DBデータ構造) php artisan make:migration -h
シーダー(DBデータ作成) php artisan make:seeder -h
No.1387
12/05 10:11

edit

Laravelのモデル(Eloquent)の結果セット(Collection)に任意のカラムを追加する。またアクセサーで書式を変更する

● Laravelのモデルの結果セットに「任意のカラム」を追加する(自動)

モデルファイルに $appends プロパティをセットします

    // SELECTされるデータセットに次の独自カラムを追加する
    protected $appends = ['_editable_flag' , '_email_aisatsu' ];

● Laravelのモデルの結果セットに「任意のカラム」を追加する(手動)

Laravelのモデル(Eloquent)の結果セット(Collection)に手動で任意のカラムを追加するには map() を使用します。

// コレクションのすべてのデータにurl = http://your.url/here を追加
$collection->map(function ($v) {
    $v['url'] = 'http://your.url/here';
    return $v;
});
// コレクションそれぞれに count=xxx (任意の値) を追加
$collection->map(function ($v) {
    $v['count'] = <計算ロジック>;
    return $v;
});

● Laravelのモデルの結果セットに書式を変える「Accessor /Mutator」を追加する

少し書式を変えたいときは Accessor /Mutator を使いましょう

例1: is_starred=1 の時に ☆ を表示するアクセサ

モデルファイルに以下を記述

    /**
     * アクセサー : is_starred=1 の時に ☆ を表示する
     */
    public function getStarMarkAttribute()
    {
        if ($this->attributes['is_starred'] == 1){
            return '<div class="text-warning">★</div>';
        }
    }

呼び出し方

$model->star_mark

例2: 「dispatch_date」が存在する時にフォーマットして表示する。存在しない場合は未発送を返す アクセサ

    /**
     * アクセサー : 「->dispatch_date_ja」 で 値「dispatch_date」が存在する時にフォーマットして表示する。存在しない場合は未発送を返す。
     */
    public function getDispatchDateJaAttribute()
    {
        if ( $this->attributes['dispatch_date'] != null ){
            $c = new \Carbon\Carbon($this->attributes['dispatch_date']);
            return $c->format('m/d');
        } else {
            return '<span class="text-danger">未発送</span>';
        }
    }

呼び出し方

$model->dispatch_date_ja
No.1384
03/19 10:29

edit

モデル
Eloquent
DB

Laravel で Laravel Excel と LibreOfficeを使ってファイルを開いて pdf 出力する

● Laravel で Excel ファイルを開いてダウンロードする

Laravel-Excel ver 3 では まだ現時点では import が使えないようなので ver 2 を入れます。( 参考: https://goo.gl/wxHLE7

● Laravel Excelのインストール

composer で インストールします

composer require "maatwebsite/excel:~2.1.0"

● インストールされたモジュールのバージョン確認

インストールされたモジュールのうち excel 関連のバージョンを調べて置きます

composer show | grep excel
maatwebsite/excel                     2.1.30   Supercharged Excel exports in Laravel
phpoffice/phpexcel                    1.8.2    PHPExcel - OpenXML - Read, Create and Write Spreadsheet ...

Laravel Excel の 2.1.30phpexcel1.8.2 がインストールされています。
ググる時にはこれらのバージョンを参考にしましょう。

● Laravel Excel で テンプレートとなるエクセルファイルを読み込んで表示する

1. 元となるエクセルファイルを storage/excel/test.xls にアップロードする

( storage/excel/ )は存在しないので作成します。

2. routes/web.php に以下を追加する

Route::get('/test/excel', 'TestController@excel');

3. app/Http/Controllers/TestController.php を以下の内容で新規作成する

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;

class TestController extends Controller
{
	public function excel()
	{
		$excel_file = storage_path('excel/test.xls');
		Excel::load($excel_file, function($reader) {
			// 1番目のシートを選択
			$reader->sheet(0, function($sheet) {
				// セルA3に現在の日付を書き込み
				$sheet->cell('A3', function($cell) {
				    $cell->setValue( now()->format('Y/m/d') );
				});		    
			});		    
		})->export('xlsx');
	}
}

4. ブラウザでアクセスして エクセルファイルがダウンロードされることを確認する

https://YOUR-APP.COM/test/excel

にアクセスすると、エクセルファイルがダウンロードされます。
最初のシートの「A3」に今日の日付が書き込まれていることを確認します。
まずこれで Laravel Excel の 動作確認の完了です。

● エクセルファイルをpdfに変換する

PHPでするよりLibreOfficeを使用しましょう。再現性が上がります。(それでも80点ぐらいの再現度ですが。)

1. Libreofficeのインストール

yum -y install libreoffice libreoffice-langpack-ja

インストール後 バージョンを確認します。

libreoffice --version

もし libreoffice が見つからない場合は こちらから検索します。

find / -name soffice.bin

2. IPAフォントをインストール

wget https://ipafont.ipa.go.jp/old/ipafont/IPAfont00303.php -O IPAfont00303.zip
unzip IPAfont00303.zip
cd IPAfont00303
mv *.ttf /usr/share/fonts
cd ..
rm -rf IPAfont00303
rm -f IPAfont00303.zip

3. 源真ゴシックをインストール

mkdir genshingothic
cd genshingothic
wget https://osdn.jp/downloads/users/8/8637/genshingothic-20150607.zip genshingothic-20150607.zip
unzip genshingothic-20150607.zip
mv *.ttf /usr/share/fonts
cd ..
rm -rf genshingothic
rm genshingothic-20150607.zip

4. フォントがインストールされていることを確認

fc-list | grep IPA

5. libreoffice を使ってコンバート

コマンドラインから以下のコマンドを実行します。

libreoffice --headless --convert-to pdf --outdir /home/kusanagi/pdf test.xls

パスは絶対パスで指定しておくと確実です。

No.1383
12/02 22:46

edit

Laravel で モデル(データベース)のカラムを変更(追加)する

1. テーブル変更のパッケージを追加する

composer require doctrine/dbal

2. テーブル「articles」を変更するマイグレーションファイル「add_columns_articles_table」を生成する

add_columns_articles_table は任意の命名でOKですが「作業内容_テーブル名_table」としておくとテーブル作成時のファイルと命名が揃います

php artisan make:migration add_columns_articles_table  --table=articles

3. 生成されたファイル「2018_xx_xx_xxxxxx_add_columns_articles_table.php」にテーブル追加の命令を記述する

例:「articles」テーブルに以下のカラムを追加します

・「status_id」カラムの後ろにint型の「recruit_flg」を追加します
・「recruit_flg」カラムの後ろにint型の「recruit_date」を追加します
    public function up()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->integer('recruit_flg')->default(0)->after('status_id');    // この行を追加
            $table-> dateTime('recruit_date')->nullable()->after('recruit_flg');    // この行を追加
        });
    }

注意:SQLiteでは任意の位置にカラム追加が出来ないようです
回避策 : https://goo.gl/a2atCx

4. マイグレーションを戻す処理を down()メソッドに記述します

    public function down()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->dropColumn(['recruit_date','recruit_flg']);
        });
    }

5. カラム追加のマイグレーション実行

php artisan migrate

6. 実行したマイグレーションを戻す

php artisan migrate:rollback

以上で、データベースのデータを削除することなく、カラムを追加できます。

No.1381
11/28 21:09

edit

モデル
artisan

LaravelでCSVファイルをインポートする

● LaravelでCSVファイルをインポートする

ガリガリ書いてもいいですが、 fast-excelを使ってやるとさっとできます

https://github.com/rap2hpoutre/fast-excel

https://github.com/rap2hpoutre/fast-excel

fast-excelのインストール

composer require rap2hpoutre/fast-excel
use Rap2hpoutre\FastExcel\FastExcel;
$csv = (new FastExcel)->importSheets('data.csv');
dd($csv);

これだけで「data.csv」を読み込んで $csv にハッシュの配列形式で格納します。

● 日本語の文字コードが化ける問題への対応

文字コードは utf-8 以外の場合文字化けします。 csvファイルは sjis なことが多いので、事前に変換しておきましょう。

    //========================================== convertFileEncode
    protected function convertFileEncode($infname="", $incode='sjis-win', $outfname="", $outcode='UTF-8', $nl="\r\n") {
        if ( ! is_file($infname) ) {
            die("変換失敗:{$infname} が見つかりません.");
        }
        $tmp_filename = getmypid().'.tmp';
        $outfp = fopen($tmp_filename, 'wb');
        if ($outfp === FALSE) {
            die("変換失敗:{$tmp_filename} に書き込むことができません.");
        }
        $fp = fopen($infname,'r') or die("ファイル({$infname})のオープンに失敗しました");
        while ( ($line = fgets($fp,999999)) !== false ) {
            $outstr = mb_convert_encoding($line, $outcode, $incode);
            $outstr = preg_replace("/\r\n|\r|\n/", $nl, $outstr);
            fwrite($outfp, $outstr);
        }
        fclose($fp);
        fclose($outfp);
        rename($tmp_filename, $outfname);
        chmod($outfname, 0666);
        return true;
    }

エラー処理は適宜書き換えてください。(とりあえず die() していますが、例外を投げた方がいいでしょう。)

No.1379
11/27 18:23

edit

Laravelで try catch する

Laravel では以下のコードでは catch できません。

try {
    // 何かしらの処理
} catch (Exception $e) {
    dd($e);
}

 ↓ このように変更します

try {
    // 何かしらの処理
} catch (\Exception $e) {
    dd($e);
}

\Exception と表記します)

No.1373
11/22 22:05

edit

Laravelのモデルで複数のAND条件のクエリーを実行する

Laravelのモデルで複数のAND条件のクエリーを実行する

クロージャを使う方法がよく紹介されていますが、ローカルスコープを使うのもおすすめです
スコープを使うと SQL文で言う所の 「AND ( 何かしらのSQL文 )」 を発行することができます。

例えば次のような単純なSQL文もスコープにしてしまうと簡単です。

AND ( feed_id = 100 )

モデルファイル( 例:User モデルの場合 ) app/User.php

    /**
     * ローカルスコープ:inFeed:フィードIDに限定するスコープ
     */
    public function scopeInFeed($query, $feed_id)
    {
        return $query->where('feed_id','=', $feed_id);
    }

コントローラファイルに記述

$model->inFeed( 100 );	// ローカルスコープ適用
No.1370
11/17 18:35

edit

Laravelのモデルでリレーションに条件をつける

次のようにリレーションがあった場合

    /**
     * 1対1リレーション
     */
    public function mt_status()
    {
        return $this->belongsTo('App\MtStatus');
    }

 ↓ 次のようにして条件をつけることができます ( is_only_admin = 0 )

    /**
     * 1対1リレーション
     */
    public function mt_status()
    {
        return $this->belongsTo('App\MtStatus')->where('is_only_admin', '=', 0);
    }
No.1365
11/16 14:47

edit

Laravelのモデルで自分で設定した日付型カラムで format メソッドを使用する

Laravelで自分で作成した

Laravelのモデルで自分で設定した日付型カラムで

$touroku_date->format('Y/m/d')

のようなformat メソッドを使用すると
以下のようなエラーとなります

Call to a member function format() on string 

このエラーを出さないようにするにはモデルファイルに登録します

app/モデル.php

    // dates(formatメソッドを使用できるようにする)
    protected $dates = [
        'created_at',
        'updated_at',
        'touroku_date' // 追加する
    ];
No.1364
11/27 14:58

edit

Laravelで指定したIPのみアクセスできるように制限をかける

● Laravelで指定したIPのみアクセスできるように制限をかける

https://goo.gl/mzAAiv

こちらの方法がとてもよかったので引用させていただきます。
変更点としては アクセスを許可するIP を .env ファイルに記述しています(後から見返したときに見通しをよくするため)

1. ミドルウェア(IpLimit.php)を作成する

app/Http/Middleware/IpLimit.php

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Log;

/**
 * クライアントのリアルIPがホワイトリストに存在するかチェックするためのミドルウェア
 */
class IpLimit {

	/**
	 * Handle an incoming request.
	 * @param  \Illuminate\Http\Request  $request
	 * @param  \Closure  $next
	 * @return mixed
	 */
	public function handle($request, Closure $next) {
		$config = \Config::get('ip_limit');
		if ($config['enable'] !== true) {
			return $next($request);
		}
		if ($config['isProxy'] === true) {
			$request->setTrustedProxies([$request->ip()]);
		}
		if ($this->isAllow($request->ip(), $config['allowIps']) === false) {
			$error_message = 'cannot access from : ' . $request->ip();
			Log::debug( $error_message );
			abort( 404, $error_message );
		}
		return $next($request);
	}


	private function isAllow(string $remoteIp, array $accepts) {
		foreach ($accepts as $accept) {
			if ($this->isIn($remoteIp, $accept)) {
				return true;
			}
		}
		return false;
	}


	private function isIn(string $remoteIp, string $accept) {
		if (strpos($accept, '/') === false) {
			return ($remoteIp === $accept);
		}
		list($acceptIp, $mask) = explode('/', $accept);
		$acceptLong = ip2long($acceptIp) >> (32 - $mask);
		$remoteLong = ip2long($remoteIp) >> (32 - $mask);
		return ($acceptLong == $remoteLong);
	}

}

2. Kernel に登録する

app/Http/Kernel.php に以下を追加

    protected $routeMiddleware = [
        'iplimit' => \App\Http\Middleware\IpLimit::class,    // この行を追加する

3. 設定ファイルを作成する

config/ip_limit.php

<?php
return [
    'enable'   => env('IP_LIMIT_ENABLE', false),
    'isProxy'  => env('IP_LIMIT_PROXY',  false),
    'allowIps' => [
        env('LOCALHOST_IP', '127.0.0.1'),
	    env('IP_LIMIT_ENABLE_ADDRESS_01', false) ,
	    env('IP_LIMIT_ENABLE_ADDRESS_02', false) ,
	    env('IP_LIMIT_ENABLE_ADDRESS_03', false) ,
	    env('IP_LIMIT_ENABLE_ADDRESS_04', false) ,
	    env('IP_LIMIT_ENABLE_ADDRESS_05', false) ,
    ],
];

4. .env にアクセスを許可する IP を記述する

.env

IP_LIMIT_ENABLE=true		
# IP_LIMIT_PROXY: Laravelがバランサー配下に設置されている場合にtrueにすると、Real IPを取得する
IP_LIMIT_PROXY=false
IP_LIMIT_ENABLE_ADDRESS_01=xxx.xxx.xxx.xxx/24
IP_LIMIT_ENABLE_ADDRESS_02=yyy.yyy.yyy.yyy
IP_LIMIT_ENABLE_ADDRESS_03=
IP_LIMIT_ENABLE_ADDRESS_04=
IP_LIMIT_ENABLE_ADDRESS_05=

5. .ルーターにミドルウェアを追加する

routes/web.php

ミドルウェアをかませます

Route::get('/register', 'RegisterController@showRegistrationForm')->name('register');

 ↓

Route::group(['middleware' => 'iplimit'], function () {
    Route::get('/register', 'RegisterController@showRegistrationForm')->name('register');
});

以上です。

No.1362
12/19 14:16

edit

Laravelで独自のエラーページ(404 , 403 , 500)をカスタマイズして作成する

● Laravelで独自のエラーページ(404 , 403 , 500)をカスタマイズして作成する

Laravelの標準のエラーページをカスタマイズするには

/resources/views/errors/404.blade.php にファイルを置くだけです。

1. ディレクトリ errors を作成する

2. ファイルを作成する

ファイル名は

403.blade.php
404.blade.php
500.blade.php

とすると、404エラーの時は 「404.blade.php」を見に行きます。

● Laravelでエラーページ(404 , 403 , 500)に独自メッセージを表示させる

エラー発生時にエラーメッセージを追加する

abort( 404, '独自のエラーメッセージ' );

Bladeテンプレートでエラーメッセージを表示

{{ $exception->getMessage() }}

これだけで、エラーページにメッセージが表示されます。

● Laravelの独自のエラーページをデフォルトのエラーページと同じようなデザインにする

デフォルトのデザイン ↑ にしたい場合は次のようなコードにします

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Page Not Found</title>
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">
    <style>
    html,
    body {
        background-color: #fff;
        color: #636b6f;
        font-family: 'Nunito', sans-serif;
        font-weight: 100;
        height: 100vh;
        margin: 0;
    }

    .full-height {
        height: 100vh;
    }

    .flex-center {
        align-items: center;
        display: flex;
        justify-content: center;
    }

    .position-ref {
        position: relative;
    }

    .content {
        text-align: center;
    }

    .title {
        font-size: 36px;
        padding: 20px;
    }
    </style>
</head>

<body>
    <div class="flex-center position-ref full-height">
        <div class="content">
            <div class="title">
                Sorry, the page you are looking for could not be found.
            </div>
        </div>
    </div>
</body>
</html>

● エラーページにエラーメッセージを表示させてデバッグしやすくする

以下のようにすると .envAPP_DEBUG=1 の時だけエラーメッセージを表示させることができます。

            @if(env('APP_DEBUG') == 1)
                {{ $exception->getMessage() }}
            @endif

例:
Laravelエラーページにエラーメッセージを表示させる

添付ファイル1
添付ファイル2
No.1361
12/20 22:33

edit

添付ファイル

Laravel のデバッグを楽にする laravel-debugbar を使用する

Laravel のデバッグパッケージといえば laravel/telescope とlaravel-debugbar の2つが有名ですが、ここでは laravel-debugbar の使い方を紹介いたします。

● laravel-debugbarのインストール

composer require barryvdh/laravel-debugbar

● 使い方

.env の設定が以下になっていることを確認します。

APP_DEBUG=true

● laravel-debugbar の起動方法

Google Chrome で Laravelアプリを起動すると、

  1. 左下に Laravelの赤いアイコンが表示されていますのでそれをクリックします。
  2. 画面したの一番右から2番目のアイコンをクリックするとウィンドウ幅が上に大きくなって表示されます。

● (APP_DEBUG=true)にしたままlaravel-debugbarを無効にする

次のように設定すると laravel-debugbarのみ無効 にできます

APP_DEBUG=true
DEBUGBAR_ENABLED=false # laravel-debugbarを無効

● laravel-debugbar を一時的にオフにする

laravel-debugbar は 実行するSQL文が多いと重くなるので、ページごとに オンオフを切り替えたい時があります。
次のように オン/オフ します。

\Debugbar::enable();
\Debugbar::disable();
No.1360
02/28 10:52

edit

LaravelでFactoryとFakerとSeederを使ってダミーデータを作成する

● LaravelでFactoryとFakerとSeederを使ってダミーデータを作成する

PHPのFakerです。Faker Senpai ではないです。
Laravelだと標準でFakerがインストールされ、とても簡単に扱えるのでデータを作成する際には是非利用しましょう。
(Laravelアプリのインストール、モデルファイルはすでに用意してある前提で進めます。 )

Factoryを日本語で使用する

config/app.php の一番下に以下を追加

'faker_locale' => 'ja_JP',

先ずはダミーデータがどのようなデータになるか確認する

routes/web.php に以下を追加

Route::get('/faker', function () {
	$faker = Faker\Factory::create('ja_JP');
	$dummyData = [
		'name'                     => $faker->name,
		'password'                 => $faker->password,
		'country'                  => $faker->country,
		'prefecture'               => $faker->prefecture,
		'city'                     => $faker->city,
		'postcode'                 => $faker->postcode,
		'address'                  => $faker->address,
		'streetAddress'            => $faker->streetAddress,
		'phoneNumber'              => $faker->phoneNumber,
		'email'                    => $faker->email,
		'safeEmail'                => $faker->safeEmail, // (実在しないアドレスのため処理とかで使っても安心)
		'company'                  => $faker->company,
		'iso8601'                  => $faker->iso8601($max = 'now'),
		'dateTimeBetween'          => $faker->dateTimeBetween($startDate = '-110 years', $endDate = 'now')->format('Y年m月d日'),
		'numberBetween'            => $faker->numberBetween($min = 100, $max = 200),
		'title'                    => $faker->title,
		'realText'                 => $faker->realText($maxNbChars = 50, $indexSize = 2),
		'randomNumber'             => $faker->randomNumber($nbDigits = NULL),
		'randomFloat'              => $faker->randomFloat($nbMaxDecimals = NULL, $min = 0, $max = NULL),
		'randomElement'            => $faker->randomElement($array = ['男性', '女性']),
		'lexify'                   => $faker->lexify($string = '??????'),
		'hexcolor'                 => $faker->hexcolor,
		'ipv4'                     => $faker->ipv4,
		'url'                      => $faker->url,
		'imageUrl'                 => $faker->imageUrl($width = 640, $height = 480, $category = 'cats', $randomize = true, $word = null),
		'userAgent'                => $faker->userAgent,
		'creditCardType'           => $faker->creditCardType,
		'creditCardNumber'         => $faker->creditCardNumber,
		'creditCardExpirationDate' => $faker->creditCardExpirationDate,
		'isbn13'                   => $faker->isbn13,
		'isbn10'                   => $faker->isbn10,
	];
	dump($dummyData);
	exit();
});

http://YOUR-APP.TLD/faker にアクセスして表示させます。 次のようなダミーデータが表示されます。

array:31 [▼
  "name" => "浜田 舞"
  "password" => "sPz?uT[rr"
  "country" => "ドミニカ国"
  "prefecture" => "埼玉県"
  "city" => "廣川市"
  "postcode" => "9926575"
  "address" => "1202087  大阪府加藤市西区原田町廣川1-8-9"
  "streetAddress" => "若松町山岸5-1-2"
  "phoneNumber" => "05-4265-9978"
  "email" => "mitsuru67@gmail.com"
  "safeEmail" => "chiyo.kanou@example.net"
  "company" => "株式会社 喜嶋"
  "iso8601" => "1984-04-25T21:15:23+0000"
  "dateTimeBetween" => "1974年08月07日"
  "numberBetween" => 125
  "title" => "Dr."
  "realText" => "るしていただおじぎを捕とりと歴史れきしになって、と思ってすうりんどんどん流ながら上着うわぎのりを川。"
  "randomNumber" => 55
  "randomFloat" => 6539745.6
  "randomElement" => "男性"
  "lexify" => "znkbep"
  "hexcolor" => "#fb573b"
  "ipv4" => "136.204.203.254"
  "url" => "http://wakamatsu.jp/delectus-aspernatur-unde-quae-explicabo-aut-nisi"
  "imageUrl" => "https://lorempixel.com/640/480/cats/?97142"
  "userAgent" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2) AppleWebKit/5330 (KHTML, like Gecko) Chrome/37.0.841.0 Mobile Safari/5330"
  "creditCardType" => "Visa"
  "creditCardNumber" => "4485419150999"
  "creditCardExpirationDate" => DateTime @1634115758 {#207 ▼
    date: 2021-10-13 09:02:38.0 UTC (+00:00)
  }
  "isbn13" => "9793648060130"
  "isbn10" => "7424451421"
]

引用: https://goo.gl/VmSXqV

artisanコマンドから Factory を作成する

モデル「Client.php (DBテーブル名:client)」に対する「ClientFactory」を作成します。

php artisan make:factory ClientFactory

完了すると database/factories/ClientFactory.php が作成されています

デフォルトでは

$factory->define(Model::class, function (Faker $faker) {
    return [
        //
    ];
});

となっているのでここに設定を記述して行きます。

    return [
		'client_name'    =>  $faker->name ,
		'addr_name'      =>  $faker->address,
    ];

これでOKです。

Seederファイルを作成する

以下の内容で database/seeds/ClientsSeeder.php を作成する

<?php

use Illuminate\Database\Seeder;

class ClientsSeeder extends Seeder {

    public function run()
    {
    	// 10件作成
      factory(App\Client::class, 10)->create();
    }

}

シーダー実行ファイルに記述してあげます

database/seeds/DatabaseSeeder.php

    public function run()
    {
        $this->call(ClientsSeeder::class);
    }

artisanからシーダーを実行する

まずキャッシュを削除する

php artisan cache:clear; php artisan config:clear; php artisan route:clear; php artisan view:clear; composer dump-autoload

データを全て作り直し、シーダーを実行します

php artisan migrate:fresh --seed
No.1359
11/13 16:09

edit

LaravelのBladeテンプレートでルーターのプレフィックスを使う

● LaravelのBladeテンプレートでルーターのプレフィックスを使う

ルーターで

Route::group(['prefix' => 'admin'], function () {

のように、プレフィクスをつけている場合に Bladeでその値を取得する方法。

・Bladeでプレフィクスを取得する

    @php
        $prefix = Request::route()->getPrefix()
    @endphp

としておいてから

{{URL::to($prefix.'/articles/search')}}

このようにも書けます

{{ url("$prefix/articles/search") }}

http://YOUR-SITE.TLD/admin/articles/search

もちろん、わざわざこんなことをせずに素直に

{{ route('articles.search') }}

と書くのがいいです。

No.1357
11/10 11:04

edit

Laravelのメッセージを日本語化する

https://github.com/caouecs/Laravel-lang/tree/master/src/ja

1. 多言語リソースファイルをダウンロードする

https://github.com/caouecs/Laravel-lang

2. /resources/lang/に「ja」 ディレクトリをアップロードする。

3. config/app.php の設定を変更する

    'locale' => 'en',

  ↓

    'locale' => 'ja',

4. timezone も合わせて変更しておく

'timezone' => 'UTC',

 ↓

'timezone' => 'Asia/Tokyo',

以上です。

No.1356
03/12 15:22

edit

Laravelでエラーログをファイルに保存しつつメールで送信する

● Laravelでエラーログをファイルに保存しつつメールで送信する

ログにはレベルがあります。( PSR-3 ) PSR-3: Logger Interface: https://www.php-fig.org/psr/psr-3/

(危険な順)

8. EMERGENCY
7. ALERT
6. CRITICAL
5. ERROR
4. WARNING
3. NOTICE
2. INFO
1. DEBUG

このログレベルを利用して

・ログレベルが ERROR 以上の時はログに保存しつつメールで送信
・ログレベルが WARNING 以下の時はログに保存

という運用ができるように設定してみます。

コントローラーのコンストラクタに以下を記述

protected $monolog;
public function __construct()
{
    // umask。適宜書き換えてください。
    umask(0000);

	$this->monolog = Log::getLogger();	// laravel 5.6以降

	// 1. monolog - mail
	$transport = new \Swift_SendmailTransport('/usr/sbin/sendmail -t');
	$mailer    = new \Swift_Mailer($transport);
	$message   = new \Swift_Message('monolog ERROR');
	$message->setFrom('メールアドレス');
	$message->setTo('メールアドレス');
	$this->monolog->pushHandler(new \Monolog\Handler\SwiftMailerHandler($mailer, $message, \Monolog\Logger::ERROR, false));

	// 2. monolog - file - rotation
	$formatter = new \Monolog\Formatter\LineFormatter(null, null, true);
	$handler = new \Monolog\Handler\RotatingFileHandler(storage_path('logs').DIRECTORY_SEPARATOR.'error.log', 10, \Monolog\Logger::ERROR );
	$handler->setFormatter($formatter);
	$this->monolog->pushHandler($handler);
}

次のメソッドでログに記録します。

ログファイルに記録

$this->monolog->debug('1. debug');
$this->monolog->info('2. info');
$this->monolog->notice('3. notice');
$this->monolog->warning('4. warning');

ログファイルに記録 + メール送信

$this->monolog->error('5. error');
$this->monolog->critical('6. critical');
$this->monolog->alert('7. alert');
$this->monolog->emergency('8. emergency');
No.1355
11/14 23:31

edit

Laravelでログを出力する

● Laravelでログを出力する

cron実行時などは手動でログを出力して保存しておくと後からのデバッグが楽になります

use Log;
// $monolog = Log::getMonolog(); // Laravel 5.5以前
$monolog = Log::getLogger();	// laravel 5.6以降

ログの出力(下に行くほど深刻)

// DEBUG
$monolog->debug($message, $context);

// INFO
$monolog->info($message, $context);

// NOTICE
$monolog->notice($message, $context);

// WARNING
$monolog->warning($message, $context);

// ERROR
$monolog->error($message, $context);

// CRITICAL
$monolog->critical($message, $context);

// ALERT
$monolog->alert($message, $context);

// EMERGENCY
$monolog->emergency($message, $context);

● Laravelのログにファイル名やメソッド名を自動的に追加する

引用: https://goo.gl/NtbtSa

use Log;
$monolog = Log::getLogger();
$ip = new \Monolog\Processor\IntrospectionProcessor(
    \Monolog\Logger::DEBUG,
    [
        'Monolog\\',
        'Illuminate\\',
    ]
);
$monolog->pushProcessor($ip);

このようなログになります

[2018-11-09 01:52:35] local.WARNING: テーブルからデータを取得できません  {"file":"/home/app/Http/Controllers/TestController.php","line":231,"class":"App\\Http\\Controllers\\TestController","function":"postarticle"}

とても便利なので是非利用しましょう。

● ログの時刻がおかしい時の修正方法

config/app.php を以下のように変更します

    'timezone' => 'Asia/Tokyo',
No.1354
11/09 11:04

edit

Laravelの命名規約(または命名法則)

● Laravel命名規約

LaravelのコーディングスタイルはPSR-2に準拠。

PSR-2 スタイルの特徴

    PSR-1のコーディング規約には従わなければなりません。
    インデントには4つのスペースを利用しなければなりません。タブは使用してはいけません。
    1行の長さに制限はありませんが、120文字以下が望ましいです。できれば80文字以下にして下さい。
    クラス・メソッドの波括弧の前には改行を入れなければなりません。
    メソッドやプロパティの定義は最初にabstract/final、次にpublic/protected/private、最後にstaticを書かなければなりません。
    制御構文開始の波括弧の前には改行を入れません。
    制御構文の(の後、)の前にはスペースを入れません。

引用 : https://goo.gl/Fchriz

単数形複数形には注意する事。

http://www.infiniteloop.co.jp/docs/psr/psr-2-coding-style-guide.html

種類 単数 or 複数 ケース
モデル
(ファイル名)
単数形 パスカルケース(先頭大文字) Post.php
MsCountry.php
テーブル名 複数形 スネークケース(小文字) posts
ms_countries
コントローラ
(ファイル名)
どちらもOK パスカルケース(先頭大文字) PostController.php
MsCountryController.php
クラス どちらもOK パスカルケース(先頭大文字) PostController
MsCountryController
メソッド --- キャメルケース(先頭小文字) public function searchUser()
変数 --- スネークケース(小文字) $user_name

● Laravel DB命名規約

名前が決まっているカラム

カラム名 何を表すか?
id 主キー
created_at 登録日時
updated_at 更新日時
No.1353
12/05 11:56

edit

Laravelでフォーム送信時の先頭と最後のスペースや改行の自動削除を停止する

● Laravelでフォーム送信時の先頭と最後のスペースや改行の自動削除を停止する

Laravelではフォーム送信時に先頭と最後のスペース(改行も。)は自動削除されます。
これを停止するには Http/Kernel.php の 次の行をコメントアウトします。

protected $middleware = [
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    // \App\Http\Middleware\TrimStrings::class, // この行をコメントアウトする
No.1352
11/08 22:03

edit

Laravel + nginx をサブディレクトリで動作させる

● Laravel + nginx で動作しているアプリをサブディレクトリで動作させる

例: /my_app/ で Laravelアプリを動作させる

/etc/nginx/conf.d/YOUR-SITE.conf

	location /my_app/ {
		try_files $1 /my_app/index.php?$query_string;
	}

nginx -s reload で nginx をリスタートすればOKです。

my_app に シンボリックリンクを貼ってください。

● kusanagi を使用している場合

KUSANAGIを使っている場合は設定ファイルが2つに分かれている事があります YOUR-SITE_http.conf , YOUR-SITE_ssl.conf の2ファイルを編集しましょう

参考: https://goo.gl/fcmdT4

● うまくいかないときは Laravel 公式の 設定ファイルをチェックする

こちらに公式の設定ファイルがあるので、手元の設定ファイルと比較して揃えておきましょう https://laravel.com/docs/5.8/deployment#nginx

No.1349
03/15 18:22

edit

Laravelで admin / user のMulti-Auth を素早く作成する

管理者側テーブル「admin」を利用した認証とユーザー側テーブル「users」を利用した認証を作成する
「素早く」がテーマなので composer パッケージを利用します。
Laravel 5.6 でのやり方です。

「Laravelアプリの作成」「DB接続設定」は設定完了しているものとします。

● Hesto/multi-auth

https://github.com/Hesto/multi-auth

・パッケージのインストール

composer require hesto/multi-auth

・認証ファイルのインストール(小文字、単数形で命名します)

php artisan multi-auth:install admin -f
php artisan multi-auth:install user -f

・DBの作成

php artisan migrate

以上です。

・早速使う

管理者ログイン

http://YOUR-SITE.TLD/admin/login

ユーザーログイン

http://YOUR-SITE.TLD/user/login

・Bladeでの認証記述方法

Bladeテンプレートで adminまたはuserでログインしているかどうかを判別する

@if ( Auth::guard('admin')->check() )
<h1>adminとしてログイン済みです</h1>
@endif
@if ( Auth::guest() )
<h1>管理者ログイン前のguestです</h1>
@endif

・Bladeテンプレートでログイン後のユーザー名を表示する

{{ Auth::guard('user')->user()->name }}

・コントローラでログイン後のユーザー名を表示する

use Illuminate\Support\Facades\Auth;
{{ Auth::guard('user')->user()->name }}

● コントローラで認証チェックを使用する

app/Http/Kernel.php には以下のような記述が増えています

    protected $routeMiddleware = [
        'user' => \App\Http\Middleware\RedirectIfNotUser::class,
        'user.guest' => \App\Http\Middleware\RedirectIfUser::class,
        'admin' => \App\Http\Middleware\RedirectIfNotAdmin::class,
        'admin.guest' => \App\Http\Middleware\RedirectIfAdmin::class,
........

なのでこれを使用しましょう。

コントローラのコンストラクタに以下のように記述します

	function __construct(){
		// admin ログイン認証
		$this->middleware('admin');
	}

● ルーターで認証チェックを使用する

routes/web.php に次のように 'middleware' => 'admin' を追加します

// admin ログインが必要なページ
Route::group(['prefix' => 'admin', 'middleware' => 'admin'], function () {
            Route::get("articles/index", "ArticleController@index")->name("articles.index");
});

● 管理者、ユーザー毎にログアウトした時のリダイレクト先を設定する

ログアウトした時のリダイレクト先はコントローラーで設定します
管理者用、ユーザー用のAuthコントローラーは
/app/Http/Controllers/AdminAuth/LoginController.php
/app/Http/Controllers/UserAuth/LoginController.php
にあるので、ここに記述します。
vendor/hesto/multi-auth/src/Traits/LogsoutGuard.php のトレイトをオーバーライドします )

    // ログアウト後のリダイレクト先を「/admin/login」に設定する
        public function logoutToPath() {
        return '/admin/login';
    }

● /user/home , /admin/home など homeアクションの動作をカスタマイズする

デフォルトでは routes/user.php

Route::get('/home', function () {
    $users[] = Auth::user();
    $users[] = Auth::guard()->user();
    $users[] = Auth::guard('admin')->user();
    return view('admin.home');
})->name('home');

という風にクロージャで /user/home へのルーティングが記述されています。 これらをコメントアウトで消してしまってroutes/web.php に記述していくと見通しがいいと思います。

● パスワードリマインダーのメールテキストを変更する

パスワードリマインダーの文面は

app/Notifications/AdminResetPassword.php
app/Notifications/UserResetPassword.php

といった場所に作成されます。
これを変更しましょう。

    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->line('You are receiving this email because we received a password reset request for your account.')
            ->action('Reset Password', url('admin/password/reset', $this->token))
            ->line('If you did not request a password reset, no further action is required.');
    }

 ↓

    public function toMail($notifiable)
    {
        return (new MailMessage)
                ->subject('管理者メールのリセット')
                ->line('管理者パスワードリセットがリクエストされました')
                ->action('管理者パスワードをリセットする', url('admin/password/reset', $this->token))
                ->line('もし管理者パスワードリセットをリクエストしていない場合は、これ以上の操作は必要ありません。このメールを破棄してください。');
    }

このように一部日本語になります。

● パスワードリマインダーのメールデザインを変更する

こちらの方法でカスタマイズしましょう https://goo.gl/pkoo21

添付ファイル1
No.1348
01/23 17:19

edit

添付ファイル

LaravelのBladeで public のパスを表示する

● LaravelのBladeで public のパスを表示する

明示的に public ディレクトリを指定するときには asset('/') をおすすめします。

asset('/') はスラッシュ終わりの場合に最後にスラッシュがつきます。
url('/') はスラッシュ終わりの場合に最後にスラッシュがつきません。

{{ asset('/') }}
{{ url('/') }}

 ↓

https://YOUR-SERVER.TLD/
https://YOUR-SERVER.TLD

ファイル名まで指定する場合はどちらも同じです。

{{ asset('/assets/js/jquery-1.7.2.min.js') }}
{{ url('/assets/js/jquery-1.7.2.min.js') }}

 ↓

https://YOUR-SERVER.TLD/assets/js/jquery-1.7.2.min.js
https://YOUR-SERVER.TLD/assets/js/jquery-1.7.2.min.js
No.1347
12/17 11:29

edit

LaravelのValidatorで独自のチェックを行った後独自のエラーメッセージを表示させる

● LaravelのValidatorで独自のチェックを行った後独自のエラーメッセージを表示させる

Laravelでフォーム入力値のバリデーションを行った後、独自のチェックを行って、エラーが発生した場合 エラーメッセージと共に入力画面へ戻したい。といったことがあるかと思います。

次のようにして好きなメッセージでエラーメッセージを設定できます。

use Validator;
// 通常のバリデーション
$validator = Validator::make($request->all(), [
	'feed_url'  => 'required',
]);
$validator->validate();

// 追加で入力チェックを行う
if ( エラーがある場合 ) {
$validator->errors()->add('feed_url', 'このURLにはRSSフィードが含まれていません。');
return back()->withInput()->withErrors($validator);
}

エラーメッセージのセット方法は次のように記述してもOKです。

return back()->withInput()->withErrors(array('feed_url' => 'このURLにはRSSフィードが含まれていません。'));
No.1345
11/10 09:55

edit

LaravelでRSSフィードを読み込む

● awjudd/feed-reader

ざっと見たところ、「simplepie/simplepie」のLaravel5用ラッパーです。

● awjudd/feed-reader のインストール

composer require awjudd/feed-reader

config/app.php の編集

    'providers' => [
        .....
        Awjudd\FeedReader\FeedReaderServiceProvider::class, // この行を追加
    'aliases' => [
        .....
        'FeedReader' => Awjudd\FeedReader\Facade::class,, // この行を追加

● 設定ファイルの作成

php artisan vendor:publish

(  [1 ] Provider: Awjudd\FeedReader\FeedReaderServiceProvider )を選択します。

● Laravelコントローラーから使用する

use Awjudd\FeedReader\Facade as FeedReader;
$feed = FeedReader::read('https://RSS-FEED-SITE-URL');

if ( $feed->error() ) {
    echo $feed->error();
}

foreach ($feed->get_items() as $item) {
    $hash = [];
    $hash['site_title'] = $item->get_feed()->get_title();
    $hash['title'] = trim($item->get_title());
    $hash['permalink'] = trim($item->get_permalink());
    $hash['link'] = trim($item->get_link());
    $hash['date'] = $item->get_date('Y-m-d H:i:s');
    $hash['content'] = $item->get_content();
    dump($hash);
}

中身は「simplepie/simplepie」なので下記を参照してください。

https://github.com/simplepie/simplepie
https://goo.gl/ma6j9T

No.1344
11/08 17:43

edit

Laravelでsqliteを使用する / sqliteデータベースファイルを指定する

● Laravelでsqliteを使用する

Laravelでデータベース sqlite を使用します。データベースファイルは database/database.sqlite になります。

1. .env にsqlite設定を記述

mysqlの設定を # でコメントアウトして、sqlite設定を記述します。

# DB_CONNECTION=mysql
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=homestead
# DB_USERNAME=homestead
# DB_PASSWORD=secret

DB_CONNECTION=sqlite

2. 中身がからのデータベースファイルを作成する

touch database/database.sqlite

3. マイグレーション実行

php artisan migrate

以上です。簡単ですね。

● Laravelでデータベースファイルを指定して sqlite を使用する

.envフルパスでDBファイルを指定します。

例: /PATH/TO/YOUR/APP/database/production.sqliteを指定する

DB_DATABASE=/PATH/TO/YOUR/APP/database/production.sqlite 
No.1342
11/07 13:35

edit

Laravelで最速でソースコードを色づけしながらMarkdownを使用する

● Laravelで最速でソースコードを色づけしながらMarkdownを使用する「gitdown」

● gitdown

https://github.com/calebporzio/gitdown

1. gitdown のインストール

composer require calebporzio/gitdown

2. Bladeの記述を変更する

{{ $memo->text_name }}

 ↓

{!! GitDown::parseAndCache($memo->text_name) !!}

これだけでマークダウンでパースされます。

3. ソースコードに色づけする

@gitdown

以上です。最速。

● laravelで markdown をライトに使用する「laravel-markdown」

1. laravel-markdown のインストール

composer require andreasindal/laravel-markdown

2. Bladeの記述を変更する

{{ $memo->text_name }}

 ↓

@markdown($memo->text_name)

これだけでマークダウンでパースされます。

No.1341
03/12 16:59

edit

Laravelで指定したGETデータ(またはPOSTデータ)を取得する

● Laravelで指定したGETデータ(またはPOSTデータ)を取得する

Laravelで httpの全てのGETデータやPOSTデータは

$request->all();

で取得しますが、この時、取得したい項目を指定することができます。

「user_name」「email_name」を取得

$request->all(['user_name','email_name']);

なので、EloquentモデルでデータのUPDATEを行う時

$user->fill($request->all())->save();

 ↓

$user->fill( $request->all(['user_name','email_name']) )->save();

と書くことができます。 便利ですね。

No.1338
10/31 18:30

edit

LaravelのモデルにDBに存在しない独自のカラム(プロパティ)を追加する

● LaravelのモデルにDBに存在しない独自のカラム(プロパティ)を追加する

例としてあるモデル(User)に独自カラム「_editable_flag」を値「normal」で追加する。

app/User.php に以下の記述を追加する

    // 独自カラム
    // protected $appends = array('editable_flag');
    protected $appends = array('_editable_flag'); // このようにアンダースコア始まりのカラムも作成できます。(メソッド名は変更せずでOK)

    // 独自カラムのアクセサ
    public function getEditableFlagAttribute()
    {
        return 'normal';
    }

No.1337
10/31 13:35

edit

LaravelのBladeビューでテンプレートファイル名を表示させる

デバッグ時にどのBladeビューファイルが使用されているかを確認したい時があります。 そんな時は

● LaravelのBladeビューでテンプレートファイル名を変数に代入する( .env の APP_DEBUG=true の時のみ )

それぞれのテンプレートファイル名に配置

@if(env('APP_DEBUG') == 1)
    @php($template_filename = 'show.blade.php')
    @php($compiled_template_filename = __FILE__)
@endif

( show.blade.php はファイルごとに適宜書き換えてください。 )

● LaravelのBladeビューで変数を表示する( .env の APP_DEBUG=true の時のみ )

@if(env('APP_DEBUG') == 1)
<!-- {{$template_filename or '' }} -->
<!-- {{$compiled_template_filename or '' }} -->
@endif

レイアウトファイルに記述しておきます。

No.1336
10/31 09:30

edit

Laravelのログをローテーションさせる

● Laravelのログをローテーションさせる

Laravelのログはデフォルトでは1つのファイルに追記を繰り返していきます。
ローテーションさせましょう。

.envファイルのデフォルト値「stack」を「daily」に変更します。

.env

LOG_CHANNEL=stack

 ↓

LOG_CHANNEL=daily

これだけでローテーションできるようになります。

その他以下のような設定が可能です。

名前 説明
stack 「マルチチャンネル」チャンネルを作成するためのラッパー機能
single シングルファイル/パスベースのロガーチャンネル(StreamHandler
daily RotatingFileHandlerベースの毎日ファイルを切り替えるMonologドライバ
slack SlackWebhookHandlerベースのMonologドライバ
syslog SyslogHandlerベースのMonologドライバ
errorlog ErrorLogHandlerベースのMonologドライバ
monolog サポートしているMonologハンドラをどれでも使用できる、Monologファクトリドライバ
custom チャンネルを生成するため、指定したファクトリを呼び出すドライバ

monolog を選択して、深刻なエラーの場合はメールなり通知を送信するという運用が実用的かと思われます。

● cronを使っている場合に cron実行ユーザーの権限でログを作成されてしまうので permission denied エラーとなる場合の対処法

/config/logging.php に permission 項目を記述できます。 (Laravel version 5.6.10 以降)

        'daily' => [
            'driver' => 'daily',
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
            'days' => 7,
            'permission' => 0666,
        ],
No.1332
10/30 13:26

edit

LaravelのEloquentに追加したいパッケージ

● Laravelで権限(Role)を管理するパッケージ

● zizaco/entrust(★5919)

https://packagist.org/packages/zizaco/entrust
https://itsolutionstuff.com/post/laravel-52-user-acl-roles-and-permissions-with-middleware-using-entrust-from-scratch-tutorialexample.html

● laravel/socialite(★3507)

https://packagist.org/packages/laravel/socialite

● LaravelのEloquentでタグを管理するパッケージ

● rtconner/laravel-tagging(★679)

https://packagist.org/packages/rtconner/laravel-tagging

● cviebrock/eloquent-taggable(★266)

https://packagist.org/packages/cviebrock/eloquent-taggable

● rinvex/laravel-tags(★11)

https://packagist.org/packages/rinvex/laravel-tags

No.1326
10/27 15:27

edit

LaravelのBladeビューで現在のURLを取得する

● LaravelのBladeビューで現在のURLを取得する

・現在のURLを取得(GETパラメーター( ? 以降の文字列)も取得します。)

{{ request()->fullUrl() }}

例: http://test.server.tld/users/search?q=test

・現在のURLを取得(GETパラメーター( ? 以降の文字列)は取得しません)

{{ url()->current() }}

例: http://test.server.tld/users/search

・現在のURLを相対で取得(GETパラメーター( ? 以降の文字列)も取得します。)

{{ str_replace(url('/'),"",request()->fullUrl()) }}

例: /search?q=test

・リクエストURIの取得

{{ request()->path() }}

例: users/search

・リクエストのURIが指定されたパターンにマッチするか

        @if ( request()->is('*users*') )
            マッチします<br>
        @endif

・完全なURLを取得(クエリ文字列なし)

{{ request()->url() }}

例: http://test.server.tld/users/search

・リクエストメソッドの取得

{{ request()->method() }}

GET

・リクエストメソッドが指定したものにマッチするか

        @if( request()->isMethod('get') )
            getメソッドです<br>
        @endif

引用: https://goo.gl/tojhBs

No.1325
11/26 21:59

edit

LaravelのBladeテンプレートでcsrfトークン、PUT/PATCH/DELETE メソッドを埋め込む。

● LaravelのBladeテンプレートで擬似的なPUT/PATCH/DELETE メソッドを埋め込む

例: PUT メソッドを埋め込みます

@method('PUT')

● LaravelのBladeテンプレートでcsrfトークンを埋め込む

@csrf

● LaravelのBladeテンプレートでcsrfトークンを手動で埋め込む。

<input type="hidden" name="_token" value="{{ csrf_token() }}"
No.1324
03/19 11:19

edit

LaravelのBladeテンプレートで変数の存在確認を行う

● LaravelのBladeテンプレートで変数の存在確認を行う

LaravelのBladeテンプレートで未定義の変数を使用するとエラーとなります。 事前に isset で 確認しましょう。

@if (isset( $text ))
<p>$test</p>
@endif

変数が未定義の場合に null をセットする

@if ( ! isset($v->flag) )
<?php $v->flag = null; ?>
@endif

または @ をつけて未定義エラーを回避します

@if ( $q['data_id'] )

 ↓

@if ( @$q['data_id'] )

● LaravelのBladeテンプレートで変数が存在しない場合に null (または空文字)を表示させる

変数が存在しない場合に null (または空文字)表示でいいのなら

{{$hoge or null}}
{{$hoge or ''}}

でもOKです。こちらの方が簡単ですね。

No.1323
11/16 16:47

edit

LaravelのコントローラーでHTTPのGETパラメーターを受け取る

LaravelのコントローラーでHTTPのGETパラメーターを受け取る

1. use Illuminate\Http\Request; の追加

use Illuminate\Http\Request;

2. 使用したいメソッドで $request を受け取る

	public function show($id)
	{

 ↓ Request型の $request をコントローラーのメソッドで受け取るようにします。

	public function show(Request $request, $id)
	{

3. 使う

URL https://YOUR-SERVER.TLD/test/action?file=001 でアクセスする時

echo $request->input('file') ;

次のように出力されます

001
No.1322
12/13 10:36

edit

Laravelのbladeテンプレート内で vue.js を使用する

Laravelのbladeテンプレート、vue.jsのテンプレート、どちらも {{ }} で変数を囲う記法なので、混在するとLaravelでエラーとなります。 そこで対応方法が2つあるようです。

● {{ の 前に @ をつける

    <div>
        {{ message }}
    </div>

 ↓

    <div>
        @{{ message }}
    </div>

● vue.js側のデリミタ {{ }} を (% %) に変更する

こちらの方法がオススメです。

Vue.config.delimiters = ['(%', '%)']; でデリミタを変更して使用します。

var vm = new Vue({
    el: '#myApp',
    data: {
    }
});

  ↓

var vm = new Vue({
    delimiters: ["(%","%)"] ,
    el: '#myApp',
    data: {
    }
});

引用: https://goo.gl/Y7QqBz

No.1321
10/29 09:45

edit

LaravelのBladeテンプレートで現在のアクション(URL, メソッド名)を取得する

● LaravelのBladeテンプレート内現在のコントローラーを取得する

<?php $current_controller_name = explode('.', Route::currentRouteName())[0]; ?>
現在のコントローラー名は {{ $current_controller_name }}

引用: https://goo.gl/9WmwRR

● LaravelのBladeテンプレート内で現在のルーティングを取得する

記法 戻り値(例)
{{ Route::currentRouteName() }} projects.edit

● LaravelのBladeテンプレート内でURLを取得する

記法 戻り値(例)
{{ Request::url() }} https://MY-SERVER.TLD/projects/3/edit
{{ Request::url("/") }} https://MY-SERVER.TLD/projects/3/edit
{{ Request::root() }} https://MY-SERVER.TLD
{{ Request::fullUrl() }} https://MY-SERVER.TLD/projects/3/edit
{{ Request::path() }} projects/3/edit
{{ Request::decodedPath() }} projects/3/edit

( urlエンコードする場合は)
urlencode(request()->fullUrl()) と記述します。

● LaravelのBladeテンプレート内でパスを取得する

記法 戻り値(例)
{{ url("") }} https://MY-SERVER.TLD
{{ url('/') }} https://MY-SERVER.TLD
{{ app_path() }} /var/www/vhosts/MY-SERVER.TLD/laravel/my_app/app
{{ base_path() }} /var/www/vhosts/MY-SERVER.TLD/laravel/my_app
{{ config_path() }} /var/www/vhosts/MY-SERVER.TLD/laravel/my_app/config
{{ database_path() }} /var/www/vhosts/MY-SERVER.TLD/laravel/my_app/database
{{ storage_path() }} /var/www/vhosts/MY-SERVER.TLD/laravel/my_app/storage
{{ resource_path() }} /var/www/vhosts/MY-SERVER.TLD/laravel/my_app/resources
No.1318
11/08 21:55

edit

LaravelのBladeでドロップダウンリストを簡単に作成する

laravelcollective/html を使用してドロップダウンリスト( select, option リスト) を簡単に作成します。

● laravelcollective/html のインストール

https://laravelcollective.com/docs/master/html

composer require "laravelcollective/html":"^5.4.0"

● ドロップダウンリストの配列を取得する

モデルから一覧を取得してきて、それを (key/value)方式に変換します。
コントローラーの好きなところに以下を記述します。

$clients = Client::select('id', 'client_name')->get();

// key,value ペアに直す
$client_id_loop = $clients->pluck('client_name','id');

● LaraelのBladeテンプレートにデータを渡す

return view('projects.create', compact('client_id_loop') );

● Bladeテンプレート内で Form::select を呼び出す

フォーム名「FORM_NAME」  CSSクラス名「my_class」 なドロップダウンリストを生成します。

{{ Form::select('FORM_NAME', $client_id_loop, null, ['class' => 'my_class']) }}

次のようなドロップダウンリストが生成されます

<select class="my_class" name="FORM_NAME">
    <option value="1">テスト1</option>
    <option value="2">テスト2</option>
    <option value="3">テスト3</option>
</select>

● ↑ こんなめんどくさいことをせずに Bladeのビューに1行で記述する

一撃で記述したい場合はこのように記述します。
bladeテンプレート内に記述
3つ目の引数に値を渡すと選択済みになります。null を渡すと最初の項目が選択済みになります

{{ Form::select('FORM_NAME', \App\Client::select('id', 'client_name')->get()->pluck('client_name','id'), null, ['class' => 'form-control']) }}

● 値をを選択済み(selected)のドロップダウンリストを生成する

3つめの引数に値をセットすると selected になります

{{ Form::select('FORM_NAME', $client_id_loop, 2, ['class' => 'my_class']) }}

 ↓ 次のようなドロップダウンリストが生成されます

<select class="my_class" name="FORM_NAME">
    <option value="1">テスト1</option>
    <option value="2" selected="selected">テスト2</option>
    <option value="3">テスト3</option>
</select>

●ドロップダウンリストに「選択してください」項目を追加する

key が null の値を登録します。

{{ Form::select('FORM_NAME',  [null=>'選択してください']+$client_id_loop, 2, ['class' => 'my_class']) }}

 ↓ 次のようなドロップダウンリストが生成されます

<select class="my_class" name="FORM_NAME">
    <option value="">選択してください</option>
    <option value="1">テスト1</option>
    <option value="2" selected="selected">テスト2</option>
    <option value="3">テスト3</option>
</select>

disabled な値を追加するにはこちら
https://goo.gl/cBJVaM

No.1317
03/05 14:04

edit

Laravelで1対1のリレーションを複数回取得する

Laravelでテーブルが2つ「clients」「users」あって、「clients」テーブル内に登録者IDと更新者IDが格納されている場合に 更新者の名前を取得する方法。

● モデルに1対1 リレーションを設定

app/Client.php

DBカラムの

「clients.created_user_id」と「users.id」と同じデータがあれば取得します。
「clients.updated_user_id」と「users.id」と同じデータがあれば取得します。
    /**
     * 1対1リレーション
     *
     * @return \Illuminate\Database\Eloquent\Relations\hasOne
     */
    public function created_user()
    {
        return $this->hasOne('App\User', 'id', 'created_user_id')->withDefault();
    }


    /**
     * 1対1リレーション
     *
     * @return \Illuminate\Database\Eloquent\Relations\hasOne
     */
    public function updated_user()
    {
        return $this->hasOne('App\User', 'id', 'updated_user_id')->withDefault();
    }

->withDefault() がミソですね。存在しないときに中身が空のオブジェクトを返します。

● with メソッドの引数を複数指定する

$clients = Client::with('created_user','updated_user')->get();

● コントローラーから取得する時に with メソッドを2回投げる。

app/Http/Controllers/ClientController.php

	public function index( Request $request )
	{
		$clients = Client::with('created_user')
							->with('updated_user')
							->orderBy('id', 'desc')->paginate( 10 );
    }

引用: https://goo.gl/6h6LEC

No.1316
03/05 16:37

edit

LaravelのCRUD操作のメソッドとルーティング一覧

LaravelのCRUD操作のメソッドとルーティング一覧

例 : teams モデルの場合

HTTPメソッド URL例 ルーティング名 メソッド名
データの一覧表示
GET,HEAD teams teams.index App\Http\Controllers\TeamController@index
データの詳細表示
GET,HEAD teams/123456 teams.show App\Http\Controllers\TeamController@show
データの新規作成
GET,HEAD teams/create teams.create App\Http\Controllers\TeamController@create
POST teams teams.store App\Http\Controllers\TeamController@store
データの更新
GET,HEAD teams/123456/edit teams.edit App\Http\Controllers\TeamController@edit
PUT,PATCH teams/123456 teams.update App\Http\Controllers\TeamController@update
データの削除
DELETE teams/123456 teams.destroy App\Http\Controllers\TeamController@destroy

● クロージャで path_info のパラメーターを渡す

Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});

● クロージャで Request と パラメータ id を渡す

use \Illuminate\Http\Request;
Route::get("/{id}", function (Request $request, $id) {
    return App\Http\Controllers\HomeJaController::index( $request, $id ); }
})->where([ 'id' => '[0-9]+' ]);

( id は 正規表現で数字のみに限定しておきます。 )

● ルーターの記述方法(個別)

/routes/web.php

メソッド: 「PUT」
URL: 「teams/{id}/myteamupdate」
を ↓ 
コントローラー「TeamController」の メソッド「myteamupdate」
にルーティングする

Route::put("teams/{id}/myteamupdate", "TeamController@myteamupdate")->name('teams.myteamupdate'); // Add this line in routes.php

● ルーターの記述方法(CRUD一括)

/routes/web.php

clients のCRUD関連メソッドを一括でルーティングする

Route::resource("clients","ClientController");

● ルーターの記述方法(CRUDから一部を除外)

CRUDから一部を除外する方法です

/routes/web.php

Route::resource("clients","ClientController");

 ↓ 「SHOWメソッド」「DELETE メソッド」を除外します

Route::resource('clients', 'ClientController', ['except' => ['show', 'delete'] ]);

● ルーティング変更を確認する

コマンドラインから以下のコマンドでルーティングを確認します。
peco コマンドがある場合は peco を通しましょう。

php artisan route:list | peco
No.1315
02/12 16:32

edit

ルーティング

Laravelでメールを送信する

Laravelにはメールを送信するクラス(mailable)が最初から用意されています。
これを使って管理者宛にメールを送信してみます。

● Laravel mailableを artisan から生成する

今回管理者宛にメール送信するプログラムなので名前を「Admin」とします。(命名は自由です好きに書き換えてください)

app/Mail/Admin.php というファイルを次のコマンドで生成します。

php artisan make:mail Admin

app/Mail/Admin.php が生成されました。 以下のように修正します。

public function build() の中を書き換えます
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class Admin extends Mailable
{
    use Queueable, SerializesModels;
    private $message;
    /**
     * Create a new message instance.
     * @return void
     */
    public function __construct( $m )
    {
        $this->message = $m;
    }
    /**
     * Build the message.
     * @return $this
     */
    public function build()
    {
        // ここを書き換えます ↓
        return $this->from('FROM-ADDRESS@YOUR-DOMAIN.COM')
                    ->subject( "エラーのお知らせ" )
                    ->view('mails.admin')
                    ->with([
                        'user_name' => 'テスト 太郎' ,
                        'my_text'   => $this->message ,
                    ]);
        // ここを書き換えます ↑
    }
}

● メール本文のテンプレートファイル resources/views/mails/admin.blade.php を作成する

まず、 resources/views へ移動し、ディレクトリ mails/ を作成します。 そしてその中にファイル admin.blade.php を以下の内容で作成します

こんにちは{{ $user_name }} !!!<br>
テストメールです<br>
{!! $my_text !!}

● コントローラーからメールを送信する

コントローラーの好きな所に記述します。

use Illuminate\Support\Facades\Mail;
use App\Mail\Admin;
// メール送信
$t = '任意のテキストをここに記述します';
Mail::to('TO-ADDRESS@YOUR-DOMAIN.COM')->send( new Admin($t) );

● .env ファイルのメールの設定を確認する

正しくメール送信が行える設定になっているか .env ファイルを確認します。
ローカルサーバではなくインターネット上にあるサーバの場合はとりあえずは以下の設定でメール送信が可能です。

MAIL_DRIVER=sendmail
MAIL_HOST=localhost
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=

● メール送信を記述したコントローラにアクセスしてメールを送信する

メール送信を記述したコントローラにアクセスしてメールを送信してみます。
このようなメールが到着します

● Laravelのメールドライバの種類

.env の MAIL_DRIVER には次の指定ができるようです。

MAIL_DRIVERの値 説明 補足
sendmail PHPのmail関数で送信する(一番簡単)
smtp SMTPサーバーへログインして送信する(id,passが必要)
mailgun MailgunというAPIベースのメール配信サービスから送信する
mandrill MailgunというAPIベースのメール配信サービスから送信する
ses Amazon AWSが提供するAmazon SESから送信する
sparkpost SparkPostというAPIベースのメール配信サービスから送信する
log 送信は行わず、ログファイルに内容を書き込む storage/logs/laravel.log に内容が記述されます
array ロジックは通りますが、送信はされません

引用: https://goo.gl/fjREcG

添付ファイル1
No.1312
11/09 15:23

edit

添付ファイル

Laravelのモデルで更新日(updated_at)のみ変更する

● Laravelのモデルで更新日(updated_at)のみ変更する

$model->touch(); 

これだけです、これだけで下記のようなSQL文が実行されます

            [query] => update `MY-TABLE` set `updated_at` = ? where `id` = ?
            [bindings] => Array
                (
                    [0] => 2018-10-17 22:44:43
                    [1] => 16090
                )
No.1311
10/17 22:47

edit

Laravel

Laravelで .env config ファイルに値を保存し取り出す

● .env ファイルに設定情報を保存する

MYAPP_URL=http://localhost

● .env ファイルから設定情報を取り出す

$aaa = env(MYAPP_URL);

設定がない場合にデフォルト値をセットすることもできます

$aaa = env(MYAPP_URL, 'default_value');

● config/xxxxx.php ファイルに設定情報を保存する

例: config/myfile.php に値を保存します

<?php
return [
	'data1' => "設定情報です" ,
];

KEY, VALUE 形式だけでなく 配列形式でも保存できます。

● config/xxxxx.php ファイルから設定情報を取り出す

次の2つのうちどちらでも取り出すことが出来ます。

config('myfile.data1');
\Config::get('myfile.data1');

● configファイルから値がとりだせない / 取り出した値が NULL になる時は

configファイルから値がとりだせない / 取り出した値が NULL になる時は次のコマンドを実行します

php artisan config:clear;

● .env ファイルに設定情報を保存する

No.1310
10/17 21:58

edit

LaravelでCLIから呼び出す自作コマンドを作成する。コマンドをcronで定期実行する

● LaravelでCLIから呼び出す自作コマンドを作成する

フレームワークによってはコントローラーを直接CLIから叩けるものもありますが、 Laravelの場合はコマンドを用意する必要があるようです。 (とはいえ artisan コマンドが用意されているので簡単です。)

● 作成するコマンド名を考える

コマンド名は

make:auth
make:migration

 のように(makeグループの中のauth)みたいな感じで、グルーピングされていますので、
自作コマンドもグルーピングしておくと、コマンドが増えた時に一覧表示で見やすくなります。

今回作成するコマンドは

myapp:print

とします。

● コマンドファイルを artisan で作成する

myapp:print コマンドを作成する時には次のように入力します

php artisan make:command  MyappPrint

するとファイル app/Console/Commands/MyappPrint.php が自動生成されます。

● 自動生成されたファイルを編集する

app/Console/Commands/MyappPrint.php を以下のようにします

protected $signature = 'myapp:print'; にコマンド名をセットします。
protected $description = 'MYAPP:にコマンドの説明をセットします。

<?php

namespace App\Console\Commands;
use Illuminate\Console\Command;

class MyappPrint extends Command
{
    /**
     * The name and signature of the console command.
     * @var string
     */
    protected $signature = 'myapp:print';


    /**
     * The console command description.
     * @var string
     */
    protected $description = 'MYAPP: ハローと表示します';


    /**
     * Create a new command instance.
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }


    /**
     * Execute the console command.
     * @return mixed
     */
    public function handle()
    {
        // ここにロジックを記述
        echo 'Hello Myapp Command !!!' . "\n";
    }
}

● ターミナルから実行する

php artisan myapp:print

結果

Hello Myapp Command !!!

● コマンドラインで引数を受け取る

1. シグネイチャを変更します

    protected $signature = 'myapp:print';

 ↓

    protected $signature = 'myapp:print {id}';

と変更します。

「引数なし」を許可するには

    protected $signature = 'myapp:print {id?}';

とします。

2.handle()メソッド内で引数を受け取ります

    public function handle()
    {
        // ここにロジックを記述
        $id = $this->argument('id');
        echo 'Hello Myapp Command !!!' . "\n";
        echo $id;
    }

ターミナルから実行時に引数を渡します

php artisan myapp:print

● Laravelでコマンドをcron定期実行する(タスクスケジュール)

Laravel で定期実行させるにはまず cron で毎分ごとにLaravelのスケジューラを実行させ、その中でLaravelで設定した時間ごとにコマンドを自動実行します。

1. crontab に設定する

crontab -e

crontabの書式に沿って以下のように記述します

* * * * * php7 /YOUR/APP/PATH/artisan schedule:run >> /dev/null 2>&1

2. app/Console/Kernel.php にコマンドを記述

コマンド「myapp:getdata」を1分ごとに起動するように設定します。

    protected function schedule(Schedule $schedule)
    {
        // RSSからデータを取得 (1分ごと)
        $schedule->command('myapp:getdata')->everyMinute();
    }

以上です。 ログを見て定期実行が行われているか確認します。

スケジュールは以下のように設定できます。

メソッド 説明
->cron('* * * * * *'); CRON記法によるスケジュール
->everyMinute(); 毎分タスク実行
->everyFiveMinutes(); 5分毎にタスク実行
->everyTenMinutes(); 10分毎にタスク実行
->everyFifteenMinutes(); 15分毎にタスク実行
->everyThirtyMinutes(); 30分毎にタスク実行
->hourly(); 毎時タスク実行
->hourlyAt(17); 一時間ごと、毎時17分にタスク実行
->daily(); 毎日深夜12時に実行
->dailyAt('13:00'); 毎日13:00に実行
->twiceDaily(1, 13); 毎日1:00と13:00時に実行
->weekly(); 毎週実行
->monthly(); 毎月実行
->monthlyOn(4, '15:00'); 毎月4日の15:00に実行
->quarterly(); 四半期ごとに実行
->yearly(); 毎年実行
->timezone('America/New_York'); タイムゾーン設定

● php artisan schedule:run で動作を確認する

cronでコマンドが呼ばれているかを確認するには

php artisan schedule:run

としますが、あらかじめ メソッドの修正が必要です!(重要)

1. schedule メソッドの実行間隔を 1分に変更する

1分に変更しないと、No scheduled commands are ready to run. が出て終了してしまいます。
また、重複起動を回避するメソッド withoutOverlapping() も外しておきましょう。

    protected function schedule(Schedule $schedule)
    {
        $schedule->command('myapp:getdata')->everyMinute();

2. schedule:run を実行する

php artisan schedule:run

とします。

これで必ず設定されたタスクが走るので、ログを見て動作を確認します。

● withoutOverlapping() メソッドはデッドロックを自動解除しない?

どうやら withoutOverlapping() はデッドロックを自動で解除できないようです。

https://goo.gl/mVchaN

No.1309
11/26 14:47

edit

Laravel
CLI
コマンド

Laravel マイグレーション時の「Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes"」の対処法

● varcharのデフォルト文字数を191文字にして(191*4 = 764バイト) 767バイトより小さくする

app\Providers\AppServiceProvider.php

// ↓ この行を追加
use Illuminate\Support\Facades\Schema;

    public function boot()
    {
        // ↓ この行を追加
        Schema::defaultStringLength(191);
    }

No.1307
10/16 16:11

edit

Laravel のコントローラーのコンストラクタで Authを使い、リダイレクトする

● Laravel のコントローラーのコンストラクタでAuthを使う

	function __construct(){

		// コンストラクタ内で Auth を使う
		$this->middleware(function ($request, $next) {
			$user = Auth::user();
			// .....

			return $next($request);
		});
	}

● Laravel のコントローラーのコンストラクタ等で強制リダイレクトを行う

use Illuminate\Support\Facades\Redirect;
Redirect::route('myerror')->withErrors(['redirect'=>'エラー発生'])->throwResponse();

引用: https://goo.gl/8rkAu5

No.1306
10/15 16:17

edit

Laraelのモデルでグローバルスコープ、ローカルスコープを動的なパラメーターでセットする

● Laravelのモデルの「スコープ」 とは

Laravelのモデルのスコープとは簡単にいうと SQL文の「 WHERE aaa = 'bbb'」みたいなWHERE句 なのですが、

・「User」モデルの中の管理者フラグを持つものだけを取り扱う
・「User」モデルが既にあるときに、現在削除されてないユーザー( WHERE is_deleted = 0 )を「Activeuser」モデルとして作成する。

みたいなところで使います。
その時に使うのが モデルの「スコープ」です。

好きな時につけたり外したりできる「ローカルスコープ」と
基本的につけっ放しの「グローバルスコープ」があります。

● グローバルスコープの作成方法

例:自分(ログインしているユーザー)と同じチームIDを持つという条件を
( Inmyteam )というグローバルスコープとして作成して、モデルに適用します。

1. グローバルスコープの作成

/app/Scopes/Inmyteam.php

<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;

class Inmyteam implements Scope
{
    /**
     * 自分のチーム内のユーザーに限定するスコープ
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        return $builder->where('team_id', '=', Auth::user()->team_id);
    }
}

2. モデルファイルから呼び出す。

app/User.php のメソッドに下記の boot() メソッドを追加する

use App\Scopes\Inmyteam;
    protected static function boot()
    {
        parent::boot();
        // スコープ「Inmyteam」を適用
        static::addGlobalScope(new Inmyteam);
    }

以上です。簡単ですね。
なおグローバルスコープに変数は渡せないようなので、ダイナミックに変わる条件(動的なパラメーター)を指定したい場合はセッションなど別のルートから取って来ましょう。
取れない場合はローカルスコープで設定します。

引用: https://goo.gl/Sk2F26

● ローカルスコープの作成方法

引用: https://goo.gl/Wfvuka

1. ローカルスコープの作成

モデルファイルの中に直接書けばOK。 ローカルスコープはメソッドに引数を渡せます。

app/User.php

    /**
     * XXXXX に限定するローカルスコープ
     *
     * @param    \Illuminate\Database\Eloquent\Builder         $query
     * @return   \Illuminate\Database\Eloquent\Builder
     */
     public function scopeForManager($query, $manager)
     {
         return $query->where('manager', $manager->id);
     }

2. ローカルスコープの呼び出し

User::forManager($manager)->all()
No.1305
02/15 10:27

edit

Laravel でリレーションを設定し、リレーション先のテーブルを取得する

LaravelでEloquentを使ってリレーションを設定し、リレーション先のテーブルを取得する方法です。

● テーブル例

次のような2つのテーブルがあるとします
・「チーム」(teams)
・「ユーザー」(users)

このようにチームの中に複数のユーザーが所属するとします

 ─── マイチーム
     ├── 鈴木 一郎
     ├── 山田 太郎
     ├── 中村 二郎

● リレーションの設定

モデル /app/Team.php

    /**
     * 1対多リレーション
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
public function users() // 複数形(users)にする
{
    // 「is_deleted = 0」のデータを「idの大きい順」で取得する
    return $this->hasMany('App\User')->where('is_deleted', 0)->orderBy('id', 'DESC');
}

(取得条件やソート順を指定することができます。)

モデル /app/User.php

public function team() // 単数形(team)にする
{
    return $this->belongsTo('App\Team');
}

● リレーションのデータの取得

・1. チーム一覧を所属するユーザー一覧とともに取得する

use App\Team;
$all_teams = Team::with('users')->get();
dd( $all_teams->toArray() );

(実は with() メソッドを指定しなくても、Bladeテンプレートの中で リレーションオブジェクトを呼び出そうとすると自動取得されます。 ただ、自動取得が100回あると100回SQLクエリが投げられるので非効率です。with()メソッドだと in句 で一撃で取得してきます。)

・2. ログイン中のユーザーデータを(チームIDに加えて)チーム名とともに取得する

方法1: with() を使ったやり方

$user = User::with('team')->find( Auth::user()->id );
dd( $user->toArray() );

実行されるSQL文

select * from `users`";
select * from `teams` where `teams`.`id` in (?); // ? は プレースホルダ

 

方法2: LEFT JOIN を使ったやり方

$user = User::leftJoin('teams','teams.id','=','users.team_id')->find( Auth::user()->id );
Mydump::dump( $user->toArray() );

実行されるSQL文

select * from `users` left join `teams` on `teams`.`id` = `users`.`team_id` where `users`.`id` = ? limit 1

・3. 全ユーザー一覧を(チームIDに加えて)チーム名とともに取得する

$all_users = DB::table('users')
                ->leftJoin('teams','teams.id','=','users.team_id')
                ->get();
Mydump::dump( $all_users );

その他リレーションの参考: https://laravel-news.com/eloquent-tips-tricks

No.1304
01/30 15:32

edit

DB
Eloquent
モデル

LaravelでDBのシーダーを使ってデフォルトのデータをセットする

マイグレーションをやり直した時に、DBデータも自動で登録できるようにシーダーを使ってデータを作成しておくと マイグレーションのやり直しがとても楽にできます。

● DBのシーダーファイルを作る

テーブル名「clients」の場合「ClientsSeeder」や「ClientsTableSeeder」といった名前をつけて作成します。

(例: clients テーブル用のシーダーファイルを作成する )

php artisan make:seeder ClientsSeeder

database/seeds/ClientsSeeder.php が作成されます )

● 作成されたDBのシーダーファイルを編集する

database/seeds/ClientsSeeder.php

<?php
use Illuminate\Database\Seeder;
class ClientsSeeder extends Seeder
{
    /**
     * Run the database seeds.
     * @return void
     */
    public function run()
    {
        DB::table("clients")->insert([
			'id'           => 1 ,
			'client_name'  => 'テスト商事' ,
			'tel_name'     => '012-345-6789' ,
			'fax_name'     => '012-345-6780',
        ]);
        DB::table("clients")->insert([
			'id'           => 2 ,
			'client_name'  => 'てすとの商事' ,
			'tel_name'     => '112-345-6789' ,
			'fax_name'     => '112-345-6780',
        ]);
    }
}

● 呼び出し元ファイル(DatabaseSeeder.php)に記述

database/seeds/DatabaseSeeder.php に作成したシーダーファイルを記述して呼び出します

<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     * @return void
     */
    public function run()
    {
        $this->call([
          ClientsSeeder::class ,		// 追加
        ]);
    }
}

● シーダーの実行

php artisan db:seed

● Class XXXXXSeeder does not exist エラーが出る場合

composer の autoload を再読み込みしてから実行するとうまく実行できます。

composer dump-autoload
php artisan db:seed
No.1303
10/23 14:43

edit

DB

Laravelのパンくずリストlaravel-breadcrumbsを使用してページタイトルとパンくずを表示させる

● laravel-breadcrumbsのインストール

composer require davejamesmiller/laravel-breadcrumbs:5.x

● パンくずリストのデータを定義する

routes/breadcrumbs.php を以下の内容で作成します

<?php

// Home
Breadcrumbs::for('home', function ($trail) {
    $trail->push('Home', route('home'));
});

// Home > About
Breadcrumbs::for('about', function ($trail) {
    $trail->parent('home');
    $trail->push('About', route('about'));
});

● 設定ファイルを生成する

次の設定ファイルを生成コマンドを実行します

php artisan vendor:publish --provider="DaveJamesMiller\Breadcrumbs\BreadcrumbsServiceProvider"

● パンくずリストを表示する

ビューファイル(XXXXX.blade.php)に以下のように記述します

{{ Breadcrumbs::render('home') }}

もしくは、Route::currentRouteName() で現在のルーティングが取得できるので

{{ Breadcrumbs::render(Route::currentRouteName()) }}

としておくとビューファイルは触らなくてもいいので楽です。(レイアウトファイルにパンくずを設置してある場合はこちらがおすすめです。)

● パンくずリストをカスタマイズする

自作のパンくずリストテンプレートを使用するには config/breadcrumbs.php を編集します

25行目を次のように書き換えます

###    'view' => 'breadcrumbs::bootstrap4',
    'view' => 'my_breadcrumbs',

すると、テンプレートファイルviews/breadcrumbs.blade.phpを見に行くようになります。

テンプレートファイルを用意する

views/breadcrumbs.blade.php

(以下は例です。適宜書き換えてください。)

@if (count($breadcrumbs))
    <ol class="navbar__breadcrumb breadcrumb d-none d-sm-flex">
        @foreach ($breadcrumbs as $breadcrumb)
            @if ($breadcrumb->url && !$loop->last)
                <li class="breadcrumb-item"><a href="{{ $breadcrumb->url }}">{{ $breadcrumb->title }}</a></li>
            @else
                <li class="breadcrumb-item active">{{ $breadcrumb->title }}</li>
            @endif
        @endforeach
    </ol>
@endif

以上です。 とても簡単にパンくずリストが出来るのでLaravelを使っている場合は必須ともいえるでしょう。

● パンくずの一番後ろのテキストをページタイトルとして表示する

これも便利です。blade.php ファイルにページタイトルを記述しなくても自動的にセットされます。

    <title>{{ ($breadcrumb = Breadcrumbs::current()) ? $breadcrumb->title : 'No Name' }}</title>
No.1302
11/13 16:43

edit

Laravel

Laravelのキャッシュクリア

● Laravelのファイル更新が反映されない?時はキャッシュクリアを行いましょう

Laravelで「ファイルを更新したのに更新されてない?」
という時はキャッシュが残っている可能性が大です。
こちらのコマンドでキャッシュを削除しましょう。

php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
composer dump-autoload

・1行で書いてコピペして実行!

php artisan cache:clear; php artisan config:clear; php artisan route:clear; php artisan view:clear; composer dump-autoload
No.1283
10/12 16:21

edit

Laravel

Laravel で自作パッケージを簡単に作成する

PackageCreator がとても便利です

● PackageCreator

https://github.com/SUKOHI/PackageCreator

・インストール

composer require sukohi/package-creator

インストールすると「make:package コマンド」が使用できるようになります

・パッケージの作成( php artisan make:package コマンド )

php artisan  make:package   (ベンダー名)   (パッケージ名)   (保存するフォルダ名(アプリケーションからの相対パス) )  

例 )

php artisan  make:package  myname  my-package  test_packages 

自動生成されるファイル

./test_packages/Myname/MyPackage/src/Facades/MyPackage.php
./test_packages/Myname/MyPackage/src/MyPackage.php
./test_packages/Myname/MyPackage/src/MyPackageServiceProvider.php
./test_packages/Myname/MyPackage/composer.json

● パッケージ作成例

例として mydump クラスを作成してみます。

1. コマンドの実行

php artisan  make:package  akato0315  mydump  mypackages 

2. クラスの実装

APP/mypackages/Akato0315/Mydump/src/Mydump.php を編集して以下の内容にします

<?php 
namespace Akato0315\Mydump;
class Mydump {
    public static function dump( $mix )
    {
  		print "\n".'<pre style="text-align:left;display:block;padding:9.5px;margin:10px;font-size:13px;line-height:1.4;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px;">'."\n";
  		print '<span style="color:#999;">TYPE: ' . gettype($mix) . "</span>\n";
  		print_r($mix);
  		print "\n</pre>\n\n";
    }

    public static function dump2( $mix )
    {
      print "\n"."<!--"."\n";
  		print "\n".'<pre style="text-align:left;display:block;padding:9.5px;margin:10px;font-size:13px;line-height:1.4;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px;">'."\n";
  		print '<span style="color:#999;">TYPE: ' . gettype($mix) . "</span>\n";
  		print_r($mix);
  		print "\n</pre>\n\n";
      print "\n"."-->"."\n";
    }
}

3. configファイル と composer.json を編集

APP/config/app.php の「providers」と「aliases」に以下を追加します

    'providers' => [
        ..................... 
        Akato0315\Mydump\MydumpServiceProvider::class,
    'aliases' => [
        ..................... 
        'Mydump' => Akato0315\Mydump\Facades\Mydump::class,

composer.json を以下のように修正します

        "psr-4": {
            "App\\": "app/" 
        }

        ↓

        "psr-4": {
            "App\\": "app/" ,
            "Akato0315\\Mydump\\": "mypackages/Akato0315/Mydump/src"
        }

4. コマンドラインから次のコマンドを実行

composer dumpautoload -o
php artisan config:cache

5. Laravelのコントローラーから使用する

use Mydump;

$mix = [
    'aaa' => 'bbb' ,
    'ccc' => 'ddd' ,
];
Mydump::dump( $mix );

5. 結果

添付ファイル1
mydump.png ( 22.5 KBytes ) ダウンロード
No.1282
10/05 09:52

edit

添付ファイル

Laravel
composer

Laravelのコントローラーからビューへの値の渡し方

● with

複数データを渡すときは連想配列で渡します

$data = [
 "data1" => $data1 ,  
 "data2" => $data2 ,  
];
return view('mytemplate')->with($data);

またはwithメソッドを2回呼んでもOKです。

return view('mytemplate')->with('data1',$data1)->with('data2',$data2);

● compact

すっきりと書きたい場合は compact を使って以下のように書くことができます

return view('mytemplate',compact('data1', 'data2'));

● ページネーションにパラメーターを渡す

コントローラーから次のように渡します。

$pagination_params = [
    "aaa" => 1 ,
    "bbb" => 2 ,
];
return view('mytemplate', compact('pagination_params'));

ビューでは次のようにして呼び出します
mytemplate.blade.php

{{ $model->appends($pagination_params)->links() }}

次のようなリンクがページネーションにつきます
( 3ページ目へのリンクにつく文字列 )

?&aaa=1&bbb=2&page=3

● ビューで渡された値の展開

foreach でオブジェクトを回す

<ul>
    @foreach($data_obj as $v)
    <li><a href="#">{{$v->data_name}}</a></li>
    @endforeach
</ul>

foreach で配列を回す

<ul>
    @foreach($data_loop as $v)
    <li><a href="#">{{$v['data_name']}}</a></li>
    @endforeach
</ul>

● ビューからコントローラーへのリンクを表示する

<a href="{{ route('tweets.index') }}">Tweets</a>

またはこのようにも書けます

<a href="{{ url("/tweets") }}">Tweets</a>
No.1279
10/09 16:17

edit

Laravel のページャー(ページネーション)の表示とカスタマイズ

● Laravelのページャー(ページネーション / pagination)の表示

Bladeテンプレート内で次のように記述します

{!! $tweets->render() !!}

links() というエイリアスもあります。(機能は同じ)

{{ $model->links() }}

● 検索結果ページなどパラメーターを引き継ぐ

検索結果ページでは「検索文字列」「1ページあたりの表示数」などのパラメーターを引き継ぐ必要があります。
その時は次のように appends() メソッドを呼びます。

コントローラー pagination_params をコントローラーから渡します

$pagination_params = [
// パラメーターセット(連想配列)
];

return view('users.index', compact(pagination_params'));

bladeテンプレート内

    {!! $tweets->appends($pagination_params)->links('pagination.default') !!}

● ページャー(ページネーション)のカスタマイズ

ページネーションをカスタマイズして「First Page」「Last Page」のリンクを追加してみましょう。

    {!! $tweets->links('pagination.default') !!}

resources/views/pagination/default.blade.php を以下の内容で新規作成します

@if ($paginator->lastPage() > 1)
<ul class="pagination">
    <li class="page-item {{ ($paginator->currentPage() == 1) ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->url(1) }}">First Page</a>
     </li>
    <li class="page-item {{ ($paginator->currentPage() == 1) ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->url(1) }}">
            <span aria-hidden="true">«</span>
            {{-- Previous --}}
        </a>
    </li>
    @for ($i = 1; $i <= $paginator->lastPage(); $i++)
        <li class="page-item {{ ($paginator->currentPage() == $i) ? ' active' : '' }}">
            <a class="page-link" href="{{ $paginator->url($i) }}">{{ $i }}</a>
        </li>
    @endfor
    <li class="page-item {{ ($paginator->currentPage() == $paginator->lastPage()) ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->url($paginator->currentPage()+1) }}" >
            <span aria-hidden="true">»</span>
            {{-- Next --}}
        </a>
    </li>
    <li class="page-item {{ ($paginator->currentPage() == $paginator->lastPage()) ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->url($paginator->lastPage()) }}">Last Page</a>
    </li>
</ul>
@endif

● カスタマイズした結果


         ↓

添付ファイル1
添付ファイル2
No.1278
08/06 09:35

edit

添付ファイル

Laravel で DBの構造と最後に実行したSQL文を取得する

● Laravel の Schema クラス

use Illuminate\Support\Facades\Schema;

category テーブルのカラムを配列で取得する

$columns = Schema::getColumnListing('category');
dump($columns);

● 最後に実行したSQL文を取得する

・方法その1

$data = $model->orderBy('id', 'desc')->paginate( 10 );
dump( $model->toSql() );

・方法その2

use DB;
DB::enableQueryLog();
$data = $model->orderBy('id', 'desc')->paginate( 10 );
dump(DB::getQueryLog());
No.1277
10/29 16:45

edit

Laravel