Working with the Sonata Admin Bundle and sonata_type_collection

The Sonata Admin Bundle truly is a jewel of a package that can help you to perform feats of wonder with your admin screens. But there are a few lesser-known tricks that deserve a little more attention than the documentation gives. One such topic is the sonata_type_collection form type. The sonata_type_collection comes in handy when you have a “one-to-many” relationship (i.e. one post may have many tags) and wish to embed the form for tags within the form for posts. Talk about killing two birds with one stone, you can combine any related entities onto the same form and have them all persisted at once. In theory this sounds wonderful, but the devil is in the details. So, without further ado …Компоненты маркетинга

In my example I have a promotion entity with a standard one-to-many bi-directional relationship to promo_rules try this site. I’ve tried this with many-to-many associations, but sonata complains.

Next we go ahead and create Sonata Admin classes for each entity. Here is the PromotionAdmin:

And here is the PromoRuleAdmin:

The trick to notice here is that I actually commented out the “promotion” field relationship here? We want to create an admin for promo_rule that does NOT include the related promotion field. Why? Because we want to be able to specify the promotion in the parent form (the promotion form). Our promo_rule form will be embedded within the promotion form. If you’re still with me, then the next question becomes, how exactly do we attach the promo_rule to the promotion if its omitted from the form?

The answer:

// in the PromotionAdmin

Yes indeed, the sonata admin class allows for prePersist and preUpdate calls that allows us to set the promotion for the rule before persisting. Of course don’t forget to declare your admin classes as services in your configs. Other than that, I hope that this helps somebody out there.

9 thoughts on “Working with the Sonata Admin Bundle and sonata_type_collection

  1. Mehmet

    Hi,first of all, thanks you!

    But I have a problem:
    The functions “prePersist” and “preUpdate” are nor exectuted…
    I recognized the following behavior:
    If Im trying to add a new – in your given example – PromotionRule via the “New”-Button in the “PromotionAdmin”-Formular, the program navigates to the “PromoRuleAdmin”. Therefore the “prePersist” and “preUpdate” in the “PromotionAdmin” is never reached.

    What could cause this problem?

    Thanks! Mehmet

    Reply
  2. Florin

    How would you make it allow rule deletions? There is a checkbox next to every rule, but no delete button (which probably should work by ajax so that it doesn’t break the parent edit).

    Reply
    1. mhill Post author

      Rule deletions are handled on save. You simply check the checkbox next to each rule you wish to delete and when you save the entire promotion the rules checked for deletion will be deleted.

      Reply
  3. Nelson

    I’ve been using this approach for months (maybe since you published this post), but now I’m trying to achieve the same functinoaly by using the same trick (but now with Symfony 2.3.9, Sonata User 2.2.2 and Sonata Admin 2.2.9) and it doesn’t work anymore. I haven’t implement your example exactly, but in case I would, this would be the output:

    The current field `rules` is not linked to an admin. Please create one for the target entity : ``

    In my case, i always had the entities Emails and Phones linked to User (of the Sonata User Bundle). So I used to have the many email and phones for one user, instead to add an user to email address or a phone number, so the error message is:

    The current field `emails` is not linked to an admin. Please create one for the target entity : ``

    Any one else having the issue?

    Reply
  4. mofodojodino

    Hi this works great when you only have the requirement to edit/create from an embedded form, I however have to do so from an embedded and non embedded form. Is there a way of detecting that the Rule in this case is being edited as an individual entity or as a relationship of a Promotion.

    I need this so that I can show a list of Promotions while editing an individual Rule but not show the list of Promotion’s when editing the Promotion itself.

    Hope this makes sense!

    Reply
  5. mofodojodino

    I figured out how to do this, so if anyone else comes across this same issue hopefully this will help.

    You need to access the Root of the admin object and then you can test if it is an instance of the Rule or of the Promotion.

    $rootSubject = $this->getRoot()->getSubject();
    if ($rootSubject instanceof Rule) {
    … do something for rule
    } else {
    … do something else
    }

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *