doufan1899 2016-02-17 14:11 采纳率: 100%
浏览 40

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

I am trying to link a one to many entity together using Doctrine in Apigility. The relationship is 1 slide has many bullets points. So I want the return json to show each slide and all its related nested bullets. But as you can see from the output below the bullets always return empty:

{
  "_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
}

The slide entity for both the bullet and the slide

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

}

The database entries

+----+-------+----------+------+
| 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 |
+----+----------+---------------+

Any help would be gratefully appreciated.

I've also added the 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'
        )
    )
);

module/apiexample/config/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条回答 默认 最新

  • douding6266 2016-03-01 10:19
    关注

    Your getBullets method returns a ArrayCollection instance and the Hal renderer doesn't know how to render (serialize) this object and that is why you see {} (an object in json format). You should add a custom hydrator/extractor where you return some renderable value for your bullits. You could for example make it to a Hal\Collection instance.

    In your hydrator/extractor you could do something like:

    <?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;
        }
    
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)