使用与ZF3 MVC Response JSON的关系序列化对象

时间:2017-09-10 02:52:01

标签: php json zend-framework3

我有一个Zend Framework 3应用程序。我将ViewJsonStrategy添加到module.config.php。但我想返回一个JSON对象,它们的关系对象在数组中是ONE TO MANY:

在我的控制器上

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

关联的对象就像Object而不是Array()。 我怎么能这样的关系对象到达像Json Array()?

2 个答案:

答案 0 :(得分:1)

反射水合器本身不允许嵌套水合/提取。 但是Hydrator Aggregates会这样做,但你必须投入更多的工作,然后只是简单地实例化它。如果你选择这条路线,我会投入更多的时间并将其注入控制器以保持高可测试性

还要考虑使用doctrine / doctrine-module composer包提供的Doctrine Hydrator。该项目还有关于hydration

的简短文档

答案 1 :(得分:0)

谢谢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;

}