martial/crud-bundle

This project aims to give a simple way to provide a CRUD service in a SOA Symfony2 project.

Installs: 11

Dependents: 0

Stars: 4

Watchers: 5

Forks: 1

Language: PHP

1.3.0 2014-03-19 16:27 UTC

README

This bundle aims to give a simple way to provide a CRUD service in a SOA Symfony2 project.

Note: Only Doctrine is supported at this time.

Build Status Scrutinizer Code Quality Code Coverage

Why should I use it

For example, a "show" action inside a controller:

<?php

namespace Martial\LabBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
    public function showAction($id)
    {
        $crud = $this->get('martial.crud')->getCrudManager('article');
        $article = $crud->find($id);

        return $this->render('MartialLabBundle:Default:show.html.twig', array(
                'article' => $article
            )
        );
    }
}

Pretty cool, but here is a new way to save a form:

public function createAction()
{
    $crud = $this->get('martial.crud')->getCrudManager('article');
    $crud->saveForm($this->getRequest());

    return $this->render('MartialLabBundle:Default:show.html.twig', array(
            'article' => $crud->getCurrentEntity()
        )
    );
}

And you're done. Of course, this snippet does not take care about the errors management. You can see here a complete example of a CRUD manager implementation.

The goal of this bundle is to be provided as a dependency to your business services:

<?php

namespace Martial\LabBundle\Article;

use Martial\CrudBundle\Service\Crud;

class ArticleService
{
    /**
     * @var \Martial\CrudBundle\Service\Crud
     */
    private $crudManager;

    /**
     * @param Crud $crudManager
     */
    public function __construct(Crud $crudManager)
    {
        $this->crudManager = $crudManager;
    }
}

Installation

1- Add the bundle in your composer.json:

{
    require: {
        "martial/crud-bundle": "~1"
    }
}

2- Run a composer update:

$ php composer.phar update martial/crud-bundle

3- Enable the bundle in your AppKernel:

<?php

public function registerBundles()
{
    $bundles = array(
        // ...
        new Martial\CrudBundle\MartialCrudBundle(),
    );
}

Configuration

You must declare the entities in your config.yml:

martial_crud:
    entities:
        article:
            repository: MartialLabBundle:Article
            entity_namespace: Martial\LabBundle\Entity\Article
            form_type_namespace: Martial\LabBundle\Form\ArticleType
        comment:
            repository: MartialLabBundle:Comment
            entity_namespace: Martial\LabBundle\Entity\Comment
            form_type_namespace: Martial\LabBundle\Form\CommentType

And you want something harder to configure, you will be disappointed!

The SOA way

If you want to use a service to manage your "article" entity, first create (for example) an ArticleService class:

<?php

namespace Martial\LabBundle\Service;

use Martial\CrudBundle\Service\AbstractCrudService;

class ArticleService extends AbstractCrudService
{
    /**
     * Define the entity key used by the CRUD manager.
     *
     * @return string
     */
    public function getEntityKey()
    {
        return 'article';
    }
}

Your class can extend the base class \Martial\CrudBundle\Service\AbstractCrudService which provide the main CRUD methods. In this case, the only thing to do is to implement the getEntityKey method. This method must return the key of your entity, as defined in your configuration file.

Then, register your service in the container:

parameters:
    martial_lab.article.class: Martial\LabBundle\Service\ArticleService

services:
    martial_lab.article:
        class: %martial_lab.article.class%
        arguments: [@martial.crud]

As you can see, the martial.crud service must be provided to your service as the first constructor argument. That's all, now you can use the CRUD methods provided by the AbstractCrudService class:

  • findAll: Returns an array of all the objects found in the table.
  • find: Return a single object.
  • save: Create or update an object.
  • delete: Delete an object.

For convenience, the class also provides some other methods:

  • createForm: Returns an instance of \Symfony\Component\Form\Form.
  • saveForm: Save a form. You must provide the current request to the service with the setRequest method before using it.
  • getCurrentEntity: Returns the entity used by the methods createForm and saveForm.
  • getCurrentForm: Returns the form used by the method saveForm.
  • getRepository: Returns your ORM repository in order to use your custom methods.

You can find here an example of a controller using such a CRUD service.

Cache

This bundle comes with a native compatibility with Sonata Cache. For example, you can configure your application to use a memcached server with this configuration:

# app/config.yml
sonata_cache:
    caches:
        memcached:
            prefix: my-prefix
            servers:
                - { host: 127.0.0.1, port: 11211, weight: 0 }

You can declare this cache backend to be used by one of your entity:

# app/config.yml
martial_crud:
    entities:
        article:
            repository: MartialLabBundle:Article
            entity_namespace: Martial\LabBundle\Entity\Article
            form_type_namespace: Martial\LabBundle\Form\ArticleType
            cache:
                adapter: sonata.cache.memcached
                ttl: 3600 # Not required, 3600 seconds is the default value

Imagine that your service exposes a method to retrieve the articles with even IDs, here is an example of implementation:

<?php

namespace Martial\LabBundle\Service;

use Martial\CrudBundle\Service\AbstractCrudService;

class ArticleService extends AbstractCrudService
{
    /**
     * Define the entity key used by the CRUD manager.
     *
     * @return string
     */
    public function getEntityKey()
    {
        return 'article';
    }

    /**
     * Find all articles with even IDs.
     *
     * @return array
     */
    public function findAllWithEvenIds()
    {
        $key = array('articles-even-ids');
        $cacheService = $this->getCrudManager()->getCacheService();

        if ($cacheService->has($key)) {
            $articles = $cacheService->get($key)->getData();
        } else {
            $articles = $this->getRepository()->findAllWithEvenIds();
            $cacheService->set($key, $posts, $this->getCrudManager()->getCacheTtl());
        }

        return $articles;
    }
}

The action of your controller:

public function evenArticlesAction()
{
    $articleService = $this->get('martial_lab.article');
    $articles = $articleService->findAllWithEvenIds();

    return $this->render('MartialLabBundle:Default:even-articles.html.twig', array(
            'articles' => $articles
        )
    );
}