LaravelEloquentに新しいデータベースレコードを挿入する方法
このシリーズの前のセクションでは、LinkListモデルとLinkモデル間の1対多関係の2つのモデルを設定しました。 このセクションでは、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;
}
}
handle()メソッドは、コマンドがそのプロシージャを実行する場所です。 これはそれがすることです:
- 親の
Illuminate\Console\Commandクラスを介して利用できるask()メソッドは、コマンドラインでユーザーから入力を取得するために使用されるメソッドです。 これにより、ユーザーにリンクの入力を求め、入力を検証して、それが有効なURLであることを確認します。 - 次に、スクリプトはオプションの説明を要求します。
- urlおよびdescriptionの値が取得されると、スクリプトは、親
Illuminate\Console\Commandから利用できるconfirm()メソッドを使用して確認を求めるプロンプトを表示します。 yまたはyesで確認が送信されると、スクリプトは新しいリンクオブジェクトを設定し、モデルの親から利用できるsave()メソッドを使用してデータベースに保存します。Illuminate\Database\Eloquent\Modelクラス。- スクリプトは、
info出力メソッドを使用して、リンクがデータベースに保存されたことをユーザーに通知するメッセージを出力します。
戻り値に関する注意:bashで実行されているコマンドラインアプリケーションのコンテキストでは、ゼロ以外の戻り値は、アプリケーションがエラーで終了したことを通知するために使用されますが、0成功して終了したことを意味します。
ここでlink:newコマンドを実行すると、データベースはすべてのリンクがリストに接続されていることを想定しているため、終了する前にコマンドが壊れます。 リンクを含めるリストをユーザーが選択できるようにする必要があります。ユーザーから提供されていない場合は、デフォルトのリストを使用します。
次のコードは、デフォルトのリストを使用するためにリストを指定するか、空白のままにするようにユーザーに要求します。 次に、リストがまだ存在しない場合は、リストを検索するか、指定されたスラッグを使用して新しいリストを作成しようとします。 ユーザーから提供されたリストを取得するために、このコードはfirstWhereメソッドを使用して、slugフィールドに基づいてリストを検索します。 最後に、LinkListオブジェクトからアクセスできるlinks()関係を使用して新しいリンクを保存します。
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;
}
}
完了したら、ファイルを保存して閉じます。 次に、次のコマンドを実行します。
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()メソッド内でそのデータを使用するために、結果を配列に変換します。 問題は、配列変換が行われると、クラスモデル(LinkとLinkList)間の関係が失われ、リンクが接続されているリストに関する情報にアクセスするのが難しくなることです。に。
このコードを変更して、データベースから関連オブジェクトを含む完全な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モデルを使用してデータベースに新しいレコードを挿入する別の方法を示します。今回はデータベースシーダーを使用します。