yii2 类似mongoose schema ,对mongodb 进行类型定义,以及强制转换

来源:互联网 发布:易语言文本替换源码 编辑:程序博客网 时间:2024/09/21 09:01


安装完mongodb的插件,就可以使用mongodb了,但是,在插入和更新mongodb的信息的时候,active record 会因为没有类型,

不能对字段自动的强制转换类型,下面是强制转换类型


common\extensions\mongodb\IActiveRecord.php

<?phpnamespace common\extensions\mongodb;use Yii;use yii\mongodb\ActiveRecord;use common\extensions\mongodb\IActiveRecord\TypeConvert;//use common\extensions\IActiveRecord;/** * ActiveRecord is the base class for classes representing Mongo documents in terms of objects. * * @author Paul Klimov <klimov.paul@gmail.com> * @since 2.0 */class IActiveRecord extends ActiveRecord{public $_is_insert;/*public function __construct(){$this->on(self::EVENT_AFTER_FIND,[$this,'afterFindData']);}public function afterFindData($event){$event->name = 'aaaaaaaaaaaaa';}*/# 1.将mongodb的时间转换成字符串 public static function getDateTime($dataOb,$format = 'Y-m-d H:i:s'){if($dataOb->sec){return  date($format, $dataOb->sec);}return $dataOb;}# 2.将mongodb的时间转换成字符串 public function getDate($dataOb,$format = 'Y-m-d'){if($dataOb->sec){return  date($format, $dataOb->sec);}return $dataOb;}# 3.返回属性定义public function attributes()    {        $attributes = [];$schema_columns = $this->schema_columns();foreach($schema_columns as $column => $data){ $attributes[] = $column;}$attributes[] = '_id';return $attributes;    }# 4.在保存前,强制进行类型转换,依赖于 schema_columns()函数对collection的字段类型定义。public function beforeSave($insert)    {        if (parent::beforeSave($insert)) {# 得到字段结构定义$columns =  $this->schema_columns();# 得到当前的值。$model_data =  $this->getSchemaData();# 如果是插入操作if($insert == self::EVENT_BEFORE_INSERT){$this->_is_insert = 1;# 生成当前的id  这个id 是当前通过 ids(colleciton)进行递增得来。$collection_name = $this->collectionName();$this->_id = $this->increament($collection_name);}else{}# 转换类型  进行类型强制转换。$data = TypeConvert::forceChangeColumnsType($columns,$model_data,$this->_is_insert);# 将强制转换类型后得到的值,重新进行赋值。foreach($data as $k_col => $l_colo_val){//echo $k_col;$this->$k_col = $l_colo_val;}return true;} else {return false;        }    }# 5.得到当前的属性值public function getSchemaData(){$attributes = $this->attributes();$arr = [];foreach($attributes as $attribute  ){$arr[$attribute] = $this->$attribute;}return $arr;}# 6.得到递增idpublic  function increament($tablename){$coll = Yii::$app->mongodb->getCollection("ids");$update = array('?inc'=>array('id'=>1));$query = array('name'=>$tablename);$command = array('findandmodify'=>'ids', 'update'=>$update,'query'=>$query, 'new'=>true, 'upsert'=>true);$result = $coll->mongoCollection->db->command($command);$id = $result['value']['id'];Global $current_mongo_id;$current_id = (int)$id->value;return $id;} /*public static function find()    {        return Yii::createObject(IActiveQuery::className(), [get_called_class()]);    }*/}

common\extensions\mongodb\IActiveRecord\TypeConvert.php

