如何在LaravelEloquent中更新数据库记录

来自菜鸟教程
跳转至:导航、​搜索

在本系列的前一部分中,您更新了现有的 Artisan 命令以支持新的列表功能。 虽然有插入和删除链接的命令,但演示应用程序当前没有编辑现有链接的命令。 例如,这对于在列表之间移动链接或更新链接描述很有用。

在本指南中,您将创建一个新的 Artisan 命令来更新数据库中的现有链接。

在您的终端中,首先确保您位于项目的根目录中,然后运行以下命令来引导一个新的 Artisan 命令:

docker-compose exec app php artisan make:command LinkUpdate

这将创建一个位于 app/Console/Commands 的新 LinkUpdate.php 文件。 在您选择的代码编辑器中打开文件:

app/Console/Commands/LinkUpdate.php

此文件包含新 Artisan 命令的样板代码。 您将对其进行更新以处理编辑链接,前提是其唯一的 id。 这是您的 handle() 方法需要做的:

  • 获取用户提供的 id 并检查数据库中是否存在与 id 匹配的链接。
  • 如果找不到有效链接,则显示错误消息并退出。
  • 如果找到有效链接,则提示用户提供链接描述和链接列表的更新值。
  • 要求用户确认更改。
  • 确认后,更新数据库中的项目。

首先在文件顶部包含几个 use 定义,以便稍后引用 LinkLinkList 类:

应用程序/控制台/命令/LinkUpdate.php

<?php
 
namespace App\Console\Commands;
 
use App\Models\Link;
use App\Models\LinkList;
use Illuminate\Console\Command;
 
...

要获取链接 id,您应该在新的 link:update 命令中设置一个强制参数,以便用户在运行时需要提供该参数。 找到文件顶部的命令签名定义并将其替换为突出显示的行:

应用程序/控制台/命令/LinkUpdate.php

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

如果您保存文件并尝试在没有附加参数的情况下立即运行该命令,您将收到错误消息:

docker-compose exec app php artisan link:update
OutputNot enough arguments (missing: "link_id").

handle()方法中,需要获取用户提供的链接id并在数据库中定位。 这可以通过父 Command 类提供的 argument() 方法来完成。 然后,您可以使用 find() Eloquent 方法在数据库中查询与该 id 的链接。 如果 find() 方法返回 null,则表示没有找到与 id 的链接,因此程序应该错误退出。

应用程序/控制台/命令/LinkUpdate.php

...
   /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $link_id = $this->argument('link_id');
        $link = Link::find($link_id);
 
        if ($link === null) {
            $this->error("Invalid or non-existent link ID.");
            return 1;
        }
        
        // obtain updated information from user
    }
...

当找到有效链接时,您需要提示用户更新链接信息。您可以使用 ask 方法来执行此操作,在下一个示例中突出显示:

app/Console/Commands/LinkUpdate.php:函数句柄()

...
        if ($link === null) {
            $this->error("Invalid or non-existent link ID.");
            return 1;
        }
 
        $link->description = $this->ask('Link Description (ENTER to keep current)') ?? $link->description;
        $list_name = $this->ask('Link List (ENTER to keep current)') ?? $link->link_list->title;
...

此代码将提示用户更新描述和列表,同时将当前值保持为默认值,以防用户不提供新值,按 ENTER 跳过提示。

获得所有这些信息后,您可以继续进行更新。 在运行数据库更新之前,最好使用 confirm() 方法让用户确认更改。 这是这样的代码的样子:

app/Console/Commands/LinkUpdate.php:函数句柄()

...
        $link->description = $this->ask('Link Description (ENTER to keep current)') ?? $link->description;
        $list_name = $this->ask('Link List (ENTER to keep current)') ?? $link->link_list->title;
 
        $this->info("Description: $link->description");
        $this->info("Listed in: " . $list_name);
 
        if ($this->confirm('Is this information correct?')) {
            //code that updates the link
        }
...

