20200214のlaravelに関する記事は6件です。

Laravel HTML::linkやHTML::linkActionメソッドが使えない件(LaravelCollective)

環境

  • PHP 7.4.1
  • Composer 1.9.3
  • Laravel Framework 6.14.0
  • laravelcollective/html v6.0.3

結論

LaravelCollective/html v5.4から記法が変更になっています。
v5.4以降を使用する場合は、link_toやlink_to_actionメソッドを使いましょう。
完全にRailsに寄せてきてますね。
https://laravelcollective.com/docs/6.0/html#generating-urls

link_to('foo/bar', $title = null, $attributes = [], $secure = null)
link_to_action('HomeController@getIndex', $title = null, $parameters = [], $attributes = [])

参考(公式)

・LaravelCollective | HTML v5.3
https://laravelcollective.com/docs/5.3/html#generating-urls

・LaravelCollective | HTML v5.4
https://laravelcollective.com/docs/5.4/html#generating-urls

余談

以下の記事が更新されておらず、自分の環境だけかな?とめっちゃ焦りました。
以下のサイトに編集リクエストみたいなのが出せる人がいたら是非お願いします。

・Laravel Recipes日本語版 | HTMLリンクを生成する
http://recipes.laravel.jp/recipe/250

・Laravel Recipes日本語版 | コントローラのアクションへのHTMLリンクを生成する
http://recipes.laravel.jp/recipe/246

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel foreachで配列回して送信したcheckboxのoldを取得する

環境

  • PHP 7.4.1
  • Composer 1.9.3
  • Laravel Framework 6.14.0
  • laravelcollective/html v6.0.3

結論

laravelcollective/html入れてFormファサード使ったら、勝手に直前の入力値をcheckedにしてくれました。
便利すぎて震えた。

Composer

composer require laravelcollective/html

View

<form method="post" action="{{ action('HogeController@fuga') }}">
    {{ csrf_field() }}
    <input type="submit">
    <ul>
    @foreach($items as $item)
        <li>
          {{ Form::checkbox('item_ids[]', $item->id) }}
        </li>
    @endforeach
    </ul>

    {{-- バリデーションエラー確認用 --}}
    @if ($errors->any())
        <div class="alert alert-danger">
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif
</form>

Controller

public function fuga(Request $request) {
    $this->validate($request, [
        'item_ids' => 'required|array',
        'item_ids.*' => 'email' // わざとバリデーションをエラーにして確認. integerにする
    ]);
    dd($request->item_ids);
}

余談

もちろん、Formファサードを使用しない以下のコードはcheckedされません。

<input type="checkbox" name="item_ids[]" value="{{ $item->id }}">
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Homestead環境のログファイルの場所

環境

  • Laravel Homestead 9.2.0

結論

アプリケーションのルートから見て storage/logs/laravel.log にあります。
私の場合は /home/vagrant/code/Laravel/storage/logs/laravel.log でした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel-async-queueでLaravelの非同期キューを小さく使い始める

Laravelでキューを使うにはキューワーカーを立てる必要がありますが、キューワーカーのプロセス監視方法や、キューワーカーを使用しているアプリケーションのデプロイ方法を考える必要があり、結構面倒臭いです。
キューワーカーが不要な同期キュードライバもありますが、これだと非同期処理の旨味がありません。

laravel-async-queue

https://github.com/barryvdh/laravel-async-queue

laravel-async-queueというパッケージが非同期キュードライバを提供しています。
この非同期キュードライバを使うと、ジョブをバックグラウンドプロセスで即時に実行できるようになり、キューワーカーを立てることなく非同期処理の旨味を得ることができます。

インストール方法

なお、この記事では下記のバージョンのソフトウェアを使用しています。

ソフトウェア バージョン
PHP 7.2.12
Laravel 5.5.44
laravel-async-queue v0.7.3

laravel-async-queueをComposerでインストールします。

