2017 © Pedro Peláez
 

library rest-bundle

image

fsc/rest-bundle

  • Thursday, October 11, 2012
  • by AdrienBrault
  • Repository
  • 4 Watchers
  • 7 Stars
  • 25 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 5 Forks
  • 2 Open issues
  • 1 Versions
  • 0 % Grown

The README.md

FSCRestBundle

Build Status, (*1)

This bundle will generate a REST HATEOAS api based on the configuration you'll do. ATM it can only generate a read only api, backed by doctrine ORM. The representations are optimized for the XML format, but are also usable in JSON., (*2)

If you create relations between resources, the bundle will automatically create links between them., (*3)

The design obviously took many shortchuts, and is not a reference of OOP design ... but it works. But it's easy to override behavior because you need to the extend the classe that does everything, for each resource..., (*4)

This bundle was extracted from an app, and need some love to be usable. (ie composer, make tests work etc ...), (*5)

LICENSE

MIT: Resources/meta/LICENSE, (*6)

TODO

  • Create a "sanbox" symfony2 app to demonstrate how to fully use the bundle

Installation

Edit your composer.json like this:, (*7)

{
    "require": {
        ...
        "jms/serializer-bundle": "dev-xml-attribute-map as 0.9.0",
        "fsc/rest-bundle": "*"
        ...
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/adrienbrault/JMSSerializerBundle"
        }
    ]
}

Update your deps: composer update., (*8)

Add the bundle to your AppKernel:, (*9)

// in AppKernel::registerBundles()
$bundles = array(
    // ...
    new FSC\RestBundle\FSCRestBundle(),
    new JMS\SerializerBundle\JMSSerializerBundle(),
    new FOS\FOSRestBundle(),
    // ...
);

Be aware that this bundle relies on a fork of JMSSerializerBundle, because this PR is still not merged: https://github.com/schmittjoh/JMSSerializerBundle/pull/164, (*10)

Example

For an example of what the controller returns: https://gist.github.com/3800069, (*11)

You need to define services, tagged with fsc_rest.resource., (*12)

services:
    fsc.core.spot.resource.spots:
        class: FSC\Core\SpotBundle\REST\SpotsResource
        parent: fsc.rest.resource.abstract_doctrine
        tags:
          - { name: fsc_rest.resource }
<?php

namespace FSC\Core\TeamBundle\REST;

use FSC\Core\MainBundle\REST\AbstractSocialEntityResource;
use FSC\Common\RestBundle\Form\Model\Collection;
use FSC\Core\TeamBundle\Repository\FormationRepository;
use FSC\Core\SpotBundle\Repository\SpotRepository;

class TeamsResource extends AbstractSocialEntityResource
{
    protected function configure()
    {
        return array_merge(parent::configure(), array(
            'prefix' => '/teams',
            'entity_class' => 'FSC\Core\TeamBundle\Entity\Team',
        ));
    }

    // Configure root collection ... /teams
    protected function configureCollection()
    {
        return array_merge(parent::configureCollection(), array(
            'xml_root_name' => 'teams',
            'representation_class' => 'FSC\Core\TeamBundle\Model\Representation\Teams',
            'pager_fetch_join_collection' => false,
        ));
    }

    // Configure how each entity representation looks like
    // ie:
    //
    // <team id="">
    //   <name></name>
    //   ...
    // </team>
    protected function configureEntity()
    {
        return array_merge(parent::configureEntity(), array(
            'expanded_collections' => array('formations'),
            'xml_root_name' => 'team',
            'normalize_attributes' => array(
                'id' => 'id',
            ),
            'normalize_elements' => array(
                'name' => 'name',
                'clubName' => 'clubName',
                'category' => 'category',
                'division' => 'division',
                'foundedAt' => 'foundedAt',
            ),
        ));
    }

