创建数据库与模型

本节将通过为 books 资源创建 SQLite 数据库表、填充示例数据并定义访问模型来构建数据层。完成后,将获得一个包含示例数据的 books 表。

创建迁移

迁移通过定义应用与回滚逻辑,实现对数据库架构的版本控制。下面为简单的 authorsbooks 表创建迁移。

运行 Spark 命令:

php spark make:migration CreateAuthorsTable
php spark make:migration CreateBooksTable

这将在 app/Database/Migrations/ 目录下创建新文件。

app/Database/Migrations/CreateAuthorsTable.php 修改为:

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class CreateAuthorsTable extends Migration
{
    public function up()
    {
        $this->forge->addField([
            'id' => [
                'type'           => 'INTEGER',
                'unsigned'       => true,
                'auto_increment' => true,
            ],
            'name' => [
                'type'       => 'VARCHAR',
                'constraint' => '255',
                'null'       => false,
            ],
            'created_at' => [
                'type' => 'DATETIME',
                'null' => true,
            ],
            'updated_at' => [
                'type' => 'DATETIME',
                'null' => true,
            ],
        ]);

        $this->forge->addPrimaryKey('id');
        $this->forge->addUniqueKey('name');
        $this->forge->createTable('authors');
    }

    public function down()
    {
        $this->forge->dropTable('authors');
    }
}

在本示例中,作者仅需姓名。已将姓名设为唯一键以防止重复。

现在,将 app/Database/Migrations/CreateBooksTable.php 修改为:

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class CreateBooksTable extends Migration
{
    public function up()
    {
        $this->forge->addField([
            'id' => [
                'type'           => 'INTEGER',
                'unsigned'       => true,
                'auto_increment' => true,
            ],
            'title' => [
                'type'       => 'VARCHAR',
                'constraint' => '255',
                'null'       => false,
            ],
            'author_id' => [
                'type'     => 'INTEGER',
                'unsigned' => true,
                'null'     => false,
            ],
            'year' => [
                'type' => 'INTEGER',
                'null' => true,
            ],
            'created_at' => [
                'type' => 'DATETIME',
                'null' => true,
            ],
            'updated_at' => [
                'type' => 'DATETIME',
                'null' => true,
            ],
        ]);

        $this->forge->addPrimaryKey('id');
        $this->forge->addForeignKey('author_id', 'authors', 'id');
        $this->forge->createTable('books');
    }

    public function down()
    {
        $this->forge->dropTable('books');
    }
}

其中包含指向 authors 表的外键引用。由此可将每本书与作者关联,并统一管理作者姓名。

运行迁移:

php spark migrate

此时,数据库已具备存储图书与作者记录所需的结构。

创建数据填充

数据填充用于在开发阶段加载示例数据,以便立即开展工作。此处将添加一些示例图书及其作者。

运行:

php spark make:seeder BookSeeder

修改 app/Database/Seeds/BookSeeder.php 文件:

<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;

class BookSeeder extends Seeder
{
    public function run()
    {
        // Define author data and insert
        $authorData = [
            ['name' => 'Frank Herbert'],
            ['name' => 'William Gibson'],
            ['name' => 'Ursula K. Le Guin'],
        ];

        $this->db->table('authors')->insertBatch($authorData);

        // Get all inserted authors, keyed by name for easy lookup
        $authors = $this->db->table('authors')
            ->get()
            ->getResultArray();

        $authorsByName = array_column($authors, 'id', 'name');

        // Define books with author references
        $books = [
            [
                'title'     => 'Dune',
                'author_id' => $authorsByName['Frank Herbert'],
                'year'      => 1965,
            ],
            [
                'title'     => 'Neuromancer',
                'author_id' => $authorsByName['William Gibson'],
                'year'      => 1984,
            ],
            [
                'title'     => 'The Left Hand of Darkness',
                'author_id' => $authorsByName['Ursula K. Le Guin'],
                'year'      => 1969,
            ],
        ];

        $this->db->table('books')->insertBatch($books);
    }
}

该填充器先向 authors 表插入作者信息并获取其 ID,随后使用这些 ID 向 books 表插入图书数据。

然后运行数据填充:

php spark db:seed BookSeeder

此时应看到记录已插入的确认信息。

创建 Book 模型

模型为数据表提供了面向对象接口与流畅的查询 API,使数据库访问变得简单且易于复用。接下来为 authorsbooks 表创建模型。

生成模型:

php spark make:model AuthorModel
php spark make:model BookModel

这两个模型都将简单地继承 CodeIgniter 的基础模型类。

修改 app/Models/AuthorModel.php

<?php

namespace App\Models;

use CodeIgniter\Model;

class AuthorModel extends Model
{
    protected $table         = 'authors';
    protected $primaryKey    = 'id';
    protected $allowedFields = ['name'];
    protected $useTimestamps = true;
}

修改 app/Models/BookModel.php

<?php

namespace App\Models;

use CodeIgniter\Model;

class BookModel extends Model
{
    protected $table         = 'books';
    protected $primaryKey    = 'id';
    protected $allowedFields = ['title', 'author_id', 'year'];
    protected $useTimestamps = true;
}

这会告知 CodeIgniter 使用哪张表,以及哪些字段允许批量赋值。

下一节将使用这些新模型来构建 RESTful API 控制器。届时将构建 /api/books 接口,并了解 CodeIgniter 的 Api\ResponseTrait 如何简化 CRUD 操作。