/** * 获取当前类型的数据 * * @param OOP_ORM_Data $obj * @param $data * @param $compiled_data * @return mixed */ public function &get_data(OOP_ORM_Data $obj, &$data, &$compiled_data, &$compiled_raw_data) { $config = $this->config(); $fun = $config['func']; $args = $config['args']; foreach ($args as &$item) { if ($item === '$this') { $item = $obj; } elseif (is_string($item) && substr($item, 0, 7) === '$this->') { $key = substr($item, 7); $item = $obj->{$key}; } } if (count($fun) === 1) { $tmp_data = call_user_func_array($fun[0], $args); } else { if ($fun[0] === '$this') { $fun[0] = $obj; $tmp_data = $obj->__orm_callback('get_by_function_di', $fun, $args); } else { $tmp_data = call_user_func_array($fun, $args); } } if (false === $config['runtime']) { # 非实时运行 $compiled_data[$this->key] = $tmp_data; $compiled_raw_data[$this->key] = $tmp_data; } return $tmp_data; }
protected function format_field_value(OOP_ORM_Data $obj, &$data, $new_data, $format_type) { # 数据主键 $id = $obj->pk(','); # 这个是对应主表的表名称,它和元数据的 table_name 字段是对应的 $table = $obj->finder()->tablename(); # 这个是metadata所在的表名称 $my_table = $this->table_name; $meta_group = $this->meta_group; if (null === $new_data || '' === $new_data || array() === $new_data) { # 删除了 # 读取已经加载的所有元数据 $old_metadata = $obj->__orm_callback('get_metadata'); if (isset($old_metadata[$my_table][$meta_group])) { foreach ($old_metadata[$my_table][$meta_group] as $hash => $item) { # 遍历所有当前组的数据 if ($item['table_name'] === $table && $item['field_name'] === $this->field_name) { # 把当前字段的数据全部设置成 null 以便进行删除处理 $data[$my_table][$hash] = null; } } } return; } # 读取已经加载的所有元数据 $old_metadata = $obj->__orm_callback('get_metadata'); $old_item_data = array(); if (isset($old_metadata[$my_table][$meta_group])) { foreach ($old_metadata[$my_table][$meta_group] as $hash => $item) { # 把数据整理到一个数组里 if ($item['table_name'] === $table && $item['field_name'] === $this->field_name) { # 把当前字段的数据全部设置成 null 以便进行删除处理 $old_item_data[$hash] = $item; } } } # 读取新数据 if ($this->config['depth']) { # 处理多行数据 $new_item_data = array(); foreach ($new_data as $k => $v) { $tmp = $this->get_meta_item($table, $id, $k, $v); $new_item_data[$tmp['hash']] = $tmp; } } else { $tmp = $this->get_meta_item($table, $id, 0, $new_data); $new_item_data[$tmp['hash']] = $tmp; } foreach ($new_item_data as $hash => $item) { $tmp_value = $item['meta_value']; if ($tmp_value !== array() && null !== $tmp_value) { if ($format_type) { # 动态格式化 if (is_array($tmp_value) || is_object($tmp_value)) { $tmp_value = serialize($tmp_value); } } elseif (isset($this->config['format']) && $this->config['format']) { # 格式化数据 $this->_format_data($tmp_value); } } $tmp_value = (string) $tmp_value; if ('' === $tmp_value) { # 空字符串,则移除 null unset($new_item_data[$hash]); } else { $new_item_data[$hash]['meta_value'] = $tmp_value; if (isset($old_item_data[$hash]) || array_key_exists($hash, $old_item_data)) { if ($old_item_data[$hash]['meta_value'] === $tmp_value) { # 相同数据,全部去掉掉则不更新 unset($new_item_data[$hash]); unset($old_item_data[$hash]); } else { unset($old_item_data[$hash]); } } } } # 把老数据清理掉 if ($old_item_data) { foreach ($old_item_data as $hash => $item) { $new_item_data[$hash] = null; } } $new_data = $new_item_data; if (isset($data[$my_table])) { $data[$my_table] += $new_data; } else { $data[$my_table] = $new_data; } }
/** * 批量获取数据 * * @param OOP_ORM $finder * @param OOP_ORM_Data $obj * @return null|OOP_ORM_Data */ protected function get_data_batch_type(OOP_ORM $finder, OOP_ORM_Data $obj, $type) { $config = $this->config(); $mapping = $config['mapping']; $where = $config['where']; $bind = isset($config['bind']) ? $config['bind'] : null; $bind_field = $this->field_name; $group = array(); if ($group_ids = $obj->__orm_callback('get_group_ids')) { $obj_class = get_class($obj); $next = true; // 用来判断使得要跳出while循环 $offset = 0; // 起始位置 $limit = 100; // 单组批量获取数,这样可以避免某些组数量特别多时导致异常问题 while ($next) { $found_count = 0; foreach ($group_ids as $group_id) { $tmp_group_data = OOP_ORM_Result::get_data_by_group_id($group_id, $offset, $limit); $found_count += count($tmp_group_data); foreach ($tmp_group_data as $item) { if (get_class($item) !== $obj_class) { # 不是相同类型的对象 continue; } if ($item === $obj) { # 同一个对象 $next = false; } if ($item->__orm_callback('is_compiled', $this->key)) { # 已经构造过的数据忽略 continue; } if ($found_count > $limit) { $next = false; } $group[] = $item; } } if (!$found_count) { # 没有可用的返回数 break; } $offset += $limit; } } if (!$group) { # 没有获取到任何组,则采样单个获取的方法 OOP_ORM_DI_ORM::set_query_info($obj, $finder, $config); return $finder->find()->current(); } $batch_where = array(); foreach ($group as $item) { /** * @var $item OOP_ORM_Data */ foreach ($mapping as $k => $v) { $batch_where[$k][] = $item->{$v}; } foreach ($where as $k => $v) { $batch_where[$k][] = $v; } if ($bind) { $batch_where[$bind][] = $item->get_data_by_field_name($bind_field, true); } } # 对数据进行去重处理 $batch_where = array_map('array_unique', $batch_where); $return = null; if (1 === count($batch_where)) { # 只有1个条件 $c_key = key($batch_where); //当前字段名 $in = current($batch_where); //获取where条件 $rs = array(); $g = $finder->in($c_key, $in)->find(); $obj->__orm_callback('set_key_batch_orm_group', $g); foreach ($g as $item) { $k = $item->get_data_by_field_name($c_key, true); $item->__orm_callback('add_parent_group_id', $group_ids); $rs[$k][] = $item; } foreach ($group as $item) { if ($mapping) { $v = current($mapping); $k = $item->{$v}; } elseif ($where) { $k = current($where); } elseif ($bind) { $k = $item->get_data_by_field_name($bind_field, true); } else { $k = null; } if (!isset($rs[$k])) { if ($type !== OOP_ORM::PARAM_TYPE_O2O) { $current = array(); } else { $current = null; } } else { $current = $rs[$k]; if ($type === OOP_ORM::PARAM_TYPE_O2O) { $current = current($current); } } if ($item === $obj) { $return = $current; } else { # 通过回调设置ORM批量获取的数据 $item->__orm_callback('set_batch_orm_data', $this->key, $current); } } } else { foreach ($batch_where as $k => $v) { $finder->in($k, $v); $finder->group_by($k); } # 组织数据 $rs = array(); foreach ($finder->find() as $item) { /** * @var $item OOP_ORM_Data */ $k = ''; foreach ($mapping as $m_k => $v) { $k .= ',' . $item->{$m_k}; } foreach ($where as $m_value) { $k .= ',' . $m_value; } if ($bind) { $k .= ',' . $item->get_data_by_field_name($bind, true); } if (!isset($rs[$k])) { $rs[$k] = $item; } } foreach ($group as $i => $item) { $k = ''; foreach ($mapping as $m_key) { $k .= ',' . $item->{$m_key}; } foreach ($where as $m_value) { $k .= ',' . $m_value; } if ($bind) { $k .= ',' . $item->get_data_by_field_name($bind_field, true); } if (!isset($rs[$k])) { # 有可能数据库中没有对应的数据 if ($type !== OOP_ORM::PARAM_TYPE_O2O) { $current = array(); } else { $current = null; } } else { $current = $rs[$k]; if ($type === OOP_ORM::PARAM_TYPE_O2O) { $current = current($current); } } if ($item === $obj) { $return = $current; } else { # 通过回调设置ORM批量获取的数据 $item->__orm_callback('set_batch_orm_data', $this->key, $current); } } } return $return; }
/** * 构造数据 * * @param OOP_ORM_Data $obj * @param $data * @param $compiled_data * @return bool * @throws Exception */ public function &get_data(OOP_ORM_Data $obj, &$data, &$compiled_data, &$compiled_raw_data) { $parent_offset = $this->config['parent_offset']; $sub_offsets = $this->config['sub_offsets']; $tmp_data =& $obj->{$parent_offset}; foreach ($sub_offsets as $key) { if (null === $tmp_data) { throw new Exception("Illegal string offset '{$key}' of class {$this->class_name}, key:{$this->key}"); } if (is_object($tmp_data)) { if (isset($tmp_data->{$key})) { $tmp =& $tmp_data->{$key}; } else { $tmp = null; } } elseif (is_array($tmp_data)) { if (isset($tmp_data[$key])) { $tmp =& $tmp_data[$key]; } else { $tmp = null; } } else { throw new Exception("Illegal string offset '{$key}' of class {$this->class_name}, key:{$this->key}"); } unset($tmp_data); $tmp_data =& $tmp; unset($tmp); } # 移除指针 unset($compiled_data[$this->key]); # 重新赋值 $compiled_data[$this->key] =& $tmp_data; # 记录一个副本用于判断是否修改 $compiled_raw_data[$this->key] = $tmp_data; # 回调 $obj->__orm_callback('set_virtual_field_update', $parent_offset, $this->key); return $compiled_data[$this->key]; }