3. Magento2 中模型 CRUD

Magento 2 模块开发基础部分 - 目录

通过 Magento 2 的模型可以很容易管理数据库数据,不需要写很多代码来实现基础的 CRUD。CRUD代表新增(create)、读取(read)、更新(update)和删除(delete)。本节主要了解如何创建数据表、模型(model)、资源模型(resource model)和资源模型集合(resource model collection)及数据库的相关操作。

开始之前先定好要用到的数据表,表名 aqrun_helloworld_post ,字段如下:

  • post_id - 文章的唯一标识ID
  • name - 文章标题
  • url_key - URL
  • post_content - 文章正文
  • tags - 标签
  • status - 状态
  • featured_image - 图片
  • created_at - 创建时间
  • updated_at - 更新时间

创建模型有如下步骤:

  • 1 安装脚本(Setup Script)
  • 2 创建模型(Model)
  • 3 创建资源模型(Resource Model)
  • 4 创建资源模型集合(Resource Model Collection)
  • 5 工厂对象(Factory Object)

第一步 添加安装脚本

首先为我们的模型创建数据表,需要增加安装配置文件

app/code/Aqrun/HelloWorld/Setup/InstallSchema.php

这个文件会在模块安装时执行一次。使用如下代码创建上面的文章表

<?php
namespace Aqrun\HelloWorld\Setup;

use Magento\Framework\DB\Ddl\Table;

class InstallSchema implements \Aqrun\Framework\Setup\InstallSchemaInterface
{
    public function install(
        \Magento\Framework\Setup\SchemaSetupInterface $setup,
        \Magento\Framework\Setup\ModuleContextInterface $context
    ){
        $installer = $setup;
        $installer->startSetup();
        if (!$intaller->tableExists('aqrun_helloworld_post')) {
            $installer->getConnection()->newTable(
                $installer->getTable('aqrun_helloworld_post')
            )->addColumn(
                'post_id',
                Table::TYPE_INTERGER,
                null,
                [
                    'identity' => true,
                    'nllable' => false,
                    'primary' => true,
                    'unsigned' => true,
                ],
                'Post ID'
            )->addColumn(
                'name',
                Table::TYPE_TEXT,
                255,
                ['nullable' => false],
                'Post name'
            )->addColumn(
                'url_key',
                Table::TYPE_TEXT,
                255,
                ['nullable' => false],
                'Post URL Key'
            )->addColumn(
                'post_content',
                Table::TYPE_TEXT,
                '64k',
                [],
                'Post Content'
            )->addColumn(
                'tags',
                Table::TYPE_TEXT,
                255,
                [],
                'Post Tags'
            )->addColumn(
                'status',
                Table::TYPE_INTEGER,
                1,
                [],
                'Post Status'
            )->addColumn(
                'featured_image',
                Table::TYPE_TEXT,
                255,
                [],
                'Post Featured Image'
            )->addColumn(
                'created_at',
                Table::TYPE_TIMESTAMP,
                null,
                ['nullable' => false, 'default' => Table::TIMESTAMP_INIT],
                'Created At'
            )->addColumn(
                'updated_at',
                Table::TYPE_TIMESTAMP,
                null,
                ['nullable' => false, 'default' => Table::TIMESTAMP_INIT_UPDATE],
                'Updated At'
            )->setComment('Post Table');

            $installer->getConnection()->createTable($table);
            $installer->getConnection()->addIndex(
                $installer->getTable('aqrun_helloworld_post'),
                $setup->getIdxName(
                    $installer->getTable('mageplaza_helloworld_post'),
                    ['name', 'url_key', 'post_content', 'tags', 'featured_image'],
                    \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                ),
                ['name','url_key','post_content','tags','featured_image',],
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
            );

        } //if

        $installer->endSetup();

    }
}

以上代码实现如何创建数据表。要注意的是系统会在模块第一次安装时自动运行这个文件。如果模块已经安装,这时需要更新模块就要把创建表的代码写在 UpgradeSchema.php 文件,并且修改 module.xml 文件的 setup_version 安装版本号值,改大一些,app/code/Aqrun/HelloWorld/etc/module.xml

内容如:

文件: app/code/Aqrun/HelloWorld/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Aqrun_HelloWorld" setup_version="1.1.0">
    </module>
</config>

文件: app/code/Aqrun/HelloWorld/Setup/UpgradeSchema.php

namespace Aqrun\HelloWorld\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;

