如何在Laravel中创建Artisan命令来管理数据库记录

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

如果到目前为止您一直在学习本系列,那么您的数据库表应该已经全部设置好了。 但是,您仍然需要实现一种方法,让用户在 links 表中插入新条目。

为了限制本系列的范围,同时使应用程序功能齐全,您将设置 Artisan 命令以在数据库中创建和删除链接。 Artisan 是 Laravel 附带的命令行工具,提供了许多实用程序来加快开发过程,从生成样板代码到删除和重新创建应用程序的数据库。

使用命令行界面来管理您的应用程序可以替代 Web 表单和安全区域,因为它需要用户登录服务器才能执行此类命令,而不是通过浏览器进行身份验证。 如果您稍后决定为您的应用程序创建一个安全区域,您可以创建 Web 表单以允许注册用户提交到数据库的新链接。

Artisan 命令通常用于执行应在后台运行的应用程序任务,可以手动或通过诸如 Crontab 之类的调度机制自动执行。 它们还可以用于帮助对需要动态配置的新应用程序功能进行原型设计,具体取决于授权用户的输入。

首先,使用 make:command 助手创建一个新的 Artisan 命令:

docker-compose exec app php artisan make:command LinkNew
OutputConsole command created successfully.

这将创建一个名为 LinkNew.php 的文件,位于 app/Console/Commands 目录中。 在这个继承自 Illuminate\Console\Command 父类的类中,您需要实现一个 handle 方法,该方法将在调用此命令时执行。 要定义命令的签名,您需要将 $signature 保护属性设置为 link:new

使用您选择的文本或代码编辑器打开新文件。 Here, nano is used:

nano app/Console/Commands/LinkNew.php

handle 方法中需要发生一些不同的事情,以便您能够保存到数据库的新链接。 首先,您将 提示用户输入 以获取链接 URL。

 $url = $this->ask('Link URL:');

然后,您将使用 filter_var 函数来验证从用户获得的输入是否是有效的 URL。 如果链接无效,您将显示错误并退出应用程序,状态码为 1,表示应用程序错误退出。

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

如果链接有效,您将继续使用与以前相同的方法请求链接描述。

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

然后,您将使用 confirm 帮助程序要求最终确认所有数据是否正确。 如果用户确认,链接最终被插入到数据库中。 您将使用在本系列的前一部分中创建的 Link Eloquent 模型与数据库进行交互。

        $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.");
        }

应用程序以 0 退出,表示成功状态(0 个错误)。

return 0;

以下代码包含这些步骤的完整实现。 将 LinkNew 类中的当前内容替换为:

应用程序/控制台/命令/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;
    }
}

完成后保存并关闭文件。

要执行命令并在数据库中插入新链接,请运行:

docker-compose exec app php artisan link:new
Output Link URL::
 > https://digitalocean.com/community

 Link Description::
 > DigitalOcean Community

New Link:
https://digitalocean.com/community - DigitalOcean Community

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

Saved.

如果您愿意,请随意添加更多链接。

列出链接

接下来,您需要创建一个新的 Artisan 命令来显示所有链接的列表。您可以将其命名为 link:list。 使用以下命令创建新命令:

docker-compose exec app php artisan make:command LinkList

使用您选择的文本或代码编辑器打开命令类:

nano app/Console/Commands/LinkList.php

在此命令的 handle 方法中,您将查询 links 表中的所有行。 您可以使用 Link 模型来访问 Eloquent 提供的底层 数据库查询方法。 要在命令行中很好地展示结果,您可以使用 table 输出助手:

        $headers = [ 'id', 'url', 'description' ];
        $links = Link::all(['id', 'url', 'description'])->toArray();
        $this->table($headers, $links);

        return 0;

以下代码包含 link:list 命令的完整实现。 将 LinkList.php 文件中的内容替换为:

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

<?php

namespace App\Console\Commands;

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

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

    /**
     * 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;
    }
}

完成后保存并关闭文件。

要运行此命令并显示已插入 links 表中的所有链接的列表,请运行:

docker-compose exec app php artisan link:list
Output+----+------------------------------------+--------------+
| id | url                                | description  |
+----+------------------------------------+--------------+
| 1  | https://digitalocean.com/community | DO Community |
| 2  | https://laravel.com                | Laravel      |
+----+------------------------------------+--------------+

删除链接

最后,您将创建一个 删除 链接的命令:

docker-compose exec app php artisan make:command LinkDelete
OutputConsole command created successfully.

使用您选择的文本或代码编辑器打开新文件:

nano app/Console/Commands/LinkDelete.php

您可以将此命令命名为 link:delete。 要知道必须删除哪个链接,您需要要求用户在调用命令时提供一个附加参数:链接的 ID。 这也是在 $signature 变量中设置的,它 定义了如何调用命令 以及应提供哪些参数,无论是否强制:

protected $signature = 'link:delete {link_id}';

此命令的 handle 方法将执行一些不同的指令。 首先,您将获得应该在命令调用中提供的链接 ID。

$link_id = $this->argument('link_id');

然后,您将使用 Eloquent 方法 find 从数据库中获取引用的链接,该方法可通过您的 Link 模型获得。

$link = Link::find($link_id);

find 方法没有找到具有该 ID 的数据库记录时,它将返回 null。 您将检查这是否是 $link 变量中包含的当前值,并在这种情况下返回错误。 程序将错误退出(代码 1)。

        if ($link === null) {
            $this->error("Invalid or non-existent link ID.");
            return 1;
        }

$link 不为空时,命令继续执行。 然后,您使用 confirm 助手请求用户确认。

if ($this->confirm('Are you sure you want to delete this link? ' . $link->url)) {
    // deletes link
}

当用户通过输入 yes 并点击 ENTER 确认操作时,您将从 Link Eloquent 模型中调用 delete 方法来删除指定的链接从数据库。

            $link->delete();
            $this->info("Link deleted.");

以下代码包含 list:delete 命令的完整实现。 将 LinkDelete.php 文件中的内容替换为以下内容:

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

<?php

namespace App\Console\Commands;

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

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

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Deletes a link from 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;
        }

        if ($this->confirm('Are you sure you want to delete this link? ' . $link->url)) {
            $link->delete();
            $this->info("Link deleted.");
        }

        return 0;
    }
}

完成后保存并关闭文件。

现在,当您想从链接表中删除链接时,您首先需要使用 artisan link:list 获取链接的 ID,如前所述。 知道链接的 ID 后,您可以运行 artisan link:delete 命令:

docker-compose exec app php artisan link:delete LINK_ID
Output
Are you sure you want to delete this link? https://laravel.com (yes/no) [no]:
 > yes

Link deleted.

您现在可以使用从命令行界面执行的 Artisan 命令在应用程序的数据库中插入、列出和删除链接。 在本系列的下一部分中,您将使用 Blade 模板和 Bulma CSS 框架设置应用程序的前端。