LoginSignup
150
182

More than 1 year has passed since last update.

Laravelのちょっとつかえる小技

Last updated at Posted at 2017-12-10

基本自分用のメモですが、何かしらお役に立てれば幸いです。
随時更新していく予定です。

Laravel Excelでウィンドウ枠の固定

use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class InvoicesExport implements FromCollection, WithStyles
{
	public function styles(Worksheet $worksheet)
	{
	    $worksheet->freezePane('A5');
	}
}

イベントなしの単一モデル保存

モデルイベントを発行させずに、特定のモデルを「保存」したい場合があります。その場合は、saveQuietlyメソッドを利用する。

// User.php
class User extends Model
{
    protected static function boot()
    {
        parent::boot();
        static::saving(function ($model) {
            $model->name = strtolower($model->name);
        });
    }
}

// UserController.php
$user = User::findOrFail(1);
$user->name = 'Victoria Faith';
$user->saveQuietly();

dd($user->name); #=> Victoria Faith

ルーティングリストをJSONファイルに書き出す

php artisan route:list --json > routes.json

JSON配列を検索する

+-----------------------------------------------------------------------------------------------+
| id | tags                                                                         |
+-----------------------------------------------------------------------------------------------+
|  1 | ["Ruby","PHP","Javascript"]                                                  |
+-----------------------------------------------------------------------------------------------+

$tag = 'Javascript';
$posts = Post::whereRaw("JSON_CONTAINS(tags,'[\"{$tag}\"]')")->get();

+-----------------------------------------------------------------------------------------------+
| id | tags                                                                         |
+-----------------------------------------------------------------------------------------------+
|  1 | [{"id":1,"tag":"Ruby"},{"id":2,"tag":"PHP"},{"id":2,"tag":"Javascript"}]     |                                         
+-----------------------------------------------------------------------------------------------+

$tag = 'Javascript';
$posts = Post::whereRaw("JSON_CONTAINS(tags,'{\"tag\":{$tag}}')")->get();

共有configファイルの設定

// 階層
- public_config
  - payment.php
- my_project
  - app
    - Providers
      - ConfigServiceProvider.php

// ServiceProvider追加
class ConfigServiceProvider extends ServiceProvider
{
    public function register()
    {
        $config = '../public_config/payment.php';
        $this->app['config']['payment'] = include $config;
    }
}

setTestNow()でテスト日時をセットする

Carbon::setTestNow(Carbon::parse('2020-11-04 16:16:16'));

echo Carbon::now();
// 結果 => 2020-11-04 16:16:16
echo Carbon::tomorrow();
// 結果 => 2020-11-03 00:00:00

登録したルーティングをすべて取得したい

$routes = collect(\Route::getRoutes())->map(function ($route) {
    return [
        'url' => $route->uri(),
        'route_name' => $route->getName(),
        'method' => $route->methods()[0],
        'action_name' => $route->getActionName(),
    ];
});

全イベントハンドラの実行を停止したい

class Order extends Model
{
    public static function boot()
    {
        parent::boot();
        static::creating(function($model){
            //
        })
        static::deleted(function($model){
            //
        })
    }
}

$order = Order::withoutEvents(function(){
        return // 処理コード
});

経過日数の計算

$created_at = $post->created_at->format('Y-m-d');
$diff = now()->diffInDays($created_at);
if ($diff == 0) {
    echo '今日';
} else if ($diff == 1) {
    echo '昨日';
} else if ($diff == 2) {
    echo 'おととい';
} else {
    echo $created_at;
}

2つのカラムの値比較をする

# 方法一
$items = Item::whereRaw('stock < safe_stock')->get();
# 方法二
$items = Item::whereColumn('stock', '<','safe_stock')->get();

JSONの値を検索する。$.key名で値を探す

+-----------------------------------------------------------------------------------------------+
| id | shopping_address                                                                         |
+-----------------------------------------------------------------------------------------------+
|  1 | {"name":"山口太郎","zip_code":"5460001","phone":"09012345678","address":"xxxxxxxxxxxxx"}  |
+-----------------------------------------------------------------------------------------------+

$order = Order::where(\DB::raw("json_extract(shopping_address, '$.phone')"), request('phone'))->get();

unique属性で大文字や小文字が区別したい

重複しないデータを登録するためのフィールド属性として「UNIQUE」があります。半角アルファベットで「ABC」のデータがある状態で新たに「abc」を登録しようとすると重複エラーが出ます。

