Apigility Doctrine 1到2个实体之间的很多关系

时间:2016-02-17 14:11:17

标签: php orm doctrine-orm apigility

我正在尝试使用Apigility中的Doctrine将一个实体链接到一个实体。关系是1幻灯片有很多子弹点。所以我希望返回json显示每个幻灯片及其所有相关的嵌套项目符号。但正如你从下面的输出中看到的那样,子弹总是返回空:

{
  "_links": {
    "self": {
      "href": "http://0.0.0.0:8888/slide"
    }
  },
  "_embedded": {
    "slide": [
      {
        "id": "2",
        "title": "Title",
        "previous": "Previous",
        "next": "Next",
        "bullets": {},
        "_links": {
          "self": {
            "href": "http://0.0.0.0:8888/slide/2"
          }
        }
      },
      {
        "id": "3",
        "title": "Title",
        "previous": "Previous",
        "next": "Next",
        "bullets": {},
        "_links": {
          "self": {
            "href": "http://0.0.0.0:8888/slide/3"
          }
        }
      },
      {
        "id": "4",
        "title": "Title",
        "previous": "Previous",
        "next": "Next",
        "bullets": {},
        "_links": {
          "self": {
            "href": "http://0.0.0.0:8888/slide/4"
          }
        }
      },
      {
        "id": "5",
        "title": "Title",
        "previous": "Previous",
        "next": "Next",
        "bullets": {},
        "_links": {
          "self": {
            "href": "http://0.0.0.0:8888/slide/5"
          }
        }
      },
      {
        "id": "6",
        "title": "Title",
        "previous": "Previous",
        "next": "Next",
        "bullets": {},
        "_links": {
          "self": {
            "href": "http://0.0.0.0:8888/slide/6"
          }
        }
      }
    ]
  },
  "total_items": 5
}

子弹和幻灯片的幻灯片实体

namespace demo\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Sentence
 *
 * @ORM\Table(name="slide")
 * @ORM\Entity(repositoryClass="demo\Repository\SlideRepository")
 */
