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

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 

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

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

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
11/17 15:17

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>
添付ファイル1
No.1361
11/15 15:26

edit

添付ファイル

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

● laravel-debugbarのインストール

composer require barryvdh/laravel-debugbar

● 使い方

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

APP_DEBUG=true

laravel-debugbar の起動方法

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

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

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',

以上です。

No.1356
11/15 09:49

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に準拠。
単数形複数形には注意する事。

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
11/09 09:49

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 に シンボリックリンクを貼ってください。

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

No.1349
11/15 10:58

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 }}

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

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
11/15 16:16

edit

添付ファイル

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

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

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
11/06 10:35

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 を使ってマークダウンをパースするのインストール

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

composer require andreasindal/laravel-markdown

2. Bladeの記述を変更する

{{ $memo->text_name }}

 ↓

@markdown($memo->text_name)

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

No.1341
11/01 17:15

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パラメーター( ? 以降の文字列)も取得します。)

{{ Request::getPathInfo() }}?{{ Request::getQueryString() }}

例: /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/08 21:53

edit

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

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

@csrf

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

<input type="hidden" name="_token" value="{{ csrf_token() }}"
No.1324
10/26 09:08

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. 使う

dump( $request->input('back_uri') );
No.1322
10/24 11:34

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>

● 値をを選択済み(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>
No.1317
11/01 14:55

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 App\User
    //  */
    public function created_user()
    {
        return $this->hasOne('App\User', 'id', 'created_user_id')->withDefault();
    }

    // /**
    //  * 1対1リレーション
    //  * @return App\User
    //  */
    public function updated_user()
    {
        return $this->hasOne('App\User', 'id', 'updated_user_id')->withDefault();
    }

->withDefault() がミソですね。存在しないときに中身が空のオブジェクトを返します。

● コントローラーから取得する時に 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
10/22 16:31

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

● ルーティングの記述方法(個別)

/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");
No.1315
11/01 13:04

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'); タイムゾーン設定
No.1309
11/16 10:44

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

public function scopeForManager($query, $manager)
{
    return $query->where('manager', $manager->id);
}

2. ローカルスコープの呼び出し

User::forManager($manager)->all()
No.1305
11/15 11:46

edit

Laravel でリレーションを設定し、リレーション先のテーブルを取得する

LaravelでEloquentを使ってリレーションを設定し、リレーション先のテーブルを取得する方法です。

● テーブル例

次のような2つのテーブルがあるとします
・「チーム」(teams)
・「ユーザー」(users)

このようにチームの中に複数のユーザーが所属するとします

 ─── マイチーム
     ├── 鈴木 一郎
     ├── 山田 太郎
     ├── 中村 二郎

● リレーションの設定

モデル /app/Team.php

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
11/10 22:21

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