if 块中,您必须首先检查请求的列表是否存在,否则使用提供的名称创建一个新列表。 然后,您将使用 associate() 方法更新此链接与其“父”列表之间的关系。 最后,save() 方法会将更改持久化到数据库中:

app/Console/Commands/LinkUpdate.php:函数句柄()

...
        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->link_list()->associate($list)->save();
            $this->info("Updated.");
        }
...

这是完整的 LinkUpdate.php 文件供您参考:

应用程序/控制台/命令/LinkUpdate.php

<?php
 
namespace App\Console\Commands;
 
use App\Models\Link;
use App\Models\LinkList;
use Illuminate\Console\Command;
 
class LinkUpdate extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:update {link_id}';
 
    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Update a link in the database';
 
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }
 
    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $link_id = $this->argument('link_id');
        $link = Link::find($link_id);
 
        if ($link === null) {
            $this->error("Invalid or non-existent link ID.");
            return 1;
        }
 
        $link->description = $this->ask('Link Description (ENTER to keep current)') ?? $link->description;
        $list_name = $this->ask('Link List (ENTER to keep current)') ?? $link->link_list->title;
 
        $this->info("Description: $link->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->link_list()->associate($list)->save();
            $this->info("Updated.");
        }
 
        return 0;
    }
}

注意: 有关 Artisan 命令的更多详细信息,请查看我们关于 如何在 Laravel 中创建 Artisan 命令以管理数据库记录的指南,这是我们介绍性 Laravel 系列的一部分。


完成后保存文件。 然后,使用 link:show 命令获取所有链接及其各自的 ID:

docker-compose exec app php artisan link:show 
Output+----+-------------------------------------------------+--------------+----------------------------------+
| id | url                                             | list         | description                      |
+----+-------------------------------------------------+--------------+----------------------------------+
| 1  | https://digitalocean.com/community              | default      | DO Community                     |
| 2  | https://digitalocean.com/community/tags/laravel | default      | Laravel Tutorias at DigitalOcean |
| 3  | https://digitalocean.com/community/tags/php     | default      | PHP Tutorials at DigitalOcean    |
| 4  | https://twitter.com/digitalocean                | social       | Twitter                          |
| 5  | https://dev.to/digitalocean                     | social       | DEV.to                           |
| 6  | https://laravel.com/docs/8.x/eloquent           | default      | Laravel Eloquent Docs            |
+----+-------------------------------------------------+--------------+----------------------------------+

然后,选择要编辑的项目。 例如,您可能希望为指向 DigitalOcean 网站的链接创建一个 digitalocean 列表(对应于 ID 为 12、和上一个示例输出中的 3)。

要更新 ID 为 1 的链接,请运行:

docker-compose exec app php artisan link:update 1 
Output Link Description (ENTER to keep current):
 > DO Community

 Link List (ENTER to keep current):
 > digitalocean

Description: DO Community
Listed in: digitalocean

 Is this information correct? (yes/no) [no]:
 > y

Updated.

然后,再次运行link:show命令可以看到更新的信息:

Output+----+-------------------------------------------------+--------------+----------------------------------+
| id | url                                             | list         | description                      |
+----+-------------------------------------------------+--------------+----------------------------------+
| 1  | https://digitalocean.com/community              | digitalocean | DO Community                     |
| 2  | https://digitalocean.com/community/tags/laravel | digitalocean | Laravel Tutorias at DigitalOcean |
| 3  | https://digitalocean.com/community/tags/php     | digitalocean | PHP Tutorials at DigitalOcean    |
| 4  | https://twitter.com/digitalocean                | social       | Twitter                          |
| 5  | https://dev.to/digitalocean                     | social       | DEV.to                           |
| 6  | https://laravel.com/docs/8.x/eloquent           | default      | Laravel Eloquent Docs            |
+----+-------------------------------------------------+--------------+----------------------------------+

在本指南中,您学习了如何使用 Laravel Eloquent 更新数据库记录。 您已升级演示应用程序以包含一个允许用户编辑数据库中现有链接的新命令。

在本系列的下一部分和最后一部分中,您将创建一个新命令来删除链接列表。