使用 PHP 设计初创公司的数据库并概述功能需求

使用 php 设计初创公司的数据库并概述功能需求

这是“使用 PHP 构建您的初创公司”系列的第二部分,在其中我将引导您完成我的初创公司 Meeting Planner 从概念到启动的整个开发过程。在这一部分中,我将概述功能目标和要求,然后引导您完成初始数据库设计和迁移。

因为我们不会看到很多功能立即生效,所以这一集可能看起来有点枯燥,但为接下来的所有内容奠定基础至关重要。如果您还没有设计过 Active Record 数据库迁移并使用过 Yii 的脚手架应用程序 Gii,那么您可能会学到很多东西。

功能要求

在描述 Meeting Planner 数据库的具体信息之前,我将引导您了解 Meeting Planner 将提供的高级功能。

规划会议

允许用户创建会议请求并邀请其他人(我们的最低可行产品仅邀请一个人)。 允许用户建议和选择地点。允许用户建议和选择日期和时间。允许用户在会议规划过程中互相发送注释。建议适合在用户附近举行会议的地点。记录所有会议添加和更改的日志(或历史记录)。

支持地点

允许用户添加他们喜欢定期聚会的最喜欢的地点。允许用户添加自己的会议地点,例如家庭和办公室。部分根据受欢迎程度建议距离每位参与者较近或等距的地点。

支持用户

维护所有正在进行的、已确认的和过去的用户会议的列表。允许用户提供联系信息,例如在线会议的电话号码和 Skype 地址。允许用户关闭不需要的电子邮件,即取消订阅。要求用户在发送邀请之前验证其电子邮件的身份。轻松阻止与不需要的邀请相关的电子邮件,例如垃圾邮件。

让事情变得更简单、更快

允许用户创建模板,以便更轻松地安排常见会议,并提供建议的日期和时间以及最喜欢的地点,例如我想安排在我最喜欢的地点、星期几和开始时间与某人一起喝早间咖啡发送包含会议更改的电子邮件,并附上用于进行更改的命令的 URL 链接,例如取消或要求更改地点、日期或时间;通过这些链接中的验证码对用户进行身份验证。提前一天发送会议提醒,其中包含联系方式和路线。

赚取收入

允许广告商,例如餐馆、咖啡店和租赁办公空间来宣传他们的场所。

虽然上面并不是详尽的功能列表,但它使您清楚地了解我们需要数据库架构支持什么。

立即学习“PHP免费学习笔记(深入)”;

安装会议规划器存储库

要开始为 Meeting Planner 设置开发环境,您可以使用我的指南《使用 Yii2 编程:入门》;按照说明安装 Composer。

所有会议策划者教程都将在我们的免费开源 Github 存储库中进行标记。因此,对于本教程系列的这一部分,您可以从此处安装基本的会议规划器框架。

对于 Meeting Planner,我安装了 Yii2 的高级应用程序模板,它为复杂的应用程序提供了稍微更强大的架构,例如用于前端(最终用户)和后端(管理)访问的不同应用程序。

要开始使用代码,您需要克隆存储库,查看本部分教程的标记版本,运行初始化,并要求 Composer 更新文件:

cd ~/Sitesgit clone git@github.com:newscloud/mp.gitcd ~/Sites/mpgit checkout p2 sudo -s php initsudo composer update

登录后复制

我在本地开发环境中使用 MAMP。因此,我需要将我首选的前端本地主机 URL 指向 ~/Sites/mp/frontend/web:

cd /Applications/MAMP/htdocsln -s ~/Sites/mp/frontend/web/ /Applications/MAMP/htdocs/mp

登录后复制

如果您将浏览器导航到 http://localhost:8888/mp,您应该会看到如下内容:

使用 PHP 设计初创公司的数据库并概述功能需求

