序列化与 ZF3 MVC 响应有关系的对象 JSON
Serializing objects with relationships to ZF3 MVC Response JSON
我有一个 Zend Framework 3 应用程序。我将 ViewJsonStrategy 添加到 module.config.php。但我想要 return 一个 JSON 对象,它们的关系对象在数组中一对多:
在我的控制器上
public function getdirectoriojsonAction(){
$idraiz = $this->cfgGral->getIdDirectorioRaiz();
if ($idraiz <= 0) {
return $this->redirect()->toRoute('configuracion', ['action' => 'index']);
} else {
if ($this->params()->fromRoute('id') > 0) {
$idraiz = $this->params()->fromRoute('id');
}
$directorio = $this->em->find($this->rutaEntityDirectorio, $idraiz);
if ($directorio->getEstado() != 0) {
$directorio = $directorio->getPadre();
$directorio->getDirectoriosHijos();
$directorio->getArchivosHijos();
}
}
$hydrator = new Reflection;
return new JsonModel($hydrator->extract($directorio));
}
实体目录
<?php
namespace Directorios\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation as ZendAnnotation;
use Directorios\Model\ArchivoInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
* @ORM\Table (name="directorio")
*
*/
class Directorio
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
* @ZendAnnotation\Exclude()
* @var int|null
*/
private $id;
/**
* @ORM\Column(type="string")
* @var string
* @Required
* @ZendAnnotation\Filter({"name":"StringTrim"})
* @ZendAnnotation\Validator({"name":"StringLength", "options":{"min":1, "max":60}})
* @ZendAnnotation\Validator({"name":"Regex", "options":{"pattern":"/^[a-zA-Z][a-zA-Z0-9_-]{0,24}$/"}})
* @ZendAnnotation\Attributes({"type":"text"})
* @ZendAnnotation\Options({"label":"Nombre:"})
*/
private $nombre;
/**
* @ORM\ManyToOne(targetEntity="Directorios\Entity\Directorio", inversedBy="directoriosHijos")
* @ORM\JoinColumn(name="padre", referencedColumnName="id")
*/
private $padre;
/**
* @ORM\OneToMany(targetEntity="Directorios\Entity\Directorio", mappedBy="padre",cascade={"persist", "remove"})
*/
private $directoriosHijos;
/**
* @ORM\OneToMany(targetEntity="Directorios\Entity\Archivo", mappedBy="padre", cascade={"persist", "remove"})
*/
private $archivosHijos;
/**
* @ORM\Column(type="datetime")
* @var \DateTime
*/
private $fechaCreacion;
/**
* @ORM\Column(type="datetime")
* @var \DateTime
*/
private $fechaModificacion;
/**
* @ORM\Column(name="ruta_real")
* @ORM\Column(type="text")
*/
private $ruta_real;
/**
*
* @ORM\Column(type="integer")
*
*/
private $estado=0;
/**
*
* @ORM\Column(type="integer")
*
*/
private $tipo;
//....... methods
public function __construct(){
$this->archivosHijos=new ArrayCollection();
$this->directoriosHijos=new ArrayCollection();
}
}
JSON 响应:
id 2
nombre "Nuevo directorio"
padre Object <- Returns Objects
directoriosHijos Object <- Returns Objects
archivosHijos Object <- Returns Objects
fechaCreacion
date "2017-09-09 21:23:20.000000"
timezone_type 3
timezone "Europe/Berlin"
fechaModificacion
date "2017-09-09 21:23:20.000000"
timezone_type 3
timezone "Europe/Berlin"
ruta_real "D:\testDirectorioRaiz"
estado 0
tipo 0
关联的对象像对象而不像 Array()。
我怎样才能使相关对象也像 Json Array() 一样到达?
Reflection Hydrator 本身不允许嵌套 hydration/extraction。
然而 Hydrator Aggregates 这样做,但是你必须在其中投入更多的工作,然后只是简单地实例化它。如果您选择这条路线,我会投入更多时间并将其注入控制器,以保持较高的可测试性
也可以考虑使用 doctrine/doctrine-module composer 包提供的 Doctrine Hydrator。该项目还有关于 hydration
的简短文档
谢谢 jeger,我正在寻找一个最简单的解决方案,但我发现这不适用于这种情况。刚才我开始研究理论水化器,但是现在我用一个简单的递归 XD 来修复。我把代码放在这里,也许会有帮助。
在我的控制器中...
// Method with response JSON
public function getdirectoriojsonAction(){
$idraiz = $this->cfgGral->getIdDirectorioRaiz();
if ($idraiz <= 0) {
return $this->redirect()->toRoute('configuracion', ['action' => 'index']);
} else {
if ($this->params()->fromRoute('id') > 0) {
$idraiz = $this->params()->fromRoute('id');
}
$directorio = $this->em->find($this->rutaEntityDirectorio,$idraiz);
if ($directorio->getEstado() == 0) {
$hydrator = new Reflection();
$dir = $hydrator->extract($directorio);
$dir = $this->getArrayHijosRec($dir, $hydrator);
}else{
return $this->redirect()->toRoute('directorios',['action'=>'error','id'=>2]);
}
}
return new JsonModel($dir);
}
// recursive method ... is not the best practice but works ...
private function getArrayHijosRec($directorioArray, Reflection $hydrator){
$directoriosHijos=$directorioArray['directoriosHijos'];
$archivosHijos=$directorioArray['archivosHijos'];
$padre=$directorioArray['padre'];
$directorioArray['directoriosHijos']=[];
$directorioArray['archivosHijos']=[];
$directorioArray['padre']=[];
$padre=(is_object($padre))?$hydrator->extract($padre):[];
$directorioArray['padre']=$padre;
foreach ($archivosHijos as $archHijo){
$archHijo=$hydrator->extract($archHijo);
$archHijo['padre']=$padre;
array_push($directorioArray['archivosHijos'],$archHijo);
}
foreach ($directoriosHijos as $dirHijo) {
$dirHijo=($hydrator->extract($dirHijo))
array_push($directorioArray['directoriosHijos'],($this->getArrayHijosRec($dirHijo,$hydrator)));
}
return $directorioArray;
}
我有一个 Zend Framework 3 应用程序。我将 ViewJsonStrategy 添加到 module.config.php。但我想要 return 一个 JSON 对象,它们的关系对象在数组中一对多:
在我的控制器上
public function getdirectoriojsonAction(){
$idraiz = $this->cfgGral->getIdDirectorioRaiz();
if ($idraiz <= 0) {
return $this->redirect()->toRoute('configuracion', ['action' => 'index']);
} else {
if ($this->params()->fromRoute('id') > 0) {
$idraiz = $this->params()->fromRoute('id');
}
$directorio = $this->em->find($this->rutaEntityDirectorio, $idraiz);
if ($directorio->getEstado() != 0) {
$directorio = $directorio->getPadre();
$directorio->getDirectoriosHijos();
$directorio->getArchivosHijos();
}
}
$hydrator = new Reflection;
return new JsonModel($hydrator->extract($directorio));
}
实体目录
<?php
namespace Directorios\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation as ZendAnnotation;
use Directorios\Model\ArchivoInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
* @ORM\Table (name="directorio")
*
*/
class Directorio
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
* @ZendAnnotation\Exclude()
* @var int|null
*/
private $id;
/**
* @ORM\Column(type="string")
* @var string
* @Required
* @ZendAnnotation\Filter({"name":"StringTrim"})
* @ZendAnnotation\Validator({"name":"StringLength", "options":{"min":1, "max":60}})
* @ZendAnnotation\Validator({"name":"Regex", "options":{"pattern":"/^[a-zA-Z][a-zA-Z0-9_-]{0,24}$/"}})
* @ZendAnnotation\Attributes({"type":"text"})
* @ZendAnnotation\Options({"label":"Nombre:"})
*/
private $nombre;
/**
* @ORM\ManyToOne(targetEntity="Directorios\Entity\Directorio", inversedBy="directoriosHijos")
* @ORM\JoinColumn(name="padre", referencedColumnName="id")
*/
private $padre;
/**
* @ORM\OneToMany(targetEntity="Directorios\Entity\Directorio", mappedBy="padre",cascade={"persist", "remove"})
*/
private $directoriosHijos;
/**
* @ORM\OneToMany(targetEntity="Directorios\Entity\Archivo", mappedBy="padre", cascade={"persist", "remove"})
*/
private $archivosHijos;
/**
* @ORM\Column(type="datetime")
* @var \DateTime
*/
private $fechaCreacion;
/**
* @ORM\Column(type="datetime")
* @var \DateTime
*/
private $fechaModificacion;
/**
* @ORM\Column(name="ruta_real")
* @ORM\Column(type="text")
*/
private $ruta_real;
/**
*
* @ORM\Column(type="integer")
*
*/
private $estado=0;
/**
*
* @ORM\Column(type="integer")
*
*/
private $tipo;
//....... methods
public function __construct(){
$this->archivosHijos=new ArrayCollection();
$this->directoriosHijos=new ArrayCollection();
}
}
JSON 响应:
id 2
nombre "Nuevo directorio"
padre Object <- Returns Objects
directoriosHijos Object <- Returns Objects
archivosHijos Object <- Returns Objects
fechaCreacion
date "2017-09-09 21:23:20.000000"
timezone_type 3
timezone "Europe/Berlin"
fechaModificacion
date "2017-09-09 21:23:20.000000"
timezone_type 3
timezone "Europe/Berlin"
ruta_real "D:\testDirectorioRaiz"
estado 0
tipo 0
关联的对象像对象而不像 Array()。 我怎样才能使相关对象也像 Json Array() 一样到达?
Reflection Hydrator 本身不允许嵌套 hydration/extraction。 然而 Hydrator Aggregates 这样做,但是你必须在其中投入更多的工作,然后只是简单地实例化它。如果您选择这条路线,我会投入更多时间并将其注入控制器,以保持较高的可测试性
也可以考虑使用 doctrine/doctrine-module composer 包提供的 Doctrine Hydrator。该项目还有关于 hydration
的简短文档谢谢 jeger,我正在寻找一个最简单的解决方案,但我发现这不适用于这种情况。刚才我开始研究理论水化器,但是现在我用一个简单的递归 XD 来修复。我把代码放在这里,也许会有帮助。
在我的控制器中...
// Method with response JSON
public function getdirectoriojsonAction(){
$idraiz = $this->cfgGral->getIdDirectorioRaiz();
if ($idraiz <= 0) {
return $this->redirect()->toRoute('configuracion', ['action' => 'index']);
} else {
if ($this->params()->fromRoute('id') > 0) {
$idraiz = $this->params()->fromRoute('id');
}
$directorio = $this->em->find($this->rutaEntityDirectorio,$idraiz);
if ($directorio->getEstado() == 0) {
$hydrator = new Reflection();
$dir = $hydrator->extract($directorio);
$dir = $this->getArrayHijosRec($dir, $hydrator);
}else{
return $this->redirect()->toRoute('directorios',['action'=>'error','id'=>2]);
}
}
return new JsonModel($dir);
}
// recursive method ... is not the best practice but works ...
private function getArrayHijosRec($directorioArray, Reflection $hydrator){
$directoriosHijos=$directorioArray['directoriosHijos'];
$archivosHijos=$directorioArray['archivosHijos'];
$padre=$directorioArray['padre'];
$directorioArray['directoriosHijos']=[];
$directorioArray['archivosHijos']=[];
$directorioArray['padre']=[];
$padre=(is_object($padre))?$hydrator->extract($padre):[];
$directorioArray['padre']=$padre;
foreach ($archivosHijos as $archHijo){
$archHijo=$hydrator->extract($archHijo);
$archHijo['padre']=$padre;
array_push($directorioArray['archivosHijos'],$archHijo);
}
foreach ($directoriosHijos as $dirHijo) {
$dirHijo=($hydrator->extract($dirHijo))
array_push($directorioArray['directoriosHijos'],($this->getArrayHijosRec($dirHijo,$hydrator)));
}
return $directorioArray;
}