Yii2.0 数据库添加数据的技巧

版权声明:本文博客都可以转载,我写博客只是为了整理自己的思路和回报天天在百度上搜索到的技术解决方案的人们 https://blog.csdn.net/canlynetsky/article/details/74999224

我们以User表为例,假设User表就3个字段,id, username, password。
当PHP从浏览器接收POST数据后,Yii提供了一种推荐的如下方式:

方法一、load

首先要new User;
load方法的源码在:vendor/yiisoft/yii2/base/Model.php,786行左右(根据版本可能有差异),定义如下:
public function load( data, formName = null)
第一个参数 dataUser:username:admin,paafssword:adminPassword data中有以new User的User这个类相同的键,即“User”。
如果传递,则传递在 dataUer data中的有效数据在User这个键下面。另一方面,如果某一天new User改为new UserModel,我们不需要修改其它代码。
dataPOST _POST,yii中我们习惯用Yii::$app->request->post()。
而为什么一定要将给User表的数据存储到一个User的键下面呢?这是为了在一个页面提交过来的数据可以提供给多个表存储使用,比如可以从页面中传输user表和user_profile表存储的数据。
那么,当我们一个页面只管理一个表的时候,完全可以用这种方式。当然,在Yii框架中,如果开启了CSRF防跨站攻击,POST到php后台的数据就带有_csrf键,如果YII_DEBUG常量设置为TRUE了,网页会抛出异常的!所以,多一事不如少一事,yii框架就让我们坚决用”表名[字段名]”的方式给input做name吧。

$user = new User();
$data = Yii::$app->request->post();
if (!$user->load($data, 'User')) {
    $this->showErrorPage('提供的数据格式不正确!');
}
if (!$user->save()) {
    $this->showErrorPage(current($user->getFirstErrors()));
}

这种方式接收表单数据存储到数据库时,表单数据是如同:

['User' => [
    'username' => 'admin',
    'password' => 'admin',
]]

这种数据,也就是说,在页面表单中有如同下面的代码:

<form action="save.php" method="POST">
    <input type="text" name="User[username]" value="">
    <input type="password" name="User[password]" value="">
    <button type="submit">保存</button>
</form>

这种方式特别适合后台的编辑和保存,因为后台编辑保存数据往往比较单一,大多数针对同一个数据表。
但是,如果是用户注册、用户登记信息、提交订单等场景,就不那么好使了。因为后台要根据数据进行重组。
当然,如果整理好数据,也是可以做到的,但你必须删除掉该数组内不属于数据表字段的键名
但是万一表单提交过来的数据如果太少了怎么办?比如User表还有用户昵称字段nick必须提供,但是你还是希望保存用户提交过来的数据(即兼容保存,很多时候业务会在JS层做好用户必填字段的限制,但是后台就放宽松了很多,尤其是大表单)。
没关系,还是有办法的,我们可以利用Yii2.0自带的数据库操作:
参考:http://www.yiichina.com/doc/guide/2.0/db-active-record#

方法二、精确操作–只针对字段数极少的数据表

$user = new User();
$user->username = @$_POST['username'];
$user->password= @$_POST['password'];
if ($user->save()) {
    ...
}

这种方式是可以成功保存数据的,但是一定要保证nick有默认值比如空字符串,或者关闭MySQL的严格模式:

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

去掉STRICT_TRANS_TABLES,即可成功保存而不报错误。

但是如果字段数太多了,比如30多个,难道要写30多行代码吗(核对30个字段名有没有写对,真是崩溃)?如果数据表字段有增减,岂不是很麻烦?

没关系,我们还有办法:

方法四、setAttributes的不安全模式

$user = new User();
$data = Yii::$app->request->post();
$user->seAttributes($data['User'], false));
if (!$user->save()) {
    $this->showErrorPage(current($user->getFirstErrors()));
}

所以:
这里就要提到load方法的一个缺点了,它依赖于User.php这个Model的rules,如果rules里忘记增加某个字段的规则定义,无论定义其为required还是string数据类型,哪怕出现一个,也可以顺利load上值,如果一个都没有,比如username在rules里没出现,那么load以后,$user->username的值为NULL。所以,我们无论何时何地,一定要确保rules里对字段有齐全的定义。
但是:如果某个数据表可以给用户自定义字段呢?用户通过网页操作,给这个表增加字段后,我们总不能让用户生成一个Model吧?这时候,就必须用方法三。我们可以将那个setAllAttributes方法放到一个基类比如里面,让这个基类继承\yii\db\ActiveRecord,让我们所有通过gii创建的Model类继承这个Model(反正有命名空间):

<?php
namespace common\models;

class Model extends \yii\db\ActiveRecord {
    function loadData($data, $key) {
        $data = $key ? @$data[$key] : $data;
        if (!is_array($data)) {
            return false;
        }
        $this->setAttributes($data, false);
        return true;
    }
}

用法还是那样,只不过这次不依赖rules了:

$user = new User(); $data = Yii::$app->request->post(); if (!$user->loadData($data, 'User')) { $this->showErrorPage('提供的数据格式不正确!'); } if (!$user->save()) { $this->showErrorPage(current($user->getFirstErrors())); } 

猜你喜欢

转载自blog.csdn.net/canlynetsky/article/details/74999224