class UpgradeSchema implements UpgradeSchemaInterface
{
    public function upgrade(
        SchemaSetupInterface $setup,
        ModuleContextInterface $context
    ){
        $installer = $setup;
        $installer->startSetup();
        if (version_compare($context->getVersion(), '1.1.0', '<')) {
            if (!$installer->tableExists('aqrun_helloworld_post')) {
                $table = $installer->getConnection()->newTable(
                    $installer->getTable('aqrun_helloworld_post')
                )->addColumn(
                    'post_id',
                    Table::TYPE_INTERGER,
                    null,
                    [
                        'identity' => true,
                        'nllable' => false,
                        'primary' => true,
                        'unsigned' => true,
                    ],
                    'Post ID'
                )->addColumn(
                    'name',
                    Table::TYPE_TEXT,
                    255,
                    ['nullable' => false],
                    'Post name'
                )->addColumn(
                    'url_key',
                    Table::TYPE_TEXT,
                    255,
                    ['nullable' => false],
                    'Post URL Key'
                )->addColumn(
                    'post_content',
                    Table::TYPE_TEXT,
                    '64k',
                    [],
                    'Post Content'
                )->addColumn(
                    'tags',
                    Table::TYPE_TEXT,
                    255,
                    [],
                    'Post Tags'
                )->addColumn(
                    'status',
                    Table::TYPE_INTEGER,
                    1,
                    [],
                    'Post Status'
                )->addColumn(
                    'featured_image',
                    Table::TYPE_TEXT,
                    255,
                    [],
                    'Post Featured Image'
                )->addColumn(
                    'created_at',
                    Table::TYPE_TIMESTAMP,
                    null,
                    ['nullable' => false, 'default' => Table::TIMESTAMP_INIT],
                    'Created At'
                )->addColumn(
                    'updated_at',
                    Table::TYPE_TIMESTAMP,
                    null,
                    ['nullable' => false, 'default' => Table::TIMESTAMP_INIT_UPDATE],
                    'Updated At'
                )->setComment('Post Table');

                $installer->getConnection()->createTable($table);
                $installer->getConnection()->addIndex(
                    $installer->getTable('aqrun_helloworld_post'),
                    $setup->getIdxName(
                        $installer->getTable('aqrun_helloworld_post'),
                        ['name', 'url_key', 'post_content', 'tags', 'featured_image'],
                        \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                    ),
                    ['name','url_key','post_content','tags','featured_image',],
                    \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                );
            } // if not table exists
        }// if version compare
    } //

}

然后运行更新的命令:

php bin/magento setup:upgrade

更新完成可以继续执行静态内容发布命令:

php bin/magento setup:static-content:deploy

现在数据库中应该就有 aqrun_helloworld_post 数据表,字段和上面一样。如果没有创建成功,或许是由于在你添加内容到 InstallSchema.php 文件前运行过上面的命令。这时需要手动清除数据表信息,在 setup_module 表找到并删除 aqrun_helloworld_post 这一行数据。然后再运行上面的命令试下。

InstallSchema.php 文件是用来创建数据表结构的, 如果要在安装时添加数据,需要使用 InstallData.php 文件:

app/code/Aqrun/HelloWorld/Setup/InstallData.php

如何使用可以到系统找如下文件查看:

  • vendor/magento/module-tax/Setup/InstallData.php
  • vender/magento/module-customer/Setup/InstallData.php
  • vendor/magento/module-catalog/Setup/InstallData.php

上面提到这些安装文件是模块第一次安装时使用的,如果要修改数据表并更新模块,要使用 UpgradeSchema.phpUpgradeData.php

第二步 创建模型

模型是MVC架构中很大一坨内容。Magento 2 模型有很多不同的功能如数据管理、安装或更新模块。这里只讨论数据的CRUD操作。我们需要创建模型、资源模型、资源模型集合来管理 aqrun_helloworld_post 表的数据。

创建模型文件:

app/code/Aqrun/HelloWorld/Model/Post.php

内容:

<?php
namespace Aqrun\HelloWorld\Model;

use Magento\Framework\Model\AbstractModel;
use Magento\Framework\DataObject\IdentityInterface;

class Post extends AbstractModel implements IdentityInterface
{
    const CACHE_TAG = 'aqrun_helloworld_post';
    protected $_cacheTag = 'aqrun_helloworld_post';
    protected $_eventPrefix = 'aqrun_helloworld_post';

    protected function _construct()
    {
        $this->_init('Aqrun\HelloWorld\Model\ResourceModel\Post');
    }

    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId()];
    }

    public function getDefaultValues()
    {
        $values = [];
        return $values;
    }
}

模型继承自 AbstractModelMagento\Framework\Model\AbstractModel 并实现接口 Magento\Framework\DataObject\IdentityInterfaceIdentityInterface 强制模型类必须实现返回模型唯一ID的 getIdentities() 方法。如果在数据库内容修改之后需要缓存清除之类的操作来显示前端内容就必须使用这个接口。

