How to use Sonata Notification Bundle? - symfony

I want to add Notifications system in my symfony (2.8) project, i thought that Sonata Notification Bundle could help, but turns out that i do not know how to use it, i install it very well, but i do not know how to use it in my project.
i need some help about this bundle, some tutorial or so.
or
is there another way to use notification system, please tell me,
thank you in advance
That the controller that i want to use notification bundle
namespace LocationBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use LocationBundle\Entity\Agence;
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* Agence controller.
*
*/
class AgenceController extends Controller
{
/**
* Lists all Agence entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$agences = $em->getRepository('LocationBundle:Agence')->findAll();
return $this->render('agence/index.html.twig', array(
'agences' => $agences,
));
}
/**
* Creates a new Agence entity.
*
*/
public function newAction(Request $request)
{
$agence = new Agence();
$form = $this->createForm('LocationBundle\Form\AgenceType', $agence);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($agence);
$em->flush();
return $this->redirectToRoute('agence_show', array('id' => $agence->getId()));
}
return $this->render('agence/new.html.twig', array(
'agence' => $agence,
'form' => $form->createView(),
));
}
/**
* Finds and displays a Agence entity.
*
*/
public function showAction(Agence $agence)
{
$deleteForm = $this->createDeleteForm($agence);
return $this->render('agence/show.html.twig', array(
'agence' => $agence,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing Agence entity.
*
*/
public function editAction(Request $request, Agence $agence)
{
$deleteForm = $this->createDeleteForm($agence);
$editForm = $this->createForm('LocationBundle\Form\AgenceType', $agence);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($agence);
$em->flush();
return $this->redirectToRoute('agence_edit', array('id' => $agence->getId()));
}
return $this->render('agence/edit.html.twig', array(
'agence' => $agence,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Deletes a Agence entity.
*
*/
public function deleteAction(Request $request, Agence $agence)
{
$form = $this->createDeleteForm($agence);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($agence);
$em->flush();
}
return $this->redirectToRoute('agence_index');
}
/**
* Creates a form to delete a Agence entity.
*
* #param Agence $agence The Agence entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(Agence $agence)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('agence_delete', array('id' => $agence->getId())))
->setMethod('DELETE')
->getForm()
;
}

I am pretty sure the Sonata Notification Bundle is not what you are searching. The Word "Notification" in the title is in your case a bit misleading. The Bundle is used to postpone actions/events using a queue system like RabbitMQ.
For what you are searching: Take a look at the Symfony's own "Flash Messages": http://symfony.com/doc/current/book/controller.html#flash-messages
It's very easy to implement and you don't need an additional bundle.

Related

Symfony 2: Dynamic Form Event returns InvalidArgumentException only when editing

I got an entity called 'Activity', that defines a relation between 2 more entities, 'Service' and 'Location'.
Both 'Service' and 'Location', use another entity called 'Allocation', to define what services can be used in a concrete location.
When I create a new Activity, after selecting a service I want the location choice field update with the values defined by allocation.
I have followed symfony documentation to create this 'location' dependent choice field in the form.
Dynamic Form Modification
All works great on create/new form, but when i try to edit service field value in an already created Activity, location field does not update and the symfony profiler shows me the following message:
Uncaught PHP Exception Symfony\Component\PropertyAccess\Exception\InvalidArgumentException: "Expected argument of type "AppBundle\Entity\Location", "NULL" given" at F:\xampp\htdocs\gcd\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php line 253 Context: { "exception": "Object(Symfony\Component\PropertyAccess\Exception\InvalidArgumentException)" }
This is a section of my Activity Entity
/**
* Activity
*
* #ORM\Table(name="activity")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ActivityRepository")
*/
class Activity
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Service
*
* #ORM\ManyToOne(targetEntity="Service", fetch="EAGER")
* #ORM\JoinColumn(name="service_id", referencedColumnName="id", nullable=false)
*/
private $service;
/**
* #var Location
*
* #ORM\ManyToOne(targetEntity="Location", fetch="EAGER")
* #ORM\JoinColumn(name="location_id", referencedColumnName="id", nullable=false)
*/
private $location;
My Controller.
/**
* Creates a new Activity entity.
*
* #Route("/new", name="core_admin_activity_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$activity = new Activity();
$form = $this->createForm('AppBundle\Form\ActivityType', $activity);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$locationAvailable = $this->isLocationAvailable($activity);
$activityOverlap = $this->hasOverlap($activity);
if($locationAvailable && !$activityOverlap){
$em = $this->getDoctrine()->getManager();
$em->persist($activity);
$em->flush();
return $this->redirectToRoute('core_admin_activity_show', array('id' => $activity->getId()));
}
}
return $this->render('activity/new.html.twig', array(
'activity' => $activity,
'form' => $form->createView(),
));
}
/**
* Displays a form to edit an existing Activity entity.
*
* #Route("/{id}/edit", name="core_admin_activity_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Activity $activity)
{
$deleteForm = $this->createDeleteForm($activity);
$editForm = $this->createForm('AppBundle\Form\ActivityType', $activity);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$locationAvailable = $this->isLocationAvailable($activity);
$activityOverlap = $this->hasOverlap($activity);
if($locationAvailable && !$activityOverlap){
$em = $this->getDoctrine()->getManager();
$em->persist($activity);
$em->flush();
return $this->redirectToRoute('core_admin_activity_show', array('id' => $activity->getId()));
}
}
return $this->render('activity/edit.html.twig', array(
'activity' => $activity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
My FormType
class ActivityType extends AbstractType
{
private $em;
public function __construct(EntityManager $entityManager)
{
$this->em = $entityManager;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('service', EntityType::class, array(
'class' => 'AppBundle:Service',
'placeholder' => 'elige servicio',
))
->add('location', EntityType::class, array(
'class' => 'AppBundle:Location',
'choices' => array(),
))
->add('name')
->add('virtual')
->add('customerSeats')
->add('customerVacants')
->add('employeeSeats')
->add('firstDate', 'date')
->add('lastDate', 'date')
->add('weekday')
->add('beginTime', 'time')
->add('endTime', 'time')
->add('admissionType')
->add('status');
$formModifier = function (FormInterface $form, Service $service = null) {
$locations = null === $service ? array() : $this->em->getRepository('AppBundle:Allocation')->findLocationsByService($service);
$form->add('location', EntityType::class, array(
'class' => 'AppBundle:Location',
'choices' => $locations,
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
$formModifier($event->getForm(), $data->getService());
}
);
$builder->get('service')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$service = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $service);
}
);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Activity'
));
}
}
javaScript function
<script>
var $service = $('#activity_service');
// When sport gets selected ...
$service.change(function() {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected service value.
var data = {};
data[$service.attr('name')] = $service.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
// Replace current position field ...
$('#activity_location').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#activity_location')
);
}
});
});
</script>
Any help will be great, thanks.
I had a similar problem, I found a solution : Symfony - dynamic drop down lists not working only when editing
I had also faced similar issue and on tracing found that it is the EntityType class on other dropdown that is causing the problem while editing the form
The solution is to submit the full form via ajax instead of only one field like in the case of new form.
So change
var data = {};
data[$service.attr('name')] = $service.val();
To
var data = $form.serializeArray()
That should fix the issue.

Symfony 2.3 PHP unit test using mock objects

Im new in Symfony and phpunit and im trying to do phpunit testing to the following codes.
/**
* Creates a form to delete a Product entity by id.
*
* #param mixed $id The entity id
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('product_delete', array('id' => $id)))
->setMethod('DELETE')
->add('submit', 'submit', array('label' => 'Delete'))
->getForm()
;
}
/**
* Finds and displays a Product entity.
*
* #Route("/{id}", name="product_show")
* #Method("GET")
* #Template()
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('AppBundle:Product')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Product entity.');
}
$deleteForm = $this->createDeleteForm($id);
return array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
);
}
Can anyone help me
My Unit Testing code (just some part)
$mockFormBuilder = $this->getMockBuilder('Symfony\Component\Form\FormBuilder')
->disableOriginalConstructor()
->getMock();
$mockFormBuilder->expects($this->any())
->method('setAction')
->will($this->returnValue(true));
And yes Im stock .. i dont know how to test setMethod, add and getForm to return a form where i can use createView Method again.

Automatically set related entity id in one to many relationship Symfony

I have a many to one related entities and everytime I create a new comment which is related to Project, I want to automatically save the realted project_id.
comment
id
comment
manyToOne
project:
targetEntity: Project
cascade: { }
mappedBy: null
inversedBy: comments
joinColumn:
name: project_id
referencedColumnName: id
orphanRemoval: false
project
id
projectName
oneToMany:
comments:
targetEntity: Comment
mappedBy: project
When using Annotation, this can be done easily using the ParamConverter, but in this case I am using Yaml format.I am using the Symfony nice Crud command to automatically generate forms and templates as well as the controllers.
I tried in controller this way
public function createAction(Request $request, Project $project)//Project
{
$entity = new Comment();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
// $entity->setProject($projectName->getProject());
$entity->setProject($project);
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('comment_show', array('id' => $entity->getId())));
}
Then in form,
{{ form(form) }}
The problem with this is it will generate a form with a dropdown with hundreds of project_id in comment project_id field
Then when submitted
Unable to guess how to get a Doctrine instance from the request information.
I am thinking of writing a jquery autocomplete to solve this but if there is more shortcut way of doing this, like the annotation Paramconverter, I am glad to use it
How would you do it so that the related project_id will be automatically saved?
Update
This is exactly the code when running Symfony2 nice crud command in console
<?php
namespace EdgeWeb\Project\EmployeeBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use EdgeWeb\Project\EmployeeBundle\Entity\Comment;
use EdgeWeb\Project\EmployeeBundle\Form\CommentType;
/**
* Comment controller.
*
*/
class CommentController extends Controller
{
/**
* Lists all Comment entities.
*
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('EmployeeBundle:Comment')->findAll();
return $this->render('EmployeeBundle:Comment:index.html.twig', array(
'entities' => $entities,
));
}
/**
* Creates a new Comment entity.
*
*/
public function createAction(Request $request)
{
$entity = new Comment();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('comment_show', array('id' => $entity->getId())));
}
return $this->render('EmployeeBundle:Comment:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Creates a form to create a Comment entity.
*
* #param Comment $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Comment $entity)
{
$form = $this->createForm(new CommentType(), $entity, array(
'action' => $this->generateUrl('comment_create'),
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
return $form;
}
/**
* Displays a form to create a new Comment entity.
*
*/
public function newAction()
{
$entity = new Comment();
$form = $this->createCreateForm($entity);
return $this->render('EmployeeBundle:Comment:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
/**
* Finds and displays a Comment entity.
*
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('EmployeeBundle:Comment')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Comment entity.');
}
$deleteForm = $this->createDeleteForm($id);
return $this->render('EmployeeBundle:Comment:show.html.twig', array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing Comment entity.
*
*/
public function editAction($id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('EmployeeBundle:Comment')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Comment entity.');
}
$editForm = $this->createEditForm($entity);
$deleteForm = $this->createDeleteForm($id);
return $this->render('EmployeeBundle:Comment:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Creates a form to edit a Comment entity.
*
* #param Comment $entity The entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Comment $entity)
{
$form = $this->createForm(new CommentType(), $entity, array(
'action' => $this->generateUrl('comment_update', array('id' => $entity->getId())),
'method' => 'PUT',
));
$form->add('submit', 'submit', array('label' => 'Update'));
return $form;
}
/**
* Edits an existing Comment entity.
*
*/
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('EmployeeBundle:Comment')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Comment entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('comment_edit', array('id' => $id)));
}
return $this->render('EmployeeBundle:Comment:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Deletes a Comment entity.
*
*/
public function deleteAction(Request $request, $id)
{
$form = $this->createDeleteForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('EmployeeBundle:Comment')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Comment entity.');
}
$em->remove($entity);
$em->flush();
}
return $this->redirect($this->generateUrl('comment'));
}
/**
* Creates a form to delete a Comment entity by id.
*
* #param mixed $id The entity id
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('comment_delete', array('id' => $id)))
->setMethod('DELETE')
->add('submit', 'submit', array('label' => 'Delete'))
->getForm()
;
}
}
Then in FormType
$builder
->add('comment')
->add('createdby')
->add('updatedby')
->add('datecreated')
->add('dateupdated')
->add('project')//related entity
;
I see at least 3 questions in your question...
For the error :
Unable to guess how to get a Doctrine instance from the request
information,
I don't know why it's happening, but it doesn't seem related directly to the relationship question... Maybe try to suppress fields 'createdby', 'updatedby', 'datecreated', 'dateupdated'from the form builder, as they are not in your mapping yaml file (or maybe you just didn't show them) - whatever, you should probably not display them in the form, but complete these fields in the controller or via prePersist actions, as the user doesn't have to know about them.
Then for the problem that the project field of the form displays a dropdown with project ids : you can specify in the form builder which property of the comment entity you want to display, via the choice_label option, like this :
$builder
->add('comment')
->add('project', 'entity', array(
'class' => 'YourBundle:Project',
'choice_label' => 'projectName',
));
This way, you still will have a dropdown, but with project names displayed instead of ids. The 'entity' file field type has many other options, see the documentation.
For your last question, which is you would like to have a text field with autocomplete instead of a dropdown, you can manage it with a data transformer + a JS autocompleter. See this answer for more information.

Persisting self referencing entity not works

I create an entity with self referencing. My entity look like this:
class Question
{
/**
* #ORM\OneToMany(targetEntity="Question", mappedBy="parent")
**/
private $children;
/**
* #ORM\ManyToOne(targetEntity="Question", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id")
**/
private $parent;
}
And i create a form to edit a Question. With this form i can add many childs to a Question. After i post this form i will save the childs for a parent Object. But the persisting of childs for a parent fails, nothing happens in the database.
public function manageDependencyAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$question = $em->getRepository('AppMyBundle:Question')->find($id);
if (!$question) {
$this->get('session')->getFlashBag()->add('danger', $this->get('translator')->trans('objectNotFound'));
return $this->redirect($this->generateUrl('app_question_list'));
}
$form = $this->createForm($this->get('form.type.question'), $question, array())->add('save', 'submit', array('label' => 'save', 'translation_domain' => 'messages', 'attr' => array('class' => 'btn btn-primary')));
$form->handleRequest($request);
if ($form->isValid()) {
// dump($question->getChildren()); // This is not empty. In this array are the selected childs.
$em->persist($question);
$em->flush();
}
}
change your entity methods:
public function addChild(Question $children)
{
$this->children[] = $children;
$children->setParent($this);
return $this;
}

Insert foreign key in Symfony2 in OneToMany relation

I have a problem with adding data to the db. I have two entities InternalDocument and InternalDocumentProduct in OneToMany relation.
In InternalDocument:
/**
* #ORM\OneToMany(targetEntity="InternalDocumentProduct", mappedBy="document", cascade={"all"})
**/
protected $products;
In InternalDocumentProduct
/**
* #ORM\ManyToOne(targetEntity="InternalDocument", inversedBy="products")
* #ORM\JoinColumn(name="document_id", referencedColumnName="id")
* */
protected $document;
When I create new InternalDocument I need to insert InternalDocumentProduct too. But When i call persist() method, InternalDocumentProduct is saved without document_id field. It's null. This is my createForm() method in InternalDocumentController:
/**
* Creates a new InternalDocument entity.
*
*/
public function createAction(Request $request)
{
$entity = new InternalDocument();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
if ($form->isValid()) {
$em->persist($entity);
$em->flush();
$em = $this->getDoctrine()->getManager();
foreach($entity->getProducts() as $p) {
$em->persist($p);
}
$em->flush();
return $this->redirect($this->generateUrl('acme_warehouse_documents'));
}
return $this->render('AcmeWarehouseBundle:InternalDocument:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
Can anyone help me?
EDIT:
I resolve this problem. I modified createAction method:
/**
* Creates a new InternalDocument entity.
*
*/
public function createAction(Request $request)
{
$entity = new InternalDocument();
$form = $this->createCreateForm($entity);
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
if ($form->isValid()) {
foreach($entity->getProducts() as $p) {
$p->setDocument($entity);
}
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('acme_warehouse_documents'));
}
return $this->render('AcmeWarehouseBundle:InternalDocument:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}

Resources