このシリーズの前のセクションでは、1対多の関係のために2つのモデルを設定しました。 LinkListLink モデル。 このセクションでは、Eloquentモデルを使用してデータベースにリンクとリストを挿入する方法を学習します。 この作業の範囲を制限するには、カスタムArtisanコマンドを使用して、コマンドラインからリンクとリストを管理します。これにはWebフォームは必要ありません。

ORMシステムを使用する最大の利点の1つは、データベーステーブルの行をコードベース内のオブジェクトとして操作できることです。 Eloquentを使用すると、他のORMと同様に、オブジェクト自体がデータベースに永続化するために使用できるメソッドを提供し、SQLステートメントの記述やテーブル内のデータの手動管理の作業を節約します。

Laravel Eloquentで1対多の関係を操作する場合、関連するモデルを保存するためのいくつかの異なるオプションがあります。 ほとんどの場合、最初に関係のone側を表すモデルを設定する必要があります。このデモでは LinkList モデル化し、それをデータベースに保存します。 その後、関係の多くの側( Link モデル)。 これは、リンクを作成できるようにするために、最初に1つ以上のリストを用意する必要があることも意味します。

ただし、リストを挿入する新しいコマンドを作成する前に、既存のコマンドを更新する必要があります link:new リスト機能をサポートするコマンド。

コードエディタで次のファイルを開きます。

app/Console/Commands/LinkNew.php

次のようなコードが表示されます。

app / Console / Commands / LinkNew.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class LinkNew extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:new';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a New Link';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $url = $this->ask('Link URL:');

        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            $this->error("Invalid URL. Exiting...");
            return 1;
        }

        $description = $this->ask('Link Description:');

        $this->info("New Link:");
        $this->info($url . ' - ' . $description);

        if ($this->confirm('Is this information correct?')) {
            $link = new Link();
            $link->url = $url;
            $link->description = $description;
            $link->save();

            $this->info("Saved.");
        }

        return 0;
    }
}

The handle() メソッドは、コマンドがそのプロシージャを実行する場所です。 これはそれがすることです:

  1. The ask() 親を通じて利用可能になったメソッド Illuminate\Console\Command classは、コマンドラインでユーザーから入力を取得するために使用されるメソッドです。 これにより、ユーザーにリンクの入力を求め、入力を検証して、それが有効なURLであることを確認します。
  2. 次に、スクリプトはオプションの説明を要求します。
  3. urlおよびdescriptionの値が取得されると、スクリプトは、 confirm() 親を通じて利用可能なメソッド Illuminate\Console\Command.
  4. で確認が送信されたとき y また yes、スクリプトは新しいリンクオブジェクトを設定し、を使用してデータベースに保存します。 save() モデルの親から利用可能なメソッド Illuminate\Database\Eloquent\Model クラス。
  5. スクリプトは、リンクがデータベースに保存されたことをユーザーに通知するメッセージを出力します。 info 出力方法。

戻り値に関する注意:で実行されているコマンドラインアプリケーションのコンテキストで bash、ゼロ以外の戻り値は、アプリケーションがエラーで終了したことを通知するために使用されますが、 0 それが成功して終了したことを意味します。

あなたが実行する場合 link:new 今すぐコマンドを実行すると、データベースはすべてのリンクがリストに接続されていることを想定しているため、終了する前に中断します。 リンクを含めるリストをユーザーが選択できるようにする必要があります。ユーザーから提供されていない場合は、デフォルトのリストを使用します。

次のコードは、デフォルトのリストを使用するためにリストを指定するか、空白のままにするようにユーザーに要求します。 次に、リストがまだ存在しない場合は、リストを検索するか、指定されたスラッグを使用して新しいリストを作成しようとします。 ユーザーから提供されたリストを取得するために、このコードは firstWhere slugフィールドに基づいてリストを検索するメソッド。 最後に、を使用して新しいリンクを保存します links() からアクセスできる関係 LinkList 物体。

現在のコンテンツを LinkNew コマンドクラス:

