简体   繁体   中英

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM