I am using the FPNTagBundle and I would like to have a text field to add tags to entities that works in the same way as the one on this site.
I can create a new entity with tags no problem by using explode but when I come to edit the entity again, I get something like this in the text field.
Doctrine\Common\Collections\ArrayCollection#0000000062a07bb50000000047044868
Is there a way I can pre populate a text field with the array collection, so that all of the tags appear, separated by a space?
Here's what I currently have in my controller:
public function editpageAction(Request $request, $id = NULL)
{
$em = $this->getDoctrine()->getEntityManager();
$tagManager = $this->get('fpn_tag.tag_manager');
$page = new Page();
if ( ! empty($id))
{
$page = $em->getRepository('ContentBundle:Page')->findOneById($id);
$tagManager->loadTagging($page);
}
$form = $this->createForm(new PageType(), $page);
if ($request->isMethod('POST'))
{
$form->bind($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($page);
$em->flush();
return $this->redirect($this->generateUrl('content_admin_list_sections'));
}
}
return $this->render('ContentBundle:Admin:page.html.twig', array('form' => $form->createView()));
}
Any advice appreciated.
Thanks
This is what the Data transfomers are made for.
How to use Data Transformers
A simple example:
public function transform($tags)
{
$tags = $tags->toArray();
if (count($tags) < 1)
return '';
else
return implode(' ', $tags);
}
public function reverseTransform($string)
{
$tags = new ArrayCollection();
$tagsArray = explode(' ', $string);
if (count($tagsArray) > 0)
$tags = new ArrayCollection($tagsArray);
return $tags;
}
Related
In my project I want to use the object created by my precedent form:
Here is the schema of my database:
My QuizController
public function creation(Request $request){
$quiz = new Quiz();
$user = $this->getUser();
$formQuiz = $this->createForm(QuizType::class, $quiz);
$formQuiz->handleRequest($request);
if ($formQuiz->isSubmitted() && $formQuiz->isValid() ) {
$quiz->setCreatedAt(new DateTimeImmutable());
$quiz->setCreatedBy($user);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($quiz);
$entityManager->flush();
return $this->redirectToRoute('creation_questions');
}
return $this->render('quiz/creation.html.twig', [
'formQuiz' => $formQuiz->createView(),
]);
}
And my QuestionController that must be connected with the quiz form
public function creation_questions(Request $request){
$quiz = ?
$question = new Questions();
$formQuestions = $this->createForm(QuestionType::class, $question);
$formQuestions->handleRequest($request);
if ($formQuestions->isSubmitted() && $formQuestions->isValid() ) {
$question->setCreatedAt(new DateTimeImmutable());
$question->setQuiz($quiz);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($question);
$entityManager->flush();
return $this->redirectToRoute('home');
}
return $this->render('questions/questions.html.twig', [
'formQuestion' => $formQuestions->createView()
]);
}
What do I have to write in place of the '?'?
You don't show your routing but you could use paramConverte "magic" from SensioFrameworkExtraBundle and do something like this.
/**
* #Route("/some-route/{id}", name="some_route_name")
*/
public function creation_questions(Request $request, Quiz $quiz)
{
$question = new Questions();
$formQuestions = $this->createForm(QuestionType::class, $question);
$formQuestions->handleRequest($request);
if ($formQuestions->isSubmitted() && $formQuestions->isValid()) {
$question->setCreatedAt(new DateTimeImmutable());
$question->setQuiz($quiz);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($question);
$entityManager->flush();
return $this->redirectToRoute('home');
}
return $this->render('questions/questions.html.twig', [
'formQuestion' => $formQuestions->createView()
]);
}
Where the {id} part of /someRoute/{id} is the Quiz Id. Symfony should automagically fetch the Quiz matching that id. Or you can be more explicit about how the param converter should interpret such a value. More info here https://symfony.com/bundles/SensioFrameworkExtraBundle/current/annotations/converters.html
Alternatively, you could pass the quiz id and fetch the quiz manually (less magic but totally legit).
/**
* #Route("/some-route/{id}", name="some_route_name")
*/
public function creation_questions(Request $request, int $id)
{
$entityManager = $this->getDoctrine()->getManager();
$quiz = $entityManager->getRepository(Quiz::class)->find($id);
$question = new Questions();
$formQuestions = $this->createForm(QuestionType::class, $question);
$formQuestions->handleRequest($request);
if ($formQuestions->isSubmitted() && $formQuestions->isValid()) {
$question->setCreatedAt(new DateTimeImmutable());
$question->setQuiz($quiz);
$entityManager->persist($question);
$entityManager->flush();
return $this->redirectToRoute('home');
}
return $this->render('questions/questions.html.twig', [
'formQuestion' => $formQuestions->createView()
]);
}
I have many to many relationships between posts and tags
The problem is when I want to get the post id and the tag id to link them in their immediary table I did a simple query to do that and I used latest() method in laravel query builder and it threw this error:
Method Illuminate\Support\Collection::latest does not exist.
This is my store function:
public function store(Request $request)
{
{
$this->validate($request,[
'title'=>'required',
'body'=>'required',
'tags'=>'required',
'slug'=>'required',
]);
$input = $request->all();
$tags = explode(",", $request->tags);
if ($input != null) {
$post = post::create($input);
$post->tag($tags);
// the problem is in this two lines
$post_id = DB::table('posts')->pluck('id')->latest();
$tagged_id = DB::table('tagging_tagged')->pluck('id')->latest();
//
dd($tagged_id , $post_id);
$relationship = new post_tagged;
$relationship->post_id = $post_id;
$relationship->tagged_id = $tagged_id;
$relationship->save();
return redirect('/admin/blog')->with('success' , 'Post added successfully');
}
return redirect('/admin/blog');
}
}
the idea that I want to achieve with those two lines is to get the latest id in the post table and in the tags table (which is the newest post)
and then storing it in the immediary table
I solved the problem by doing this
store function
public function store(Request $request)
{
{
$this->validate($request,[
'title'=>'required',
'body'=>'required',
'tags'=>'required',
'slug'=>'required',
]);
$input = $request->all();
$tags = explode(",", $request->tags);
if ($input != null) {
$post = post::create($input);
$post->tag($tags);
$post_id = DB::table('tagging_tagged')->latest('taggable_id')->first();
$post_id = $post_id->taggable_id;
$tagged_id = DB::table('tagging_tagged')->latest('id')->first();
$tagged_id = $tagged_id->id;
$relationship = new post_tagged;
$relationship->post_id = $post_id;
$relationship->tagged_id = $tagged_id;
$relationship->save();
return redirect('/admin/blog')->with('success' , 'Post added successfully');
}
return redirect('/admin/blog');
}
public function addAction(){
$em = $this -> getDoctrine() -> getEntityManager();
$a = new Button;
$form = $this -> createForm(new ButtonType());
$request = $this->get('request');
$value=0;
if($request->getMethod() == 'POST'){
$form->handleRequest($request);
$value = $form->get('addButton')->isClicked();
echo $value;
if($value =1){
$a ->setTextBox(1)
->setPlainText(1)
->setCheckBox(1)
->setRadio(1)
->setButton(1);
$em ->persist($a);
$em ->flush();
}
}
return $this->render('PagePageBundle:Default:add.html.twig', array( 'form' => $form -> createView(),));
}
I want to fill the database by clicking on a button created in the form (need help)
the method isClicked return a boolean value as described in the doc so you can simply check this (in your code you write a wrong if statement: = instead of ==)
So try this code:
$value = $form->get('addButton')->isClicked();
var_dump($value);
if($value){
$a ->setTextBox(1)
->setPlainText(1)
->setCheckBox(1)
->setRadio(1)
->setButton(1);
$em ->persist($a);
$em ->flush();
}
hope this help
I am working on a job portal's site built in Symfony 2.1. I have implemented ewz/EWZSearchBundle for job search process which is as given below:
/**
* Displays a form to create a new Job entity.
*
* #Route("/new", name="job_new")
* #Template("JobBundle:Job:new.html.twig")
*/
public function newAction(Request $request)
{
$entity = new Job();
$form = $this->createForm(new JobType(), $entity);
if('POST'===$request->getMethod()){
$form->bind($request);
if ($form->isValid()) {
$entity->setOwner($this->getEmployer());
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
$location = $entity->getLocation();
$loName = array();
foreach ($location as $key => $loc) {
$loName[] = $loc->getName();
}
$industry = $entity->getIndustry();
$inName = array();
foreach ($industry as $key => $ind) {
$inName[] = $ind->getTitle();
}
$skills = $entity->getSkills();
$skillName = array();
foreach ($skills as $key => $skl) {
$skillName[] = $skl->getTitle();
}
$education = $entity->getEducation();
$educationName = array();
foreach ($education as $key => $edu) {
$educationName[] = $edu->getTitle();
}
$search = $this->get('ewz_search.lucene');
$document = new Document();
$document->addField(Field::keyword('key', $entity->getId()));
$document->addField(Field::text('title', $entity->getTitle()));
$document->addField(Field::text('url', $this->generateUrl('job_show', array('slug' => $entity->getSlug()))));
$document->addField(Field::unstored('body', $entity->getDescription()));
$document->addField(Field::text('location', implode(" ", $loName)));
$document->addField(Field::text('industry', implode(" ", $inName)));
$document->addField(Field::text('skills', implode(" ", $skillName)));
$document->addField(Field::text('education', implode(" ", $educationName)));
$search->addDocument($document);
$search->updateIndex();
return $this->redirect($this->generateUrl('job_show', array('slug' => $entity->getSlug())));
}
}
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
It is working very fine when a candidate is searching jobs by any of following fields: location, industry, skills or education. But there are two issues of mine:
In this process for every field (locations, skills, industry or education) only one job search is applicable while I want separate search forms, for example in location-wise search, only location field is matched not the other remaining fields.
The second problem is when an employer deletes his job, the indexes of deleted jobs are also shown in the search process while after the job was deleted, the index of the deleted job should also be deleted from search index.
I have tried to delete the search index on the time of job_delete action by following code:
/**
* Deletes a Job entity
* #Route("/{slug}/delete", name="job_delete")
* #Method("POST")
*/
public function deleteAction(Request $request, $slug)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('JobBundle:Job')
->findOneBy(array('slug' => $slug));
if (!$entity) {
throw $this->createNotFoundException('Unable to find Job entity.');
}
$form = $this->createDeleteForm($entity->getSlug());
$form->bind($request);
if ($form->isValid()) {
$this->checkOwnerSecurity($entity);
$em->remove($entity);
$em->flush();
$search = $this->get('ewz_search.lucene');
$index = $search->getIndex();
$removePath = 'http://localhost/Jobtook/web/app_dev.php/employer/job/{slug}/delete';
$hits = $index->find('job_delete' . $removePath);
foreach ($hits as $hit) {
$index->delete($hit->id);
}
}
return $this->redirect($this->generateUrl('job'));
}
private function createDeleteForm($slug)
{
return $this->createFormBuilder(array('slug' => $slug))
->add('slug', 'hidden')
->getForm()
;
}
But by this code when I create many jobs and delete only one job, then all jobs are deleted from the search index even remaining jobs, that still exist in database. I don't know what I am doing wrong.
I try this cookbook about embed form:
http://symfony.com/doc/current/cookbook/form/form_collections.html
But the embed foreign key (task_id field in Tag table) is not save, always NULL
Here the complete code: https://gist.github.com/1755140
Do you know why?
Thank
Edit::
My trouble was in process form action. Like the tag form is embed dynamically, so i don't know how many tag(s) i will have. If i add in createAction
$tag1 = new Tag();
$task->addTags($tag1);
only the first embed form was correctly save! How to save the other tags?
public function createAction(Request $request)
{
$task = new Task();
$tag1 = new Tag();
$task->addTags($tag1);
$form = $this->createForm(new TaskType(), $task);
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($task);
$em->flush();
return $this->redirect($this->generateUrl('new_task', array('id' => $task->getId())));
}
return array(
'form' => $form->createView()
);
}
Edit2:
My solution which resolve the trouble, what do you think about it? Better?
public function createAction(Request $request)
{
$task = new Task();
$tasks = $request->request->get('task', array());
if (isset($tasks['tags'])) {
$tags = $tasks['tags'];
foreach($tags as $tag) {
$tag = new Tag();
$task->addTags($tag);
}
}
$form = $this->createForm(new TaskType(), $task);
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($task);
$em->flush();
return $this->redirect($this->generateUrl('new_task', array('id' => $task->getId())));
}
return array(
'form' => $form->createView()
);
}
Edit3:
A much better alternative (not tested again)
http://www.siteduzero.com/tutoriel-3-523899-creer-des-formulaires-avec-symfony2.html#ss_part_2
public function createAction(Request $request)
{
$task = new Task();
$form = $this->createForm(new TaskType(), $task);
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($task);
foreach($task->getTags() as $tag) {
$em->persist($tag);
}
$em->flush();
return $this->redirect($this->generateUrl('new_task', array('id' => $task->getId())));
}
return array(
'form' => $form->createView()
);
}
In TaskController on line 29 try to use $task->addTags($tag1); instead of $task->getTags()->add($tag1);
I don't understand. Is this solution wrong?
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
foreach($task->getTags() as $tag) {
$tag->setTask($task);
}
$em->persist($task);
$em->flush();
return $this->redirect($this->generateUrl('new_task', array('id' => $task->getId())));
}
It works and it seems simpler.