__construct() 构造方法在模型初始化时会执行,每一个CURD模型都必须使用构造方法调用 _init() 方法。_init() 方法定义了实际获取数据库信息的资源模型。如代码我们定义了资源模型: `Aqrun\Post\Model\ResourceModel\Post'。最后是一些变量:

  • $_eventPrefix 触发事件时的前缀
  • $_eventObject 获取事件对象的名称
  • $_cacheTag 缓存用的唯一ID

第三步 创建资源模型

如你所见,模型文件包含所有数据库相关处理逻辑,并不运行实际的SQL操作,而这些操作是在资源模型中定义的。现在添加资源模型:app/code/Aqrun/HelloWorld/Model/ResourceModel/Post.php

代码:

namespace Aqrun\Helloworld\Model\ResourceModel;

class Post extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    public function __construct(
        \Magento、Framework\Model\ResouceModel\Db\Context $context
    ){
        parent::__construct($context);
    }

    protected function _construct()
    {
        $this->init('aqrun_helloworld_post', 'post_id');
    }
}

资源模型必须继承虚类 \Magento\Framework\Model\ResourceModel\Db\AbstractDb。这个类包含从数据库获取信息的功能逻辑。

和模型类一样,资源模型类必须有 __construct() 构造方法,这个方法会调用定义了数据表名和主键的 _init() 函数。上面代码我们的表是 aqrun_helloworld_post 主键为 post_id

第四步 创建资源模型集合 - 获取模型集合

模型集合可以看作是资源模型,但可以筛选和获取表数据的集合。集合模型类定义在:

app/code/Aqrun/HelloWorld/Model/ResourceModel/Post/Collection.php

代码:

<?php
namespace Aqrun\HelloWorld\Model\ResourceModel\Post;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    protected $_idFieldName = 'post_id';
    protected $_eventPrefix = 'aqrun_helloworld_post_collection';
    protected $_eventObject = 'post_collection';

    protected function _construct()
    {
        $this->_init(\Aqrun\HelloWorld\Model\Post::class, \Aqrun\HelloWorld\Model\ResourceModel\Post::class);
    }
}

集合类需要继承类: \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection 并且在构造函数初始化模型和资源模型。

第五步 工厂对象

我们已经实现了创建数据表、模型、资源模型、和集合。那如何使用他们呢?

这里讨论一下模型的工厂对象。我们知道面向对象里,工厂方法是用来初始化对象的,而在Magento,工厂对象也做同样的事。

工厂类名称是模型类名后面加上 'Factory' 关键字。所以我们的工厂类是 PostFactory。 我们不需要创建这个类,Magento系统可以自动生成。当Magento的对象管理器碰到 'Factory' 结尾的类名时,如果没有创建则会自动在 var/generation 目录生成。可以找到工厂类在:

var/generation/<vendor_name>/<module_name>/Model/ClassFactory.php

此例中,目录是:

var/generation/Aqrun/HelloWorld/Model/PostFactory.php

要实例化一个模型对象我们需要使用到构造函数的依赖注入获取工厂对象,然后使用工厂对象来实例化模型对象。如下代码我们在控制器调用模型获取数据:

app/code/Aqrun/HelloWorld/Controller/Index/Index.php

代码:

<?php
namespace Aqrun\HelloWorld\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
    protected $_pageFactory;
    protected $_postFactory;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $pageFactory,
        \Aqrun\HelloWorld\Model\PostFactory $postFactory
    ){
        $this->_pageFactory = $pageFactory;
        $this->_postFactory = $postFactory;
        return parent::__contruct($context);
    }

    public function execute()
    {
        $post = $this->_postFactory->create();
        $collection = $post->getCollection();
        foreach($collection as $item){
            echo '<pre>';
            print_r($item->getData());
            echo '</pre>';
        }
        exit();
        return $this->_pageFactory->create();
    }
}

如上控制器, PostFactory 对象会在构造函数创建,在 execute() 方法我们使用 $post = $this->_postFactory->create(); 来创建模型对象。

接下来可以使用数据库管理软件到 aqrun_helloworld_post 表添加2条假数据,测试模型是否正常工作。

添加完数据访问URL http://mage.dev/helloworld/index/index 确认添加的数据列表已经显示。

如果显示错误信息: Exception printing is disabled by default for security reasons 。可以到 var/report 目录检查错误日志。

模型相关就完结了,下一章节了解下视图:布局、区块、模板

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 理工寝室商店-微信小程序 疑问小结 当时在XAMMP下mysql目录下的bin下 php -v 不起作用.到ph...
    这个超人不会飞阿阅读 1,697评论 1 1
  • 原文地址:http://magenticians.com/12-design-patterns-magento M...
    jimxu阅读 1,167评论 0 1
  • 1、PHP语言的一大优势是跨平台,什么是跨平台?一、PHP基础: PHP的运行环境最优搭配为Apache+MySQ...
    __书山有路__阅读 1,479评论 0 15
  • 一. Java基础部分.................................................
    wy_sure阅读 3,805评论 0 11
  • 朝辞白帝彩云间 千里江陵一日还 两岸猿声啼不住 轻舟已过万重山 工作之余,一时兴起,放松一下心情,来,我们摆个沙盘...
    自由自在的白云阅读 432评论 0 0