composer require barryvdh/laravel-async-queue

config/app.phpにサービスプロバイダを追加します。

config/app.php
Barryvdh\Queue\AsyncServiceProvider::class,

config/queue.phpdefaultオプションをasyncに変更します。

config/queue.php
'default' => 'async', 

さらにconnectionsオプションに非同期キュードライバ用の設定を追加します。

config/queue.php
'async' => [
    'driver' => 'async',
    'table' => 'jobs',
    'queue' => 'default',
    'expire' => 60,
],

動作テスト

動作テストをしてみます。

テスト用のコントローラとイベントリスナーとイベントを用意します。

app/Http/Controllers/TestController.php
<?php

namespace App\Http\Controllers;

use App\Events\TestEvent;
use App\Http\Controllers\Controller;
use Log;

class TestController extends Controller
{
    public function test()
    {
        Log::debug('1');
        event(new TestEvent());
        Log::debug('3');
    }
}
app/Listeners/TestListener.php
<?php

namespace App\Listeners;

use App\Events\TestEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;

class TestListener implements ShouldQueue
{
    public function handle(TestEvent $event)
    {
        Log::debug('2')
    }
}
app/Events/TestEvent
<?php

namespace App\Events;

class TestEvent
{
}
app/Providers/EventServiceProvider.php
protected $listen = [
    'App\Events\TestEvent' => [
        'App\Listeners\TestListener',
    ],
];

コントローラのアクションを実行すると、下記のようなログが出力されます。

[2020-02-13 23:36:45] local.APP.DEBUG: 1 [] {"uid":"93eb38d","process_id":1017}
[2020-02-13 23:36:45] local.APP.DEBUG: 3 [] {"uid":"93eb38d","process_id":1017}
[2020-02-13 23:36:47] local.APP.DEBUG: 2 [] {"uid":"535fd9a","process_id":1046}

1→3→2となっており、非同期処理されていることがわかります。
プロセスIDとUIDもコントローラとイベントリスナーで別になっています。

ちなみに同期ドライバの場合です。

[2020-02-13 23:38:22] local.APP.DEBUG: 1 [] {"uid":"a9173e4","process_id":1020}
[2020-02-13 23:38:22] local.APP.DEBUG: 2 [] {"uid":"a9173e4","process_id":1020}
[2020-02-13 23:38:22] local.APP.DEBUG: 3 [] {"uid":"a9173e4","process_id":1020}

1→2→3となっており、同期処理です。
もちろんプロセスIDとUIDもコントローラとイベントリスナーで同じです。

失敗ジョブを扱えるようにする

非同期キュードライバは、キューワーカーを使っていないため、ジョブが1回失敗すると自動ではリトライされません。

また、ジョブ失敗ベントが発行されず、失敗したジョブはjobsテーブルに残ったままで、failed_jobsテーブルに入りません。

これだと運用がつらいので、ジョブ失敗をSlackに通知したりできるように、ジョブ失敗イベントが発行されるようにします。

イベントリスナーの$tiresプロパティを1に設定すると、ジョブ失敗ベントが発行されるようになります1

class TestListener implements ShouldQueue
{
    public $tires = 1;
    ...
}

トレイトにしておくと便利かもしれません。

trait AsyncQueueable
{
    public $tires = 1;
}
class TestListener implements ShouldQueue
{
    use AsyncQueueable;
    ...
}

これでジョブ失敗イベントが発生するようになります。
同時に、失敗ジョブがjobsテーブルから消えるようになります。

ただ、このままだと失敗ジョブがjobsテーブルにもfailed_jobsテーブルにも残らなくなってしまうので、失敗ジョブをfailed_jobsテーブルに入れる処理をジョブ失敗イベントのコールバックとして書くことにします。
これはAppServiceProviderbootメソッドに書くのがいいと思います。