class Slide
{
   /**
     * @var integer
     *
     * @ORM\Column(name="id", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=45, nullable=true)
     */
    private $title;
    /**
     * @var string
     *
     * @ORM\Column(type="string", length=45, nullable=true)
     */
    private $previous;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=45, nullable=true)
     */
    private $next;

    /**
     * @ORM\OneToMany(targetEntity="Bullet", mappedBy="slide")
     */
    private $bullets;

    public function __construct()
    {
        $this->bullets = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * @param string $title
     */
    public function setTitle($title)
    {
        $this->title = $title;
    }

    /**
     * @return string
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * @param string $previous
     */
    public function setPrevious($previous)
    {
        $this->previous = $previous;
    }

    /**
     * @return string
     */
    public function getPrevious()
    {
        return $this->previous;
    }

    /**
     * @param int $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param string $next
     */
    public function setNext($next)
    {
        $this->next = $next;
    }

    /**
     * @return string
     */
    public function getNext()
    {
        return $this->next;
    }

    /**
     * Add bullets
     *
     * @param Bullet $bullets
     * @return Slide
     */
    public function addBullet(Bullet $bullets)
    {
      $this->bullets[] = $bullets;
      return $this;
    }
    /**
     * Remove bullets
     *
     * @param Bullet $bullets
     */
    public function removeBullet(Bullet $bullets)
    {
      $this->bullets->removeElement($bullets);
    }
    /**
     * Get bullets
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getBullets()
    {
      return $this->bullets;
    }
}

namespace demo\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Sentence
 *
 * @ORM\Table(name="bullets")
 * @ORM\Entity(repositoryClass="demo\Repository\BulletsRepository")
 */
class Bullet
{
   /**
     * @var integer
     *
     * @ORM\Column(name="id", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="bullet", type="string", length=45, nullable=true)
     */
    private $bullet;

   /**
     * @ORM\ManyToOne(targetEntity="Slide", inversedBy="bullets")
     * @ORM\JoinColumn(name="slide_id", referencedColumnName="id")
     */
    protected $slide;

    public function __construct()
    {
        var_dump('TEST!!');
        exit();
    }

    /**
     * @param int $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param string $bullet
     */
    public function setBullet($bullet)
    {
        $this->bullet = $bullet;
    }

    /**
     * @return string
     */
    public function getBullet()
    {
        return $this->bullet;
    }

    /**
     * @return string
     */
    public function getSlide()
    {
        return $this->slide;
    }

    /**
     * @param string $slide
     */
    public function setSlide(Slide $slide = null)
    {
        $this->slide = $slide;
        return $this;
    }

}

数据库条目

+----+-------+----------+------+
| id | title | previous | next |
+----+-------+----------+------+
|  2 | Title | Previous | Next |
|  3 | Title | Previous | Next |
|  4 | Title | Previous | Next |
|  5 | Title | Previous | Next |
|  6 | Title | Previous | Next |
+----+-------+----------+------+
+----+----------+---------------+
| id | slide_id | bullet        |
+----+----------+---------------+
|  1 |        2 | Test Bullet   |
|  2 |        3 | Test Bullet   |
|  3 |        4 | Array         |
|  4 |        5 | test Bullet 2 |
|  5 |        6 | test Bullet 2 |
+----+----------+---------------+

感谢任何帮助。

我还添加了application.config.php:

/**
 * Configuration file generated by ZF Apigility Admin
 *
 * The previous config file has been stored in application.config.old
 */
return array(
    'modules' => array(
        'ZF\\DevelopmentMode',
        'ZF\\Apigility',
        'ZF\\Apigility\\Provider',
        'ZF\\Apigility\\Documentation',
        'AssetManager',
        'ZF\\ApiProblem',
        'ZF\\Configuration',
        'ZF\\MvcAuth',
        'ZF\\OAuth2',
        'ZF\\Hal',
        'ZF\\ContentNegotiation',
        'ZF\\ContentValidation',
        'ZF\\Rest',
        'ZF\\Rpc',
        'ZF\\Versioning',
        'apiexample',
        'DoctrineModule',
        'DoctrineORMModule'
    ),
    'module_listener_options' => array(
        'module_paths' => array(
            './module',
            './vendor'
        ),
        'config_glob_paths' => array(
            'config/autoload/{,*.}{global,local}.php'
        )
    )
);

模块/ apiexample /配置/ module.config.php

return array(
    'controllers' => array(
        'factories' => array(
            'apiexample\\V1\\Rpc\\Ping\\Controller' => 'apiexample\\V1\\Rpc\\Ping\\PingControllerFactory',
        ),
    ),
    'router' => array(
        'routes' => array(
            'apiexample.rpc.ping' => array(
                'type' => 'Segment',
                'options' => array(
                    'route' => '/ping',
                    'defaults' => array(
                        'controller' => 'apiexample\\V1\\Rpc\\Ping\\Controller',
                        'action' => 'ping',
                    ),
                ),
            ),
            'apiexample.rest.user' => array(
                'type' => 'Segment',
                'options' => array(
                    'route' => '/user[/:user_id]',
                    'defaults' => array(
                        'controller' => 'apiexample\\V1\\Rest\\User\\Controller',
                    ),
                ),
            ),
        ),
    ),
    'zf-versioning' => array(
        'uri' => array(
            0 => 'apiexample.rpc.ping',
            1 => 'apiexample.rest.user',
        ),
    ),
    'zf-rpc' => array(
        'apiexample\\V1\\Rpc\\Ping\\Controller' => array(
            'service_name' => 'Ping',
            'http_methods' => array(
                0 => 'GET',
            ),
            'route_name' => 'apiexample.rpc.ping',
        ),
    ),
    'zf-content-negotiation' => array(
        'controllers' => array(
            'apiexample\\V1\\Rpc\\Ping\\Controller' => 'Json',
            'apiexample\\V1\\Rest\\User\\Controller' => 'HalJson',
        ),
        'accept_whitelist' => array(
            'apiexample\\V1\\Rpc\\Ping\\Controller' => array(
                0 => 'application/vnd.apiexample.v1+json',
                1 => 'application/json',
                2 => 'application/*+json',
            ),
            'apiexample\\V1\\Rest\\User\\Controller' => array(
                0 => 'application/vnd.apiexample.v1+json',
                1 => 'application/hal+json',
                2 => 'application/json',
            ),
        ),
        'content_type_whitelist' => array(
            'apiexample\\V1\\Rpc\\Ping\\Controller' => array(
                0 => 'application/vnd.apiexample.v1+json',
                1 => 'application/json',
            ),
            'apiexample\\V1\\Rest\\User\\Controller' => array(
                0 => 'application/vnd.apiexample.v1+json',
                1 => 'application/json',
            ),
        ),
    ),
    'zf-content-validation' => array(
        'apiexample\\V1\\Rpc\\Ping\\Controller' => array(
            'input_filter' => 'apiexample\\V1\\Rpc\\Ping\\Validator',
        ),
    ),
    'input_filter_specs' => array(
        'apiexample\\V1\\Rpc\\Ping\\Validator' => array(
            0 => array(
                'name' => 'ack',
                'required' => true,
                'filters' => array(),
                'validators' => array(),
                'description' => 'Acknowledge the request with a timestamp.',
            ),
        ),
    ),
    'service_manager' => array(
        'factories' => array(
            'apiexample\\V1\\Rest\\User\\UserResource' => 'apiexample\\V1\\Rest\\User\\UserResourceFactory',
        ),
    ),
    'zf-rest' => array(
        'apiexample\\V1\\Rest\\User\\Controller' => array(
            'listener' => 'apiexample\\V1\\Rest\\User\\UserResource',
            'route_name' => 'apiexample.rest.user',
            'route_identifier_name' => 'user_id',
            'collection_name' => 'user',
            'entity_http_methods' => array(
                0 => 'GET',
                1 => 'PATCH',
                2 => 'PUT',
                3 => 'DELETE',
                4 => 'POST',
            ),
            'collection_http_methods' => array(
                0 => 'GET',
                1 => 'POST',
            ),
            'collection_query_whitelist' => array(),
            'page_size' => '2',
            'page_size_param' => null,
            'entity_class' => 'apiexample\\Entity\\User',
            'collection_class' => 'apiexample\\V1\\Rest\\User\\UserCollection',
            'service_name' => 'user',
        ),
    ),
    'zf-hal' => array(
        'metadata_map' => array(
            'apiexample\\V1\\Rest\\User\\UserEntity' => array(
                'entity_identifier_name' => 'id',
                'route_name' => 'apiexample.rest.user',
                'route_identifier_name' => 'user_id',
                'hydrator' => 'Zend\\Stdlib\\Hydrator\\ObjectProperty',
            ),
            'apiexample\\V1\\Rest\\User\\UserCollection' => array(
                'entity_identifier_name' => 'id',
                'route_name' => 'apiexample.rest.user',
                'route_identifier_name' => 'user_id',
                'is_collection' => true,
            ),
            'apiexample\\Entity\\User' => array(
                'entity_identifier_name' => 'id',
                'route_name' => 'apiexample.rest.user',
                'route_identifier_name' => 'user_id',
                'hydrator' => 'apiexample\\Hydrator\\UserHydrator',
            ),
        ),
    ),
    'doctrine' => array(
        'driver' => array(
            'lanekeep_driver' => array(
                'class' => 'Doctrine\\ORM\\Mapping\\Driver\\AnnotationDriver',
                'cache' => 'array',
                'paths' => array(
                    0 => __DIR__ . '/../src/apiexample/Entity',
                ),
            ),
            'orm_default' => array(
                'drivers' => array(
                    'apiexample\\Entity' => 'lanekeep_driver',
                ),
            ),
        ),
    ),
    'view_manager' => array(
        'display_not_found_reason' => true,
        'display_exceptions' => true,
        'doctype' => 'HTML5',
        'not_found_template' => 'error/404',
        'exception_template' => 'error/index',
        'template_map' => array(
            'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
            'error/404' => __DIR__ . '/../view/error/404.phtml',
            'error/index' => __DIR__ . '/../view/error/index.phtml',
        ),
        'template_path_stack' => array(
            0 => __DIR__ . '/../view',
        ),
    ),
);

1 个答案:

答案 0 :(得分:0)

您的getBullets方法返回ArrayCollection实例,Hal渲染器不知道如何渲染(序列化)此对象,这就是您看到{}(json格式的对象)的原因。您应该添加一个自定义水合器/提取器,为您的bullits返回一些可渲染值。例如,您可以将其设置为Hal\Collection实例。

在您的保湿器/提取器中,您可以执行以下操作:

<?php

namespace Application\Extractor;

use Zend\Stdlib\Extractor\ExtractionInterface;
use ZF\Hal;

class SlideExtractor implements ExtractionInterface

    public function extract($object){

         $data = [];

         $route = //...your route to bullits
         $routeParams = //...route params if needed
         $bullits = $object->getBullits()->toArray();
         $collection = new Hal\Collection($bullits, $route, $routeParams);

         $data['bullits'] = $collection;

         //...other extractions from your slide ( $object )

         return $data;
    }

}