新服务器在使用高版本的 PHP 和 mongod 扩展的时候,配合 thinkphp 开发网站应用的时候,需要做数据分页或者查询数据总数的时候需要使用 count()
方法,出现了报错:
BSON field 'count.query' is the wrong type 'array', expected type 'object'
故障原因在 think-mongo
版本,vendor/topthink/think-mongo/src/Builder.php
文件中,parseWhere
方法在做过滤条件初始化的时候,没有考虑周全,将数据类型定义为了数组。这里在返回的时候做一个判断,如果 $filter
为空,就重新定义为 stdClass
对象。可以参考以下代码
public function parseWhere( Query $query , $where ) {
if ( empty( $where ) ) {
$where=[];
}
$filter=[];
foreach ( $where as $logic=>$val ) {
foreach ( $val as $field=>$value ) {
if ( is_array( $value ) ) {
if ( key( $value ) !== 0 ) {
throw new Exception( 'where express error:'.var_export( $value , true ) );
}
$field=array_shift( $value );
} elseif ( !($value instanceof \Closure) ) {
throw new Exception( 'where express error:'.var_export( $value , true ) );
}
if ( $value instanceof \Closure ) {
// 使用闭包查询
$query=new Query( $this->connection );
call_user_func_array( $value , [ & $query ] );
$filter[ $logic ][]=$this->parseWhere( $query , $query->getOptions( 'where' ) );
} else {
if ( strpos( $field , '|' ) ) {
// 不同字段使用相同查询条件(OR)
$array=explode( '|' , $field );
foreach ( $array as $k ) {
$filter[ '$or' ][]=$this->parseWhereItem( $query , $k , $value );
}
} elseif ( strpos( $field , '&' ) ) {
// 不同字段使用相同查询条件(AND)
$array=explode( '&' , $field );
foreach ( $array as $k ) {
$filter[ '$and' ][]=$this->parseWhereItem( $query , $k , $value );
}
} else {
// 对字段使用表达式查询
$field=is_string( $field )?$field : '';
$filter[ $logic ][]=$this->parseWhereItem( $query , $field , $value );
}
}
}
}
$options=$query->getOptions();
if ( !empty( $options[ 'soft_delete' ] ) ) {
// 附加软删除条件
list( $field , $condition )=$options[ 'soft_delete' ];
$filter[ '$and' ][]=$this->parseWhereItem( $query , $field , $condition );
}
if (empty($filter)){ // 返回空对象
return new stdClass();
}
return $filter;
}