<?php/** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */namespace common\extensions\mongodb\IActiveRecord;use Yii;use yii\mongodb\ActiveRecord;/** * ActiveRecord is the base class for classes representing Mongo documents in terms of objects. * * @author Paul Klimov <klimov.paul@gmail.com> * @since 2.0 */class TypeConvert{public static $is_insert = 0;# 强制类型转换public static function forceChangeColumnsType($columns,$model_data,$is_insert=0){$result = [];if($is_insert){self::$is_insert = $is_insert;}foreach($columns as $column_name => $data){//echo $column_name."<br/>";//var_dump( $data);//echo "<br/>";if($column_value = $model_data[$column_name]){if(is_array($data)){$dd = self::isColumnsArray($data);if( $dd == 'arrayColumns'){$result[$column_name] = self::changeType($column_value,$data[0],1);}else  if( $dd == 'arrayContainChild'){foreach($column_value as $key=>$col_value){$k = (String)(new \MongoId());$result[$column_name][$k] = self::forceChangeColumnsType($data[0],$col_value);}}else{$result[$column_name] = self::forceChangeColumnsType($data,$column_value);}}else{$result[$column_name] = self::changeType($column_value,$data);}}}return $result;}# public static function isColumnsArray($data){$not_numeric = 1;$is_string  = 1;foreach($data as $k=>$v){if(!is_numeric($k)){$not_numeric = 0;}if(is_array($v)){$is_string  = 0;}}# 代表 仅仅一个数组,数组中含有的是字符串if($not_numeric && $is_string){return  'arrayColumns';# 数组中的变量,是数组,也就是说里面含有很多子数组。}else if($not_numeric && !$is_string){return 'arrayContainChild';}# 不是数组类型return 'notArray';}# 转换类型public static function changeType($column_value,$type,$is_array=0){if($is_array){$arr = [];if(is_array($column_value)){foreach($column_value as $key=>$v){if(self::$is_insert){$v = self::changeTypeData($v,$type);$k = (String)(new \MongoId());$arr[$k] = $v;}else{$v = self::changeTypeData($v,$type);$arr[$key] = $v;}}}return $arr;}else{return self::changeTypeData($column_value,$type);}}public static function changeTypeData($column_value,$type){$type = trim(strtolower($type));if($type == 'int'){$column_value = (int)$column_value;}else if ($type == 'string'){$column_value = (String)$column_value;}else if ($type == 'string'){$column_value = (String)$column_value;}else if ($type == 'float'){$column_value = (float)$column_value;}else if ($type == 'datetime'){$column_value = new \MongoDate(strtotime($column_value));}else if ($type == 'date'){$column_value = date('Y-m-d',strtotime($column_value));$column_value = new \MongoDate(strtotime($column_value));}else{}return $column_value;}}


使用demo

1.定义active record:

<?phpnamespace myapp\code\core\Erp\Sales\models;use common\extensions\mongodb\IActiveRecord; //  use myapp\code\core\Erp\Sales\models\Mongocustomer;class Mongocustomer extends IActiveRecord{# 定义collection name    public static function collectionName()    {        return 'mongo_customer';    }# 定义collection 各个字段的类型定义,在保存前进行类型转换public function schema_columns(){# 不要定义  _idreturn ['name' => 'String',  # String类型'email' => 'String','address' => 'String','status' => 'Int',# Int类型'age'=> 'Int','active'=> 'Int','image'=> ['media'=> 'String','created_at' => 'DateTime',#时间类型'gallery'=>  ['String'],# 字符串数组],'price'=> ['en_price' => 'float',  # float类型'fr_price' => 'float',],'created_at'=> 'datetime',  # datetime类型'custom_option' => [['name' => 'String','sort_order' => 'Int','is_required'=> 'Int','data'=> [['title' => ['en_title' => 'String','fr_title' => 'String','de_title' => 'String','ru_title' => 'String',],'price' => 'Float','sort_order' => 'Int',],],],]];}}

2.调用  插入:

$Mongocustomer = new Mongocustomer();$Mongocustomer->name = 1;$Mongocustomer->created_at = '2015-01-01';$Mongocustomer->custom_option = [['name' => 'color','sort_order' => '2',],['name' => 'size','data' => [['title' => ['en_title' => 'l','fr_title' => 'l',],'price' => '12.22',],['title' => ['en_title' => 'en_m','fr_title' => 'fr_m',],'price' => '13.22',],],],];$Mongocustomer->image = ['media' => 22,'gallery' => [11,22,33,44,55],];$Mongocustomer->save();

保存完成后,看结构:


可以看到结果被强制转换了。



调用2:查询

$data = Mongocustomer::find()->asArray()->all();foreach($data as $d){echo Mongocustomer::getDateTime($d['created_at']);echo "<br/>*********<br/>";}exit;

调用3:更新:

$dd = Mongocustomer::findOne(['_id'=>45]);$dd->name = 4444;$dd->save();var_dump($dd);exit;



结果:

1._id 是类似mysql的id递增方式

2.如果一个定义的没有key的数组,会增加生成的mongodb的_id

3.定义的字段都会强制转换。

4.Mongocustomer::getDateTime($d['created_at']);  可以转换时间格式。


0 0
原创粉丝点击