app/Providers/AppServiceProvider
\Illuminate\Support\Facades\Queue::failing(function (\Illuminate\Queue\Events\JobFailed $event) {
    if ($event->job->getConnectionName() == 'async') {
        // 失敗ジョブをfaled_jobsテーブルに保存する
        $id = $this->app['queue.failer']->log(
            $event->connectionName,
            $event->job->getQueue(),
            $event->job->getRawBody(),
            $event->exception
        );
    }
    // Slackへの通知など
    ...
});

ちなみに、logメソッドはfailed_jobsテーブルのIDが返ってきます。
Slackに通知する時に使うと、後でジョブを手動でリトライする際に便利でいいと思います。

これで失敗ジョブがfailed_jobsテーブルに入るようになります。

リトライが必要な場合は、下記のArtisanコマンドを実行します。

artisan queue:retry <failed_jobsテーブルのID>

これでfailed_jobsテーブルの失敗ジョブがjobsテーブルに戻ります。

さらに下記のArtisanコマンドを実行するとジョブを実行できます。

artisan queue:async <jobsテーブルのID>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのキューを小さく使い始める

Laravelでキューを使うにはキューワーカーを立てる必要がありますが、キューワーカーのプロセス監視方法や、キューワーカーを使用しているアプリケーションのデプロイ方法を考える必要があり、結構面倒臭いです。
キューワーカーが不要な同期キュードライバもありますが、これだと非同期処理の旨味がありません。

laravel-async-queue

https://github.com/barryvdh/laravel-async-queue

laravel-async-queueというパッケージが非同期キュードライバを提供しています。
この非同期キュードライバを使うと、ジョブをバックグラウンドプロセスで即時に実行できるようになり、キューワーカーを立てることなく非同期処理の旨味を得ることができます。

インストール方法

なお、この記事では下記のバージョンのソフトウェアを使用しています。

ソフトウェア バージョン
PHP 7.2.12
Laravel 5.5.44
laravel-async-queue v0.7.3

laravel-async-queueをComposerでインストールします。

composer require barryvdh/laravel-async-queue

config/app.phpにサービスプロバイダを追加します。

config/app.php
Barryvdh\Queue\AsyncServiceProvider::class,

config/queue.phpdefaultオプションをasyncに変更します。

config/queue.php
'default' => 'async', 

さらにconnectionsオプションに非同期キュードライバ用の設定を追加します。

config/queue.php
'async' => [
    'driver' => 'async',
    'table' => 'jobs',
    'queue' => 'default',
    'expire' => 60,
],

動作テスト

動作テストをしてみます。

テスト用のコントローラとイベントリスナーとイベントを用意します。

app/Http/Controllers/TestController.php
<?php

namespace App\Http\Controllers;

use App\Events\TestEvent;
use App\Http\Controllers\Controller;
use Log;

class TestController extends Controller
{
    public function test()
    {
        Log::debug('1');
        event(new TestEvent());
        Log::debug('3');
    }
}
app/Listeners/TestListener.php
<?php

namespace App\Listeners;

use App\Events\TestEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Log;

class TestListener implements ShouldQueue
{
    public function handle(TestEvent $event)
    {
        Log::debug('2')
    }
}
app/Events/TestEvent
<?php

namespace App\Events;

class TestEvent
{
}
app/Providers/EventServiceProvider.php
protected $listen = [
    'App\Events\TestEvent' => [
        'App\Listeners\TestListener',
    ],
];

コントローラのアクションを実行すると、下記のようなログが出力されます。

[2020-02-13 23:36:45] local.APP.DEBUG: 1 [] {"uid":"93eb38d","process_id":1017}
[2020-02-13 23:36:45] local.APP.DEBUG: 3 [] {"uid":"93eb38d","process_id":1017}
[2020-02-13 23:36:47] local.APP.DEBUG: 2 [] {"uid":"535fd9a","process_id":1046}

