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

71 篇文章 0 订阅
31 篇文章 0 订阅


安装完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();

保存完成后,看结构:


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



调用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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值