安装完mongodb的插件,就可以使用mongodb了,但是,在插入和更新mongodb的信息的时候,active record 会因为没有类型,
不能对字段自动的强制转换类型,下面是强制转换类型
common\extensions\mongodb\IActiveRecord.php
<?php
namespace 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.得到递增id
public 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:
<?php
namespace 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(){
# 不要定义 _id
return [
'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();
保存完成后,看结构:
可以看到结果被强制转换了。
$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']); 可以转换时间格式。