app / Console / Commands / LinkNew.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use App\Models\LinkList;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class LinkNew extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:new';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a New Link';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $url = $this->ask('Link URL');

        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            $this->error("Invalid URL. Exiting...");
            return 1;
        }

        $description = $this->ask('Link Description');
        $list_name = $this->ask('Link List (leave blank to use default)') ?? "default";

        $this->info("New Link:");
        $this->info($url . ' - ' . $description);
        $this->info("Listed in: " . $list_name);

        if ($this->confirm('Is this information correct?')) {
            $list = LinkList::firstWhere('slug', $list_name);
            if (!$list) {
                $list = new LinkList();
                $list->title = $list_name;
                $list->slug = $list_name;
                $list->save();
            }

            $link = new Link();
            $link->url = $url;
            $link->description = $description;
            $list->links()->save($link);

            $this->info("Saved.");
        }

        return 0;
    }
}

完了したら、ファイルを保存して閉じます。 次に、次のコマンドを実行します。

  1. docker-compose exec app php artisan link:new

このリンクをデフォルトのリストに保存したくない場合は、URL、説明、およびリスト名を入力するように求められます。

新しいリンクを保存したら、 link:show コマンドを実行すると、結果に新しいリンクが追加されます。 ただし、リストに関する出力にはまだ情報が含まれていません。 更新する必要があります LinkShow この情報を表示する列を含めるコマンド。

を開きます app/Console/Commands/LinkShow.php コードエディタのファイル:

app/Console/Commands/LinkShow.php

クラスは次のようになります。

app / Console / Commands / LinkShow.php
<?php
 
namespace App\Console\Commands;
 
use App\Models\Link;
use Illuminate\Console\Command;
 
class LinkShow extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:show';
 
    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'List links saved in the database';
 
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }
 
    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $headers = [ 'id', 'url', 'description' ];
        $links = Link::all(['id', 'url', 'description'])->toArray();
        $this->table($headers, $links);
 
        return 0;
    }
}

あなたは現在のことを見るでしょう handle() メソッドは、特定の数のフィールドをフェッチし、結果を配列に変換しています。 デフォルトでは、結果はEloquentコレクションとしてEloquentから取得されるため、この関数は、そのデータを内で使用するために、それらを配列に変換します。 table() 方法。 問題は、配列変換が行われると、クラスモデル間の関係が失われることです(LinkLinkList)。これにより、リンクが接続されているリストに関する情報へのアクセスがより困難になります。

このコードを変更して、完全なコードを取得する必要があります Link データベースからの関連オブジェクトを含むオブジェクト。 での使用に適したアレイを作成するには table() メソッドでは、によって返される結果のコレクションを反復処理できます Link::all().

の現在の内容を置き換えます app/Console/Commands/LinkShow.php 次のコードでファイルします。

app / Console / Commands / LinkShow.php
<?php

namespace App\Console\Commands;

use App\Models\Link;
use Illuminate\Console\Command;

class LinkShow extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:show';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'List links saved in the database';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $headers = [ 'id', 'url', 'list', 'description' ];
        $links = Link::all();

        $table_rows = [];
        foreach ($links as $link) {
            $table_rows[] = [ $link->id, $link->url, $link->link_list->slug, $link->description ];
        }

        $this->table($headers, $table_rows);

        return 0;
    }
}

今、あなたが実行すると link:show メソッドの場合、リストスラッグを示す追加の列が表示されます。

Output
+----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+ | id | url | list | description | +----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+ | 1 | https://digitalocean.com | default | DigitalOcean Website | | 2 | https://digitalocean.com/community/tutorials | tutorials | DO Tutorials | | 3 | initial-server-setup-with-ubuntu-20-04 | tutorials | Initial server setup on ubuntu 20.04 | +----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+

このチュートリアルシリーズの後半では、フロントエンドとメインルートコードを更新して、リストに整理されたリンクを表示します。 ここでは、コマンドラインを使用して、データベースとモデルへの変更を追加、移行、および検証します。

このシリーズの次のチュートリアルでは、Eloquentモデルを使用してデータベースに新しいレコードを挿入する別の方法を示します。今回はデータベースシーダーを使用します。