/** * 设置数据 * * 键名是对象的键名,而并非数据库字段的键名,可以批量设置 * $has_created=是否已构造好的数据。若已构造好的数据则无需再经过_create_data()方法处理,默认false * * set_data( array('a'=>'1','b'=>2) ); * set_data( array('a'=>'1','b'=>2) , null , true ); * set_data( 'a , '1' ); * set_data( 'a , '1' , true ); * * @param array/string $key * @param fixed $value 值 * @param boolean $has_parsed 是否已构造好的数据,默认false * @return boolean 是否设置成功 */ public function set_data($key, $value, $has_parsed = false) { if (is_array($key)) { foreach ($key as $k => $v) { $this->set_data($k, $v, $has_parsed); } return true; } # 获取当前设置 $config = $this->_get_offset_config($key); if (!$config) { if (preg_match('#^[a-z]#i', $key) || $key == '__orm_sleep_data__') { # 没有相应的配置,直接快速设置后返回,其中__orm_sleep_data__为对象序列化时需要设置的key $this->{$key} = $value; } return; } # 当前节点是否已设置 $offset_isset = isset($this->_offset_data[$key]); # 标记为已设置过的节点 $this->_has_set_offset[$key] = true; if ($this->_orm_data_is_created) { # 对象已构造完毕 if ($offset_isset && $config['is_readonly']) { if (null !== $this->_offset_data[$key] && false !== $this->_offset_data[$key]) { # 只读字段不允许修改 return false; } } } # 映射字段 if (isset($config['_parent_offset_name'])) { $parent_offset = $config['_parent_offset_name']; # 父节点名 if (!$parent_offset || $parent_offset == $key) { return false; } $parent_data = $this->{$parent_offset}; # 设置子节点数据 $is_changed = OOP_ORM_Parse::set_sub_offset_data($parent_data, $value, explode('.', $config['_sub_key_name'])); # 将数据设置到父节点 if (false === $is_changed || false === $this->__set($parent_offset, $parent_data)) { # 若返回是false,则表示父类不允许设置(比如只读字段) return false; } else { # 父节点会推动所有子节点更新数据,所以这边直接返回true即可 return true; } } elseif (isset($config['field_name'])) { if ($this->_orm_data_is_created) { $this->_data_is_changed = true; } else { # 记录到旧数据 $this->_original_field_data[$config['field_name']] = $value; } } if ($has_parsed) { $this->_offset_data[$key] = $value; # 设为已构造 $this->_created_offset[$key] = true; } else { # 反解格式化数据 if (isset($config['format'])) { $value = OOP_ORM_Parse::de_format_data($value, $config['format']); } if (isset($this->_created_offset[$key])) { # 已经构造了 if (is_object($this->_offset_data[$key])) { # 对象 if (isset($config['object']['callback']['set_data'])) { # 配置有设置数据的接口 $call_set_data_function = $config['object']['callback']['set_data']; $obj = $this->_offset_data[$key]; $obj->{$call_set_data_function}($value); } else { $this->_offset_data[$key] = $value; # 清理掉以便可以重新构造 unset($this->_created_offset[$key]); } } else { # 已创建了且不是对象,则可以直接替换掉 $this->_offset_data[$key] = $value; } } else { # 设置了一个未构造的数据,且当前也没有构造数据,则直接替换掉 $this->_offset_data[$key] = $value; } } # 推动子字段进行更新数据 if (isset($config['_all_sub_offset'])) { foreach ($config['_all_sub_offset'] as $sub_key) { # 子字段配置 $sub_config = $this->_get_offset_config($sub_key); if (!$sub_config || !isset($sub_config['_sub_key_name'])) { continue; } # 默认都需要清理子数据 $need_reset = true; # 表示子字段已设置过 $this->_has_set_offset[$sub_key] = true; if (isset($this->_created_offset[$sub_key])) { if (is_object($this->_offset_data[$sub_key])) { # 已构造对象需要处理 $obj = $this->_offset_data[$sub_key]; if (isset($config['object']['callback']['set_data'])) { $sub_data = OOP_ORM_Parse::get_sub_offset_data($this->{$key}, explode('.', $sub_config['_sub_key_name'])); $call_set_data_function = $config['object']['callback']['set_data']; $obj->{$call_set_data_function}($sub_data); # 调用过设置数据的的回调函数后就不需要再清理了 $need_reset = false; } else { # 没有设置回调函数 if ($obj instanceof OOP_ORM_Data || method_exists($obj, 'getArrayCopy')) { # 获取当前数据 $tmp_data = $obj->getArrayCopy(); # 获取父节点的子数据 $sub_data = OOP_ORM_Parse::get_sub_offset_data($this->{$key}, explode('.', $sub_config['_sub_key_name'])); if ($tmp_data === $sub_data) { # 未修改过,不需要清理 $need_reset = false; } } elseif (method_exists($obj, '__toString')) { # 获取当前数据 $tmp_data = $obj->__toString(); # 获取父节点的子数据 $sub_data = OOP_ORM_Parse::get_sub_offset_data($this->{$key}, explode('.', $sub_config['_sub_key_name'])); if ($tmp_data === $sub_data) { # 未修改过,不需要清理 $need_reset = false; } } } } } if ($need_reset) { # 清理设置,在重新get的时候会重新构造数据 unset($this->_created_offset[$sub_key]); unset($this->_offset_data[$sub_key]); } } } return true; }