<?php<liu21st@gmail.com>
namespace think\model\concern;
use think\Collection;
use think\Exception;
use think\Loader;
use think\Model;
use think\model\Collection as ModelCollection;
trait Conversion
{
protected $visible = [];
protected $hidden = [];
protected $append = [];
protected $resultSetType;
public function append(array $append = [], $override = false)
{
$this->append = $override ? $append : array_merge($this->append, $append);
return $this;
}
public function appendRelationAttr($attr, $append)
{
if (is_string($append)) {
$append = explode(',', $append);
}
$relation = Loader::parseName($attr, 1, false);
if (isset($this->relation[$relation])) {
$model = $this->relation[$relation];
} else {
$model = $this->getRelationData($this->$relation());
}
if ($model instanceof Model) {
foreach ($append as $key => $attr) {
$key = is_numeric($key) ? $attr : $key;
if (isset($this->data[$key])) {
throw new Exception('bind attr has exists:' . $key);
} else {
$this->data[$key] = $model->$attr;
}
}
}
return $this;
}
public function hidden(array $hidden = [], $override = false)
{
$this->hidden = $override ? $hidden : array_merge($this->hidden, $hidden);
return $this;
}
public function visible(array $visible = [], $override = false)
{
$this->visible = $override ? $visible : array_merge($this->visible, $visible);
return $this;
}
public function toArray()
{
$item = [];
$visible = [];
$hidden = [];
$data = array_merge($this->data, $this->relation);
if (!empty($this->visible)) {
$array = $this->parseAttr($this->visible, $visible);
if (!empty($array)) {
$data = array_intersect_key($data, array_flip($array));
}
}
if (empty($array) && !empty($this->hidden)) {
$array = $this->parseAttr($this->hidden, $hidden);
$data = array_diff_key($data, array_flip($array));
}
foreach ($data as $key => $val) {
if ($val instanceof Model || $val instanceof ModelCollection) {
if (isset($visible[$key])) {
$val->visible($visible[$key]);
} elseif (isset($hidden[$key])) {
$val->hidden($hidden[$key]);
}
$item[$key] = $val->toArray();
} else {
$item[$key] = $this->getAttr($key);
}
}
if (!empty($this->append)) {
foreach ($this->append as $key => $name) {
if (is_array($name)) {
$relation = $this->getRelation($key);
if (!$relation) {
$relation = $this->getAttr($key);
$relation->visible($name);
}
$item[$key] = $relation->append($name)->toArray();
} elseif (strpos($name, '.')) {
list($key, $attr) = explode('.', $name);
$relation = $this->getRelation($key);
if (!$relation) {
$relation = $this->getAttr($key);
$relation->visible([$attr]);
}
$item[$key] = $relation->append([$attr])->toArray();
} else {
$item[$name] = $this->getAttr($name, $item);
}
}
}
return $item;
}
public function toJson($options = JSON_UNESCAPED_UNICODE)
{
return json_encode($this->toArray(), $options);
}
public function removeRelation()
{
$this->relation = [];
return $this;
}
public function __toString()
{
return $this->toJson();
}
public function jsonSerialize()
{
return $this->toArray();
}
public function toCollection($collection, $resultSetType = null)
{
$resultSetType = $resultSetType ?: $this->resultSetType;
if ($resultSetType && false !== strpos($resultSetType, '\\')) {
$collection = new $resultSetType($collection);
} else {
$collection = new ModelCollection($collection);
}
return $collection;
}
protected function parseAttr($attrs, &$result)
{
$array = [];
foreach ($attrs as $key => $val) {
if (is_array($val)) {
$result[$key] = $val;
} elseif (strpos($val, '.')) {
list($key, $name) = explode('.', $val);
$result[$key][] = $name;
} else {
$array[] = $val;
}
}
return $array;
}
}