然后,您需要在 MySQL 中创建数据库并在 环境devcommonmain-local.php:

 [        'db' => [            'class' => 'yiidbConnection',            'dsn' => 'mysql:host=localhost;dbname=your-db',            'username' => 'your-username',            'password' => 'your-pwd',            'charset' => 'utf8',        ],

登录后复制

在我们进一步深入运行迁移之前,我想引导您完成初步的数据库设计。

设计数据库架构

因为我正处于构建代码的早期阶段,所以我试图彻底完成数据库的布局;然而,随着我的前进,设计可能需要改变或发展。

Yii 的 Active Record 迁移使得在不同环境中以编程方式创建数据库变得相对容易,例如:本地和生产,并逐步发展它们。您可以在此处了解有关 Yii Active Record 的更多信息。

用户表

第一次迁移构建了用户表,它包含在 Yii 的高级应用程序模板中 – 请参阅 /mp/console/migrations/m130524_201442_init.php。

此迁移告诉 Yii 创建一个新的 SQL 表,其中包含用户表所需的字段,如下所示:

db->driverName === 'mysql') {            // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';        }        $this->createTable('{{%user}}', [            'id' => Schema::TYPE_BIGPK,            'friendly_name' => Schema::TYPE_STRING . ' NOT NULL',            'username' => Schema::TYPE_STRING . ' NOT NULL',            'auth_key' => Schema::TYPE_STRING . '(32) NOT NULL',            'password_hash' => Schema::TYPE_STRING . ' NOT NULL',            'password_reset_token' => Schema::TYPE_STRING,            'email' => Schema::TYPE_STRING . ' NOT NULL',            'role' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 10',            'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 10',            'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',            'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',        ], $tableOptions);    }    public function down()    {        $this->dropTable('{{%user}}');    }}

登录后复制

您可以运行第一次迁移,如下所示:

cd ~/Sites/mp./yii migrate/up 1

登录后复制

您应该看到类似这样的内容:

Jeffs-Mac-mini:mp Jeff$ ./yii migrate/up 1Yii Migration Tool (based on Yii v2.0.0)Creating migration history table "migration"...done.Total 1 out of 15 new migrations to be applied:    m130524_201442_initApply the above migration? (yes|no) [no]:yes*** applying m130524_201442_init    > create table {{%user}} ... done (time: 0.068s)*** applied m130524_201442_init (time: 0.071s)Migrated up successfully.

登录后复制

Yii 为注册、登录、注销等常见操作提供内置 Web 支持。此功能和此表将为我们的初始身份验证功能提供支持基础。我们稍后可能会以各种方式对其进行扩展,例如支持 Twitter 或 Google OAuth 进行身份验证。

通过 Active Record 迁移,您还可以向后迁移。这在开发过程中特别有帮助。例如向下迁移会删除User表:

Jeffs-Mac-mini:mp Jeff$ ./yii migrate/down 1Yii Migration Tool (based on Yii v2.0.0)Total 1 migration to be reverted:    m130524_201442_initRevert the above migration? (yes|no) [no]:yes*** reverting m130524_201442_init    > drop table {{%user}} ... done (time: 0.001s)*** reverted m130524_201442_init (time: 0.070s)Migrated down successfully.

登录后复制

如果您需要调整表格设计,可以先进行调整,然后再迁移回来。

会议桌

会议架构以及与会议相关的所有表格对于我们应用程序的功能非常重要。

这是会议的基本架构:

 $this->createTable('{{%meeting}}', [            'id' => Schema::TYPE_PK,            'owner_id' => Schema::TYPE_BIGINT.' NOT NULL',            'meeting_type' => Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0',            'message' => Schema::TYPE_TEXT.' NOT NULL DEFAULT ""',            'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',            'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',            'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',        ], $tableOptions);

登录后复制

会议的基础由所有者、会议指示符类型、邀请消息、状态字段以及标准创建和更新时间字段组成。

通过 Active Record,Yii 可以帮助我们自动创建表之间的关系。在会议表中,我们将创建一个关系,即每个会议在用户表中都有一个所有者。我们在迁移中通过创建一个外键将会议 -> Owner_ID 连接到用户 -> ID 来完成此操作。

$this->addForeignKey('fk_meeting_owner', '{{%meeting}}', 'owner_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');        

登录后复制

我们还需要在向下迁移中删除外键:

    public function down()    {       $this->dropForeignKey('fk_meeting_owner', '{{%meeting}}');        $this->dropTable('{{%meeting}}');    }

登录后复制

在我们进入 Yii 的自动化脚手架系统 Gii 之前,请耐心等待我概述更多架构。

您可以在 /mp/console/migrations 文件夹 中看到所有迁移:

使用 PHP 设计初创公司的数据库并概述功能需求

我们将在下面回顾其中的大部分内容。

餐位表

地点也是 Meeting Planner 中的一个重要组成部分,因为它们是每个人都会见面的地点。它们按地理位置编入索引,并在 Google 地方信息中引用。

这是地点的架构:

$tableOptions = null;      if ($this->db->driverName === 'mysql') {          $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';      }      $this->createTable('{{%place}}', [          'id' => Schema::TYPE_PK,          'name' => Schema::TYPE_STRING.' NOT NULL',                    'place_type' => Schema::TYPE_SMALLINT.' NOT NULL DEFAULT 0',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'google_place_id' => Schema::TYPE_STRING.' NOT NULL', // e.g. google places id          'created_by' => Schema::TYPE_BIGINT.' NOT NULL',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_place_created_by', '{{%place}}', 'created_by', '{{%user}}', 'id', 'CASCADE', 'CASCADE');

登录后复制

地点由 name、place_type、status、created_at 和 更新_at。但它们还包含 google_place_id 将它们与 Google Places 目录关联起来。

请注意,没有任何与此表中的地点关联的地理位置。这是因为 MySQL InnoDB 引擎不支持空间索引。因此,我使用 MyISAM 表创建了一个辅助表来存储地点的地理位置坐标。这是 Place_GPS 表:

class m141025_213611_create_place_gps_table extends Migration{  public function up()  {      $tableOptions = null;      if ($this->db->driverName === 'mysql') {          $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=MyISAM';      }      $this->createTable('{{%place_gps}}', [          'id' => Schema::TYPE_PK,          'place_id' => Schema::TYPE_INTEGER.' NOT NULL',          'gps'=>'POINT NOT NULL',      ], $tableOptions);      $this->execute('create spatial index place_gps_gps on '.'{{%place_gps}}(gps);');      $this->addForeignKey('fk_place_gps','{{%place_gps}}' , 'place_id', '{{%place}}', 'id', 'CASCADE', 'CASCADE');  }

登录后复制

请注意,它通过 place_id 与 Place 表相关。地点的位置只是 GPS 坐标,或 MySQL POINT。

参与者表

会议参与者存储在名为“参与者”的连接表中。他们通过 meeting_id 加入会议表,并通过 participant_id 加入用户表。如果我们希望每次会议有多个会议参与者,此表将在将来实现这一点。

class m141025_215701_create_participant_table extends Migration{  public function up()  {      $tableOptions = null;      if ($this->db->driverName === 'mysql') {          $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';      }      $this->createTable('{{%participant}}', [          'id' => Schema::TYPE_PK,          'meeting_id' => Schema::TYPE_INTEGER.' NOT NULL',          'participant_id' => Schema::TYPE_BIGINT.' NOT NULL',          'invited_by' => Schema::TYPE_BIGINT.' NOT NULL',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_participant_meeting', '{{%participant}}', 'meeting_id', '{{%meeting}}', 'id', 'CASCADE', 'CASCADE');      $this->addForeignKey('fk_participant_participant', '{{%participant}}', 'participant_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');      $this->addForeignKey('fk_participant_invited_by', '{{%participant}}', 'invited_by', '{{%user}}', 'id', 'CASCADE', 'CASCADE');        }

登录后复制

其他相关会议桌

还有其他几个表格可以帮助定义我们的会议计划选项。

会议时间表

此表包含按开始时间(时间戳)列出的所有建议会议时间(和日期)。 Suggested_by 显示谁建议的时间。而status决定是否选择会议时间。

      $this->createTable('{{%meeting_time}}', [          'id' => Schema::TYPE_PK,          'meeting_id' => Schema::TYPE_INTEGER.' NOT NULL',          'start' => Schema::TYPE_INTEGER.' NOT NULL',          'suggested_by' => Schema::TYPE_BIGINT.' NOT NULL',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_meeting_time_meeting', '{{%meeting_time}}', 'meeting_id', '{{%meeting}}', 'id', 'CASCADE', 'CASCADE');      $this->addForeignKey('fk_participant_suggested_by', '{{%meeting_time}}', 'suggested_by', '{{%user}}', 'id', 'CASCADE', 'CASCADE');      

登录后复制

集合地点表

此表显示了为会议建议的地点:

$this->createTable('{{%meeting_place}}', [          'id' => Schema::TYPE_PK,          'meeting_id' => Schema::TYPE_INTEGER.' NOT NULL',          'place_id' => Schema::TYPE_INTEGER.' NOT NULL',          'suggested_by' => Schema::TYPE_BIGINT.' NOT NULL',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_meeting_place_meeting', '{{%meeting_place}}', 'meeting_id', '{{%meeting}}', 'id', 'CASCADE', 'CASCADE');      $this->addForeignKey('fk_meeting_place_place', '{{%meeting_place}}', 'place_id', '{{%place}}', 'id', 'CASCADE', 'CASCADE');      $this->addForeignKey('fk_meeting_suggested_by', '{{%meeting_place}}', 'suggested_by', '{{%user}}', 'id', 'CASCADE', 'CASCADE');     

登录后复制

会议日志表

此表记录特定会议的所有添加和更改的历史记录。会议安排期间采取的每个操作都会被记录下来,以提供与会议相关的事件的时间历史记录。它将帮助用户查看一段时间内会议的所有更改的记录,并且还可能帮助我们进行开发调试。

$this->createTable('{{%meeting_log}}', [          'id' => Schema::TYPE_PK,          'meeting_id' => Schema::TYPE_INTEGER.' NOT NULL',          'action' => Schema::TYPE_INTEGER.' NOT NULL',          'actor_id' => Schema::TYPE_BIGINT.' NOT NULL',          'item_id' => Schema::TYPE_INTEGER.' NOT NULL',          'extra_id' => Schema::TYPE_INTEGER.' NOT NULL',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_meeting_log_meeting', '{{%meeting_log}}', 'meeting_id', '{{%meeting}}', 'id', 'CASCADE', 'CASCADE');      $this->addForeignKey('fk_meeting_log_actor', '{{%meeting_log}}', 'actor_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');

登录后复制

会议记录表

用户在对会议进行更改时可以来回发送简短的注释。该表记录了这些注释。

$this->createTable('{{%meeting_note}}', [          'id' => Schema::TYPE_PK,          'meeting_id' => Schema::TYPE_INTEGER.' NOT NULL',          'posted_by' => Schema::TYPE_BIGINT.' NOT NULL DEFAULT 0',          'note' => Schema::TYPE_TEXT.' NOT NULL DEFAULT ""',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_meeting_note_meeting', '{{%meeting_note}}', 'meeting_id', '{{%meeting}}', 'id', 'CASCADE', 'CASCADE');      $this->addForeignKey('fk_meeting_note_posted_by', '{{%meeting_note}}', 'posted_by', '{{%user}}', 'id', 'CASCADE', 'CASCADE');     

登录后复制

其他相关用户表

有几个表可以扩展用户定义。

好友表

这是一个索引表,列出了每个用户的好友。它还跟踪他们是否是最喜欢的朋友以及他们举行的会议数量。这可能有助于简化调度体验,例如首先显示最喜欢的或经常的朋友。

$this->createTable('{{%friend}}', [          'id' => Schema::TYPE_PK,          'user_id' => Schema::TYPE_BIGINT.' NOT NULL',          'friend_id' => Schema::TYPE_BIGINT.' NOT NULL',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'number_meetings' => Schema::TYPE_INTEGER . ' NOT NULL DEFAULT 0',          'is_favorite' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_friend_user_id', '{{%friend}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');           $this->addForeignKey('fk_friend_friend_id', '{{%friend}}', 'friend_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');     

登录后复制

用户位置表

这是用户喜欢见面或过去见过的地点的索引表。我们将在此处跟踪该用户最喜欢的地点和举行的会议数量。 is_special 字段将指示某个地点是用户自己的家、办公室或会议地点。

$this->createTable('{{%user_place}}', [          'id' => Schema::TYPE_PK,          'user_id' => Schema::TYPE_BIGINT.' NOT NULL',          'place_id' => Schema::TYPE_INTEGER.' NOT NULL',          'is_favorite' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'number_meetings' => Schema::TYPE_INTEGER . ' NOT NULL DEFAULT 0',          'is_special' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'note' => Schema::TYPE_STRING . ' NOT NULL',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_user_place_user', '{{%user_place}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');           $this->addForeignKey('fk_user_place_place', '{{%user_place}}', 'place_id', '{{%place}}', 'id', 'CASCADE', 'CASCADE');     

登录后复制

用户联系表

此表提供特定用户的联系信息,例如电话号码、Skype 地址以及与在这些地方联系用户相关的任何注释。

 $this->createTable('{{%user_contact}}', [          'id' => Schema::TYPE_PK,          'user_id' => Schema::TYPE_BIGINT.' NOT NULL',          'contact_type' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'info' => Schema::TYPE_STRING . ' NOT NULL',          'details' => Schema::TYPE_TEXT . ' NOT NULL',          'status' => Schema::TYPE_SMALLINT . ' NOT NULL DEFAULT 0',          'created_at' => Schema::TYPE_INTEGER . ' NOT NULL',          'updated_at' => Schema::TYPE_INTEGER . ' NOT NULL',      ], $tableOptions);      $this->addForeignKey('fk_user_contact_user', '{{%user_contact}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');     

登录后复制

为了简单起见,我现在将跳过会议模板架构。而且我还没有设计与收入相关的功能。这样做的主要原因是,我目前有很多工作要做,以运行核心功能集并完成本教程系列的前几集。然而,这是一个值得教育的时刻。这是一个很好的例子,说明企业家的资源有限,专注于核心功能,但没有“意识到”创收也是一个核心功能。因为我相信我最初可以在没有收入的情况下启动 Meeting Planner,所以这是我目前能够做出的妥协。

运行数据库迁移

既然您对我们的数据库架构和 Active Record 迁移有了更多的背景知识,那么让我们运行其余部分:

cd ~/Sites/mp./yii migrate/up all

登录后复制

您应该看到类似这样的内容:

Yii Migration Tool (based on Yii v2.0.0)Total 14 new migrations to be applied:    m141025_212656_create_meeting_table    m141025_213610_create_place_table    m141025_213611_create_place_gps_table    m141025_215701_create_participant_table    m141025_215833_create_meeting_time_table    m141025_220016_create_meeting_place_table    m141025_220133_create_meeting_log_table    m141025_220524_create_friend_table    m141025_220923_create_user_place_table    m141025_221627_create_meeting_note_table    m141025_221902_create_user_contact_table    m141025_222213_create_template_table    m141025_222431_create_template_time_table    m141025_222531_create_template_place_tableApply the above migrations? (yes|no) [no]:yes*** applying m141025_212656_create_meeting_table    > create table {{%meeting}} ... done (time: 0.124s)    > add foreign key fk_meeting_owner: {{%meeting}} (owner_id) references {{%user}} (id) ... done (time: 0.307s)*** applied m141025_212656_create_meeting_table (time: 0.434s)*** applying m141025_213610_create_place_table    > create table {{%place}} ... done (time: 0.091s)    > add foreign key fk_place_created_by: {{%place}} (created_by) references {{%user}} (id) ... done (time: 0.114s)*** applied m141025_213610_create_place_table (time: 0.206s)*** applying m141025_213611_create_place_gps_table    > create table {{%place_gps}} ... done (time: 0.120s)    > execute SQL: create spatial index place_gps_gps on {{%place_gps}}(gps); ... done (time: 0.114s)    > add foreign key fk_place_gps: {{%place_gps}} (place_id) references {{%place}} (id) ... done (time: 0.112s)*** applied m141025_213611_create_place_gps_table (time: 0.347s)*** applying m141025_215701_create_participant_table    > create table {{%participant}} ... done (time: 0.100s)    > add foreign key fk_participant_meeting: {{%participant}} (meeting_id) references {{%meeting}} (id) ... done (time: 0.138s)    > add foreign key fk_participant_participant: {{%participant}} (participant_id) references {{%user}} (id) ... done (time: 0.112s)    > add foreign key fk_participant_invited_by: {{%participant}} (invited_by) references {{%user}} (id) ... done (time: 0.149s)*** applied m141025_215701_create_participant_table (time: 0.500s)*** applying m141025_215833_create_meeting_time_table    > create table {{%meeting_time}} ... done (time: 0.142s)    > add foreign key fk_meeting_time_meeting: {{%meeting_time}} (meeting_id) references {{%meeting}} (id) ... done (time: 0.148s)    > add foreign key fk_participant_suggested_by: {{%meeting_time}} (suggested_by) references {{%user}} (id) ... done (time: 0.122s)*** applied m141025_215833_create_meeting_time_table (time: 0.413s)*** applying m141025_220016_create_meeting_place_table    > create table {{%meeting_place}} ... done (time: 0.120s)    > add foreign key fk_meeting_place_meeting: {{%meeting_place}} (meeting_id) references {{%meeting}} (id) ... done (time: 0.125s)    > add foreign key fk_meeting_place_place: {{%meeting_place}} (place_id) references {{%place}} (id) ... done (time: 0.135s)    > add foreign key fk_meeting_suggested_by: {{%meeting_place}} (suggested_by) references {{%user}} (id) ... done (time: 0.137s)*** applied m141025_220016_create_meeting_place_table (time: 0.518s)*** applying m141025_220133_create_meeting_log_table    > create table {{%meeting_log}} ... done (time: 0.109s)    > add foreign key fk_meeting_log_meeting: {{%meeting_log}} (meeting_id) references {{%meeting}} (id) ... done (time: 0.126s)    > add foreign key fk_meeting_log_actor: {{%meeting_log}} (actor_id) references {{%user}} (id) ... done (time: 0.113s)*** applied m141025_220133_create_meeting_log_table (time: 0.348s)*** applying m141025_220524_create_friend_table    > create table {{%friend}} ... done (time: 0.109s)    > add foreign key fk_friend_user_id: {{%friend}} (user_id) references {{%user}} (id) ... done (time: 0.125s)    > add foreign key fk_friend_friend_id: {{%friend}} (friend_id) references {{%user}} (id) ... done (time: 0.102s)*** applied m141025_220524_create_friend_table (time: 0.337s)*** applying m141025_220923_create_user_place_table    > create table {{%user_place}} ... done (time: 0.109s)    > add foreign key fk_user_place_user: {{%user_place}} (user_id) references {{%user}} (id) ... done (time: 0.137s)    > add foreign key fk_user_place_place: {{%user_place}} (place_id) references {{%place}} (id) ... done (time: 0.114s)*** applied m141025_220923_create_user_place_table (time: 0.360s)*** applying m141025_221627_create_meeting_note_table    > create table {{%meeting_note}} ... done (time: 0.109s)    > add foreign key fk_meeting_note_meeting: {{%meeting_note}} (meeting_id) references {{%meeting}} (id) ... done (time: 0.125s)    > add foreign key fk_meeting_note_posted_by: {{%meeting_note}} (posted_by) references {{%user}} (id) ... done (time: 0.101s)*** applied m141025_221627_create_meeting_note_table (time: 0.337s)*** applying m141025_221902_create_user_contact_table    > create table {{%user_contact}} ... done (time: 0.098s)    > add foreign key fk_user_contact_user: {{%user_contact}} (user_id) references {{%user}} (id) ... done (time: 0.125s)*** applied m141025_221902_create_user_contact_table (time: 0.225s)*** applying m141025_222213_create_template_table    > create table {{%template}} ... done (time: 0.108s)    > add foreign key fk_template_owner: {{%template}} (owner_id) references {{%user}} (id) ... done (time: 0.171s)*** applied m141025_222213_create_template_table (time: 0.281s)*** applying m141025_222431_create_template_time_table    > create table {{%template_time}} ... done (time: 0.111s)    > add foreign key fk_template_time_template: {{%template_time}} (template_id) references {{%template}} (id) ... done (time: 0.114s)*** applied m141025_222431_create_template_time_table (time: 0.226s)*** applying m141025_222531_create_template_place_table    > create table {{%template_place}} ... done (time: 0.099s)    > add foreign key fk_template_place_template: {{%template_place}} (template_id) references {{%template}} (id) ... done (time: 0.103s)    > add foreign key fk_template_place_place: {{%template_place}} (place_id) references {{%place}} (id) ... done (time: 0.101s)*** applied m141025_222531_create_template_place_table (time: 0.304s)Migrated up successfully.

登录后复制

同样,当我们在生产中安装 Meeting Planner 时,我们也将使用迁移来构建初始数据库。无需导出和导入 SQL 文件,这些文件可能会因我们跨环境使用的版本不同而损坏。

注册管理用户

在我们继续之前,您需要将自己注册为管理用户。单击工具栏中的注册链接,只需注册该应用程序即可。

使用 PHP 设计初创公司的数据库并概述功能需求

如果成功,当您返回主页时,您将看到工具栏指示您的登录状态.

使用 PHP 设计初创公司的数据库并概述功能需求

这些表单和应用逻辑都包含在 Yii 的高级应用模板中。

使用 Yii 的 Gii 构建脚手架

现在我们可以构建脚手架来支持常见的创建、读取、更新和删除操作 (CRUD) 的模型视图控制器代码。

我们将使用 Gii(Yii 令人惊叹的自动代码生成器)来构建许多基本框架代码。这个名字可能很愚蠢,但它非常强大并且是 Yii 开发的核​​心。我们将从会议和地点开始。

使用 Gii

将浏览器指向 http://localhost:8888/mp/gii。你应该看到这个:

使用 PHP 设计初创公司的数据库并概述功能需求

生成模型

使用 Gii 构建时,通常从每个表的模型生成器开始。在使用模型生成器之前,您必须先运行迁移以在数据库中创建表,就像我们上面所做的那样。 Gii 使用 SQL 表定义为您的模型生成代码。

使用 PHP 设计初创公司的数据库并概述功能需求

让我们使用模型生成器为会议桌生成模型代码。代码已在您的 Github 存储库中生成,但您可以随意再次运行这些练习。 Gii 将为您预览并可选择覆盖代码。

按如下所示为会议模型填写模型生成器:

使用 PHP 设计初创公司的数据库并概述功能需求

然后,生成 Place 模型:

使用 PHP 设计初创公司的数据库并概述功能需求

Gii 非常令人惊奇——基于我们的表定义,它生成了大量的逻辑。

在 /mp/frontend/models/Meeting.php 模型中,您将看到自动生成的属性标签:

    public function attributeLabels()    {        return [            'id' => 'ID',            'owner_id' => 'Owner ID',            'meeting_type' => 'Meeting Type',            'message' => 'Message',            'status' => 'Status',            'created_at' => 'Created At',            'updated_at' => 'Updated At',        ];    }

登录后复制

它为表单生成字段验证规则:

    public function rules()    {        return [            [['owner_id', 'message', 'created_at', 'updated_at'], 'required'],            [['owner_id', 'meeting_type', 'status', 'created_at', 'updated_at'], 'integer'],            [['message'], 'string']        ];    }

登录后复制

它会生成数据库关系 – 以下是一些示例:

/* @property User $owner * @property MeetingLog[] $meetingLogs * @property MeetingNote[] $meetingNotes * @property MeetingPlace[] $meetingPlaces * @property MeetingTime[] $meetingTimes * @property Participant[] $participants*//**     * @return yiidbActiveQuery     */    public function getMeetingLogs()    {        return $this->hasMany(MeetingLog::className(), ['meeting_id' => 'id']);    }    /**     * @return yiidbActiveQuery     */    public function getMeetingNotes()    {        return $this->hasMany(MeetingNote::className(), ['meeting_id' => 'id']);    }    /**     * @return yiidbActiveQuery     */    public function getMeetingPlaces()    {        return $this->hasMany(MeetingPlace::className(), ['meeting_id' => 'id']);    }

登录后复制

生成CRUD

现在,我们可以使用 CRUD 生成器来构建用于创建、读取、更新和删除操作的代码。

访问 CRUD 生成器并为会议创建它。请注意,前端是用户将看到的 Yii 应用程序。

使用 PHP 设计初创公司的数据库并概述功能需求

当您点击预览时,您应该会看到如下内容:

使用 PHP 设计初创公司的数据库并概述功能需求

当您点击生成时,您应该会看到以下结果:

使用 PHP 设计初创公司的数据库并概述功能需求

接下来,对地点重复上述过程。

现在,您实际上可以浏览我们网站上的会议和地点,以查看实际生成的代码。将浏览器指向 http://localhost:8888/mp/meeting。它应该看起来像这样:

使用 PHP 设计初创公司的数据库并概述功能需求

如果您注册了帐户,则应该能够创建会议。请注意,Gii 不知道我们的代码应管理的字段和用户要提供的字段之间的区别。我们将在接下来的教程中清理这些内容。目前,您需要为 owner_id 输入整数(使用 1 – 这是第一个登录的用户)、meeting_type、status、created_at 和 updated_at:

使用 PHP 设计初创公司的数据库并概述功能需求

创建几次会议后,会议索引页面将如下所示:

p>

使用 PHP 设计初创公司的数据库并概述功能需求

结合 Gii 和 Yii 的强大功能,可以比其他方式更快地构建 Web 应用程序。令人惊奇的是,只需一个数据库表结构和一段迁移代码,我们就可以轻松使用 Bootstrap 响应式构建的工作控制器和表单。

下一步是什么?

我希望您对数据库和 Gii 演练感兴趣。本系列的下一篇文章将重点介绍围绕地点构建功能。它将介绍如何使用 Google 地方信息、Google 地图和 HTML5 地理定位来构建 Meeting Planner 所需的功能。如果您想先了解一下这些主题,我编写了一个相关教程:如何使用 Zillow Neighborhood Maps 和 HTML5 Geolocation。

请随时在下面添加您的问题和评论;我一般都会参与讨论。您还可以通过 Twitter @reifman 联系我或直接给我发送电子邮件。

相关链接

使用 Yii2 编程:入门Yii 框架简介

以上就是使用 PHP 设计初创公司的数据库并概述功能需求的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/1703368.html

(0)
上一篇 2025年2月19日 15:05:45
下一篇 2025年2月19日 15:06:04

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 7个php字符串处理函数有哪些

    7个php字符串处理函数有strlen()、strpos()、substr()、str_replace()、strtolower()、strtoupper()、trim()等。详细介绍:1、strlen(),用于获取字符串的长度;2、str…

    2025年2月23日
    100
  • PHP后天搭建有哪些疑难杂症

    疑难杂症有环境配置问题、依赖关系问题、数据库连接问题、文件路径问题、安全性问题、性能优化问题、调试和日志问题、扩展和定制问题等。详细说明:1、环境配置问题,包括安装正确的PHP版本、配置PHP.ini文件、设置正确的路径和权限等;2、依赖关…

    2025年2月23日
    100
  • php中标识符允许出现的符号有哪些

    php中标识符允许出现的符号有字母、数字、下划线和中文字符。详细介绍:1、字母和数字,标识符可以由字母和数字组成,它们可以以字母开头,后面可以跟随任意数量的字母、数字或下划线;2、下划线,标识符可以包含下划线,但不能以下划线开头;3、中文字…

    2025年2月23日
    100
  • php常用的第三方类库有哪些

    php常用的第三方类库有Laravel、Symfony、Guzzle、PHPUnit、Monolog、Swift Mailer、PHPExcel、Carbon、Doctrine、PHPMailer等。详细介绍:1、Laravel是一个流行的…

    2025年2月23日
    100
  • php将字符串拆分成数组有哪些方法

    方法有:1、explode()函数,可以将字符串按指定的分隔符拆分成数组;2、str_split()函数,可以将字符串拆分成单个字符的数组;3、preg_split()函数,可以根据正则表达式将字符串拆分成数组;4、sscanf()函数,可…

    2025年2月23日
    100
  • php第三方聊天室接口对接有哪些方法

    方法有:1、HTTP请求,可以通过PHP的curl库或者file_get_contents()函数发送HTTP请求来与聊天室接口进行通信;2、WebSocket协议,可以使用PHP的WebSocket库或者第三方库来与聊天室接口进行对接;3…

    2025年2月23日
    100
  • php用于哪些工作中

    需要使用PHP的工作有Web开发、CMS开发、电子商务网站开发、服务器端脚本编程和API开发等领域。详细介绍:1、Web开发,PHP的灵活性和易于学习的特点使得它成为了Web开发人员的首选语言之一;2、CMS开发,PHP提供了丰富的功能和强…

    2025年2月23日
    100
  • php人员需要做哪些手续

    php人员需要做的手续有发布招聘广告、筛选简历、面试候选人、薪资谈判和签订合同等。详细介绍:1、发布招聘广告,招聘广告应该清楚地说明企业对PHP人员的要求,包括技术能力、工作经验和学历要求等;2、筛选简历,仔细阅读每个简历,评估候选人的技能…

    2025年2月23日
    100
  • php可以开发程序有哪些

    可以开发程序有网站开发、内容管理系统、电子商务平台、社交网络、在线论坛和社区、API开发、数据分析和可视化等等。详细介绍:1、网站开发,PHP的灵活性和强大的功能使得开发人员可以轻松构建复杂的网站,并实现各种功能,如用户注册、登录、数据存储…

    2025年2月23日
    100
  • php8更新了哪些

    php8更新了JIT 编译器、 类型系统改进、属性改进、异常改进、函数改进、其他改进等等内容。详细介绍:1、JIT 编译器,PHP8引入了一个全新的JIT编译器,它可以将PHP代码编译成本地机器码,从而提高执行速度;2、类型系统改进,PHP…

    2025年2月23日
    100

发表回复

登录后才能评论