1→3→2となっており、非同期処理されていることがわかります。
プロセスIDとUIDもコントローラとイベントリスナーで別になっています。

ちなみに同期ドライバの場合です。

[2020-02-13 23:38:22] local.APP.DEBUG: 1 [] {"uid":"a9173e4","process_id":1020}
[2020-02-13 23:38:22] local.APP.DEBUG: 2 [] {"uid":"a9173e4","process_id":1020}
[2020-02-13 23:38:22] local.APP.DEBUG: 3 [] {"uid":"a9173e4","process_id":1020}

1→2→3となっており、同期処理です。
もちろんプロセスIDとUIDもコントローラとイベントリスナーで同じです。

失敗ジョブを扱えるようにする

非同期キュードライバは、キューワーカーを使っていないため、ジョブが1回失敗すると自動ではリトライされません。

また、ジョブ失敗ベントが発行されず、失敗したジョブはjobsテーブルに残ったままで、failed_jobsテーブルに入りません。

これだと運用がつらいので、ジョブ失敗をSlackに通知したりできるように、ジョブ失敗イベントが発行されるようにします。

イベントリスナーの$tiresプロパティを1に設定すると、ジョブ失敗ベントが発行されるようになります1

class TestListener implements ShouldQueue
{
    public $tires = 1;
    ...
}

トレイトにしておくと便利かもしれません。

trait AsyncQueueable
{
    public $tires = 1;
}
class TestListener implements ShouldQueue
{
    use AsyncQueueable;
    ...
}

これでジョブ失敗イベントが発生するようになります。
同時に、失敗ジョブがjobsテーブルから消えるようになります。

ただ、このままだと失敗ジョブがjobsテーブルにもfailed_jobsテーブルにも残らなくなってしまうので、失敗ジョブをfailed_jobsテーブルに入れる処理をジョブ失敗イベントのコールバックとして書くことにします。
これはAppServiceProviderbootメソッドに書くのがいいと思います。

app/Providers/AppServiceProvider
\Illuminate\Support\Facades\Queue::failing(function (\Illuminate\Queue\Events\JobFailed $event) {
    if ($event->job->getConnectionName() == 'async') {
        // 失敗ジョブをfaled_jobsテーブルに保存する
        $id = $this->app['queue.failer']->log(
            $event->connectionName,
            $event->job->getQueue(),
            $event->job->getRawBody(),
            $event->exception
        );
    }
    // Slackへの通知など
    ...
});

ちなみに、logメソッドはfailed_jobsテーブルのIDが返ってきます。
Slackに通知する時に使うと、後でジョブを手動でリトライする際に便利でいいと思います。

これで失敗ジョブがfailed_jobsテーブルに入るようになります。

リトライが必要な場合は、下記のArtisanコマンドを実行します。

artisan queue:retry <failed_jobsテーブルのID>

これでfailed_jobsテーブルの失敗ジョブがjobsテーブルに戻ります。

さらに下記のArtisanコマンドを実行するとジョブを実行できます。

artisan queue:async <jobsテーブルのID>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel ログイン後のリダイレクト先を指定

こんにちは!

laravelのデフォルトで実装されているログイン機能について、ログイン後のリダイレクト先を変更する方法を紹介します。

laravel 6.x系です

前提として、ログイン機能が実装済みとします!(リファレンスに記載されているコマンドを打てば実装できるはず)

で、デフォルト状態だと、ログイン画面でログインすると、'/home'にリダイレクトする仕様になっていると思いますが、任意のurlを指定すことができます

app/Http/Auth/LoginController.php
//省略

public function redirectPath()
    {
        return '任意のurl';
        //例)return 'costs/index';
    }

Auth/LoginControllerに↑の関数を追記することで、任意のurlにリダイレクトさせることができます!

自分はこのコントローラの一番下に記述しました。

これだけの内容です!

リダイレクトの条件分岐もできますので、気になる方はいろんな記事をググってみてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む