Schema::create('codes', function (Blueprint $table) {
{
    // ......
    $table->string('key')->unique()->charset('utf8')->collation('utf8_bin');
    // ......
});

こうすると、ちゃんとアルファベットの大文字と小文字を区別してくれるようになります!

ソートでNULLを最後に持ってくる

Task::orderByRaw('finished_at IS NULL ASC')
	->orderBy('finished_at')
	->get();

モデルの変更された属性を取得する

$user = App\User::first();
$user->name = "Tanaka";
$user->age = 25;

$user->getChanges();
// 結果 => ["name" => "Tanaka", "age" => 25]

モデルの元の属性値を取得する

$user = App\User::first();
$user->name;                   // 元の値 Taro

$user->name = "Tanaka";         // 変更後の値 Tanaka

$user->getOriginal('name');    // 変更前の値 Taro

Collection へpaginateメソッドを使う方法

App\Providers\AppServiceProvider
use Illuminate\Support\Collection; // 追加
use Illuminate\Pagination\LengthAwarePaginator; // 追加

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // ↓↓↓ 追加 ↓↓↓
        Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
            $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
            return new LengthAwarePaginator(
                $this->forPage($page, $perPage),
                $total ?: $this->count(),
                $perPage,
                $page,
                [
                    'path' => LengthAwarePaginator::resolveCurrentPath(),
                    'pageName' => $pageName,
                ]
            );
        });

    }
}

パラメータはIDか、Modelかを判断する

use App\Item;

public function scopeOfProduct($query, $item)
{
    $item = $item instanceof Item ? $item->id : $item;
    return $query->where('item_id', $item);
}

モデルのタイムスタンプだけをアップデートする

ユーザログインした際に、最終ログオン日時を記録したい場合

User::find(1)->touch();

CSRFエラーのチェック

長時間ログインフォームを放置するとログインした際にCSRFエラーが出ます。回避ため以下

App/Exceptions/Handler.php

use Illuminate\Auth\AuthenticationException; // 追加

class Handler extends ExceptionHandler
{
    public function render($request, Exception $exception)
    {
        // ↓↓↓ 追加 ↓↓↓
        // csrf 例外の場合はログイン画面に戻る
        if ($exception instanceof \Illuminate\Session\TokenMismatchException){
            return back()->withErrors(['セッションタイムアウト']);
        }

        return parent::render($request, $exception);
    }
}

HTTPリクエストインスタンスに配列を追加する

public function login(Request $request)
{
    $request->merge(['status' => 1]);
}

シンプルな日付フィルタ

/*** 日付フィルタ ***/
// 以前の書き方
Post::where('created_at', 'LIKE', '%2017-09-11%')->get();
// 今後の書き方
Post::whereDate('created_at', '2017-09-11')->get();

/*** 年フィルタ ***/
// 以前の書き方
Post::where('created_at', 'LIKE', '%2017-%')->get();
// 今後の書き方
Post::whereYear('created_at', '2017')->get();

/*** 月フィルタ ***/
// 以前の書き方
Post::where('created_at', 'LIKE', '%-09-%')->get();
// 今後の書き方
Post::whereMonth('created_at', '09')->get();

/*** 日フィルタ ***/
// 以前の書き方
Post::where('created_at', 'LIKE', '%-15%')->get();
// 今後の書き方
Post::whereDay('created_at', '15')->get();

現在表示されているページURL・リファラURLを表示する

// 現在表示されているページURL
url()->current();

// リファラURL
url()->previous();

配列の空要素を削除する

$data = ['test', 0, false, null, []];

array_filter($data);
// 結果 => ['test']

collect($data)->filter();
// 結果 => ['test']

指定したキーの全の値を一次元配列に代入する

多次元配列のキーは「ドット」記法で表示することができます。

$data = [
    ['item'=> ['name'=> 'test 1']],
    ['item'=> ['name'=> 'test 2']],
];

collect($data)->pluck('item.name');
// 結果 => ['test 1', 'test 2'],

簡単なデバッグ出力(一)

複数の変数を表示する事は知りませんでした。

dd($array);

dd($array, $string, 100);

簡単なデバッグ出力(二)

// 以前の書き方
$users = User::where('name', 'Taro')->get();
dd($users);

// 今後の書き方
$users = User::where('name', 'Taro')->get()->dd();

@includewhenディレクティブを使用する

// Laravel5.3以前の書き方
@if ($user->isAdmin)
    @include('admin.navbar')
@endif

// Laravel5.4以降の書き方
@includeWhen($user->isAdmin, 'admin.navbar')

リダイレクト専用ルーティング

Route::redirectはLaravel5.5から使用可能になります。詳しく

// 以前の書き方
Route::get('/user', function () {
    return redirect('/user/profile');
});

// 今後の書き方
Route::redirect('/user', '/user/profile');

配列からランダムに値を取得する

array_randomはLaravel5.5から使用可能になります。詳しく

// 以前の書き方
return $names[array_rand($names)];

// 今後の書き方
return array_random($names);

指定した値を配列中にラップする

array_wrapはLaravel5.5から使用可能になります。詳しく

// 以前の書き方
$names = is_array($names) ? $names : [$names];

// 今後の書き方
return array_wrap($names);

->latest()でデータを簡単に整列する

引数指定してない場合、created_atカラムによりソートされます。

// 以前の書き方
$articles = Article::orderBy('published_at', 'desc')->get();

// 今後の書き方
$articles = Article::latest('published_at')->get();
150
182
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
150
182