Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sonata admin - child admin class

I have an Order entity, which can have multiple LineItem entities associated.

I've created an Admin class for Order and an Admin class for LineItem. But I need the LineItem Admin class to be a child of the Order Admin class.

In the LineItemAdmin class, I've set protected $parentAssociationMapping = 'order';.

Also, in the OrderAdmin class configureFormFields method, I have added ->add('lineItems', 'sonata_type_model').

However, it still doesn't work. The list of line items in the order form are not clickable, so I cannot see how to get from the Order admin form to say the LineItem admin list page.

Are there routes that need to be configured? Are there changes to the lineItems form field that I need to make?

It's been very difficult to find any good documentation on the Sonata Admin bundle, so any help would be appreciated.

PS. Even going through the SonataAdminBundle code hasn't helped, as the code is very difficult to follow owing to its complexity.

like image 881
agentar Avatar asked Jan 12 '12 19:01

agentar


2 Answers

Having just gone through the same problems with undocumented functionality, the only steps you appear to have missed are calling addChild and configureSideMenu on the parent OrderAdmin class.

This solution will create a separate page off a sidemenu which will contain the lineItems, they will not be embedded in the OrderAdmin form (I'm not sure that this is possible).

There aren't any routes to be configured, as SonataAdmin handles this for you.

Here's an example parent admin class, using annotations:

namespace YourVendor\YourBundle\Admin;

use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\Tag;
use JMS\DiExtraBundle\Annotation\Inject;
use JMS\DiExtraBundle\Annotation\InjectParams;

use Knp\Menu\ItemInterface as MenuItemInterface;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Admin\AdminInterface;

/**
 * @Service("sonata.admin.order")
 * @Tag("sonata.admin", attributes={"manager_type"="orm", "group"="Orders", "label"="Orders"})
 */
class OrderAdmin extends Admin
{
    /**
     * @InjectParams({
     *     "code" = @Inject("%your.parameters.code%"),
     *     "class" = @Inject("%your.parameters.class%"),
     *     "baseControllerName" = @Inject("%your.parameters.controller%"),
     *     "lineItems" = @Inject("sonata.admin.line_item")
     * })
     */
    public function __construct($code, $class, $baseControllerName, $lineItems)
    {
        parent::__construct($code, $class, $baseControllerName);

        $this->addChild($lineItems);
    }

    protected function configureSideMenu(MenuItemInterface $menu, $action, AdminInterface $childAdmin = null)
    {
        if (!$childAdmin && !in_array($action, array('edit', 'show'))) { return; }

        $admin = $this->isChild() ? $this->getParent() : $this;
        $id = $admin->getRequest()->get('id');

        $menu->addChild('Show Order', array('uri' => $admin->generateUrl('show', array('id' => $id))));
        $menu->addChild('Edit Order', array('uri' => $admin->generateUrl('edit', array('id' => $id))));
        $menu->addChild('Line items', array('uri' => $admin->generateUrl('sonata.admin.line_item.list', array('id' => $id))));
    }
}

If you use XML or YML for your services you probably won't need the __construct method as the addChild calls can go in the service definition.

At the time of writing there's an open issue with the JMS DiExtra Bundle with pull request for a dedicated @Admin annotation which may also avoid this requirement. It's been quiet for a couple of weeks though.

like image 64
Barry Avatar answered Nov 19 '22 09:11

Barry


You can to the following:

// Order Entity
/**
 * @ORM\OneToMany(targetEntity="OrderItem", mappedBy="invoice", cascade={"persist", "remove"}, orphanRemoval=true)
 * 
 */
protected $items;
...



// OrderAdmin.php
protected function configureFormFields(FormMapper $formMapper)
{
        $formMapper
        ->with('Order Items')
            ->add('items', 'sonata_type_collection', array('required' => true,
                                                           'by_reference' => false,
                                                           ),
                                                     array('edit' => 'inline',
                                                           'inline' => 'table',))
 ....

Make sure that you have also an OrderItem Admin. Thats necessary because of the sonata_type_collection needs an Admin class to work.

That solution works fine for in my invoice bundle with many invoice items.

like image 28
sensi Avatar answered Nov 19 '22 11:11

sensi