序列化与 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;

}