    // Configure each entity collection, ie: a teams has formations, so you'll have a collection
    // at /teams/{id}/formations
    protected function configureEntityCollections()
    {
        return array_merge_recursive(parent::configureEntityCollections(), array(
            'formations' => array(
                'representation_class' => 'FSC\Core\TeamBundle\Model\Representation\Formations',

                // Which resources should be asked to normalize the collection elements ...
                'resources' => array(
                    'FSC\Core\TeamBundle\Entity\Formation' => 'fsc.core.team.resource.formations',
                ),
                'create_qb' => function ($em, $repository, $entity) {
                    $formationRepository = $em->getRepository('FSCCoreTeamBundle:Formation'); /** @var $formationRepository FormationRepository */

                    return $formationRepository->createSelectByTeamQB($entity);
                },
            ),
            'official-spots' => array(
                'representation_class' => 'FSC\Core\SpotBundle\Model\Representation\Spots',
                'resources' => array(
                    'FSC\Core\SpotBundle\Entity\Spot' => 'fsc.core.spot.resource.spots',
                ),
                'create_qb' => function ($em, $repository, $team) {
                    $spotRepository = $em->getRepository('FSCCoreSpotBundle:Spot'); /** @var $spotRepository SpotRepository */

                    return $spotRepository->createSelectNonDeletedByOfficialTeamQB($team);
                },
            ),
        ));
    }
}
<?php

namespace FSC\Core\SpotBundle\REST;

use FSC\Core\MainBundle\REST\AbstractSocialEntityResource;
use FSC\Common\RestBundle\Form\Model\Collection;
use FSC\Core\TeamBundle\Repository\TeamRepository;

class SpotsResource extends AbstractSocialEntityResource
{
    protected function configure()
    {
        return array_merge(parent::configure(), array(
            'prefix' => '/spots',
            'entity_class' => 'FSC\Core\SpotBundle\Entity\Spot',
        ));
    }

    protected function configureCollection()
    {
        return array_merge(parent::configureCollection(), array(
            'xml_root_name' => 'spots',
            'representation_class' => 'FSC\Core\SpotBundle\Model\Representation\Spots',
            'pager_fetch_join_collection' => false,
        ));
    }

    protected function configureEntity()
    {
        return array_merge(parent::configureEntity(), array(
            'xml_root_name' => 'spot',
            'normalize_attributes' => array(
                'id' => 'id',
            ),
            'normalize_elements' => array(
                'name' => 'name',
                'description' => 'description',
                'subCategory' => 'subCategory',
                'category' => 'category',
                'surface' => 'surface',
                'previousNames' => 'previousNames',
                'capacity' => 'capacity',
                'facts' => 'facts',
                'opened' => 'opened',
                'architect' => 'architect',
            ),
        ));
    }

    protected function configureEntityCollections()
    {
        return array_merge_recursive(parent::configureEntityCollections(), array(
            'official-teams' => array(
                'representation_class' => 'FSC\Core\TeamBundle\Model\Representation\Teams',
                'resources' => array(
                    'FSC\Core\TeamBundle\Entity\Team' => 'fsc.core.team.resource.teams',
                ),
                'create_qb' => function ($em, $repository, $spot) {
                    $teamRepository = $em->getRepository('FSCCoreTeamBundle:Team'); /** @var $teamRepository TeamRepository */

                    return $teamRepository->createSelectByOfficialSpotQB($spot);
                },
            ),
        ));
    }

    protected function configureEntityRelations()
    {
        return array_merge(parent::configureEntityRelations(), array(
            'creator' => array(
                'get_relation' => function ($em, $repository, $spot) {
                    return $spot->getSpotCreator();
                },
                'resources' => array(
                    'FSC\Core\UserBundle\Entity\User' => 'fsc.core.user.resource.users',
                ),
            ),
        ));
    }
}

More details

When you request a resource, the bundle will:, (*13)

Entity --(normalize)--> Representation --(serialize)--> XML/JSON
             ||                              ||
        RESTResources                   JMSSerializer

The Versions