I would like a user to be able to leave a review(comment) about a user on it public profile.
Once I refresh the public profile page I have this error:
An exception has been thrown during the rendering of a template
("Controller
"FLY\BookingsBundle\Controller\PostController::commentAction()"
requires that you provide a value for the "$entity" argument (because
there is no default value or because there is a non optional argument
after this one).") in
ApplicationSonataUserBundle:Profile:UserShow.html.twig at line 108.
The url of the public profile look like this :
http://127.0.0.1/symfony/web/app_dev.php/user/show/john/26
Routing.yml
userShow:
pattern: /user/show/{entity}/{slug}
defaults: { _controller: FLYBookingsBundle:Post:userShow }
comment:
pattern: /user/show/{entity}/{slug}
defaults: { _controller: FLYBookingsBundle:Post:comment }
requirements:
_method: POST
PostController.php
public function userShowAction($entity)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ApplicationSonataUserBundle:User')->findBy(array('username' => $entity));
$user = $em->getRepository('ApplicationSonataUserBundle:Avatar')->findBy(array('user' => $entity));
return $this->render('ApplicationSonataUserBundle:Profile:UserShow.html.twig', array('user' => $user,'entity' => $entity));
}
.
public function commentAction(Request $request,$entity)
{
$em = $this->getDoctrine()->getManager();
$user = $this->container->get('security.token_storage')->getToken()->getUser();
$comment = new Comment();
$entity = $em->getRepository('ApplicationSonataUserBundle:User')->findBy(array('username' => $entity));
$form = $this->createForm( new CommentType(),$comment);
dump($form);
if ($this->get('request')->getMethod() == 'POST') {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$comment->setCreatedAt(new \DateTime());
$comment->setApproved(true);
$comment->setRecipient();
$comment->setAuthor($this->container->get('security.token_storage')->getToken()->getUser());
$em->persist($comment);
$em->flush();
$this->get('session')->getFlashBag()->add(
'success',
'Your comment was succesfully added'
);
}
return $this->redirect($this->generateUrl('userShow', array(
'entity' => $entity,
//'slug' => $slug,
)));
}
return $this->render('ApplicationSonataUserBundle:Profile:commentForm.html.twig', array( 'entity' => $entity,'user' => $user,'comment' => $comment,
'form' => $form->createView()));
}
UserShow.html.twig
{% for entity in entity %}
<div class="row">
<div class="col-sm-9">
{{ render(controller('FLYBookingsBundle:Post:comment')) }}
</div>
</div>
{% endfor %}
CommentForm.html.twig
<form action="{{ path('comment', {'entity': entity, 'slug':entity.user.id}) }}" method="POST">
{{ form_start(form) }}
{{ form_errors(form) }}
<div class="form-group">
<label>Review Text</label>
{{ form_widget(form.body, { 'attr': {'class': 'form-control','style': 'width: 100%', } }) }}
{{ form_errors(form.body) }}
</div>
<button style="float: right;font-size: 14px; height: 40px; width: 180px;" type="submit">Leave a Review</button>
{{ form_rest(form) }}
</form>
ADD:
public function userShowAction(Request $request,$entity,$slug)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('ApplicationSonataUserBundle:User')->findBy(array('username' => $entity));
$useravatar = $em->getRepository('ApplicationSonataUserBundle:Avatar')->findBy(array('user' => $entity));
$recipient = $em->getRepository('ApplicationSonataUserBundle:User')->findOneBy(array('id' => $slug));
$comment = new Comment();
$user = new User();
$form = $this->createForm( new CommentType(),$comment);
if ($this->get('request')->getMethod() == 'POST') {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$comment->setCreatedAt(new \DateTime());
$comment->setApproved(true);
$comment->setRecipient($recipient);
dump($entity);
$comment->setAuthor($this->container->get('security.token_storage')->getToken()->getUser());
$em->persist($comment);
$em->flush();
$this->get('session')->getFlashBag()->add(
'success',
'Your comment was succesfully added'
);
}
return $this->redirect($this->generateUrl('userShow', array(
'entity' => $comment->getRecipient(),
'slug' => $slug
)));
}
return $this->render('ApplicationSonataUserBundle:Profile:UserShow.html.twig', array('useravatar' => $useravatar,'user' => $user,'entity' => $entity,'form' => $form->createView()));
}
.
Comment.php
<?php
namespace Application\Sonata\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\HasLifecycleCallbacks
* #ORM\Entity
* #ORM\Entity(repositoryClass="Application\Sonata\UserBundle\Entity\UserRepository")
* #ORM\Table(name="comment")
*
*/
class Comment
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var User
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="commentrecipient")
* #ORM\JoinColumn(onDelete="CASCADE")
*
*/
protected $recipient;
/**
* #var User
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="comment")
*/
protected $author;
/**
* #ORM\Column(name="approved",type="boolean", nullable=true)
*/
protected $approved;
/**
* #var string
*
* #ORM\Column(name="body", type="text")
* #Assert\NotBlank
*/
private $body;
/**
* #ORM\Column(name="createdAt", type="datetime", nullable=false)
*/
protected $createdAt;
/**
* #ORM\Column(name="updatedAt", type="datetime", nullable=false)
*/
protected $updatedAt;
public function __toString()
{
return (string) $this->getRecipient();
}
public function __construct()
{
$this->setCreatedAt(new \DateTime());
$this->setUpdatedAt(new \DateTime());
$this->setApproved(true);
}
}
User.php
/**
* #ORM\OneToMany(targetEntity="Application\Sonata\UserBundle\Entity\Comment", mappedBy="recipient", cascade={"persist"})
* #ORM\JoinColumn(nullable=true)
*/
protected $commentrecipient;
FLYBookingsBundle:Post:comment require parameter.
Change {{ render(controller('FLYBookingsBundle:Post:comment')) }} to
{{ render(controller('FLYBookingsBundle:Post:comment', {'entity' : entity )) }}
in UserShow.html.twig
Related
I want to generate dependent dropdown list in Symfony 3.4
I have followed the exact example(copy and paste) : https://ourcodeworld.com/articles/read/652/how-to-create-a-dependent-select-dependent-dropdown-in-symfony-3
I have created all the tables and populated them.
I really didn't change any thing I want to test the code as it is before using it in my project.
the result :
Update:
Person entity:
/**
* Person
*
* #ORM\Table(name="person")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PersonRepository")
*/
class Person
{
/**
* #var integer
*
* #ORM\Column(name="id", type="bigint")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="last_name", type="string", length=255, nullable=false)
*/
private $lastName;
/**
* #var \AppBundle\Entity\City
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\City")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="city_id", referencedColumnName="id")
* })
*/
private $city;
/**
* #var \AppBundle\Entity\Neighborhood
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Neighborhood")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="neighborhood_id", referencedColumnName="id")
* })
*/
private $neighborhood;
Person type
class PersonType extends AbstractType
{
private $em;
/**
* #param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name')
->add('lastName');
$builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPreSubmit'));
}
protected function addElements(FormInterface $form, City $city = null) {
// 4. Add the province element
$form->add('city', EntityType::class, array(
'required' => true,
'data' => $city,
'placeholder' => 'Select a City...',
'class' => 'AppBundle:City'
));
$neighborhoods = array();
if ($city) {
$repoNeighborhood = $this->em->getRepository('AppBundle:Neighborhood');
$neighborhoods = $repoNeighborhood->createQueryBuilder("q")
->where("q.city = :cityid")
->setParameter("cityid", $city->getId())
->getQuery()
->getResult();
}
$form->add('neighborhood', EntityType::class, array(
'required' => true,
'placeholder' => 'Select a City first ...',
'class' => 'AppBundle:Neighborhood',
'choices' => $neighborhoods
));
}
function onPreSubmit(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
$city = $this->em->getRepository('AppBundle:City')->find($data['city']);
$this->addElements($form, $city);
}
function onPreSetData(FormEvent $event) {
$person = $event->getData();
$form = $event->getForm();
$city = $person->getCity() ? $person->getCity() : null;
$this->addElements($form, $city);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Person'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_person';
}
}
views/Person.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
<h1>Person creation</h1>
{{ form_start(form) }}
{{ form_widget(form) }}
<input type="submit" value="Create" />
{{ form_end(form) }}
<ul>
<li>
Back to the list
</li>
</ul>
{% endblock %}
{% block javascripts %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$('#appbundle_person_city').change(function () {
var citySelector = $(this);
$.ajax({
url: "{{ path('person_list_neighborhoods') }}",
type: "GET",
dataType: "JSON",
data: {
cityid: citySelector.val()
},
success: function (neighborhoods) {
var neighborhoodSelect = $("#appbundle_person_neighborhood");
neighborhoodSelect.html('');
neighborhoodSelect.append('<option value> Select a neighborhood of ' + citySelector.find("option:selected").text() + ' ...</option>');
$.each(neighborhoods, function (key, neighborhood) {
neighborhoodSelect.append('<option value="' + neighborhood.id + '">' + neighborhood.name + '</option>');
});
},
error: function (err) {
alert("An error ocurred while loading data ...");
}
});
});
</script>
{% endblock %}
Person controller:
class PersonController extends Controller
{
/**
* Returns a JSON string with the neighborhoods of the City with the providen id.
*
* #param Request $request
* #return JsonResponse
*/
public function listNeighborhoodsOfCityAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$neighborhoodsRepository = $em->getRepository("AppBundle:Neighborhood");
$neighborhoods = $neighborhoodsRepository->createQueryBuilder("q")
->where("q.city = :cityid")
->setParameter("cityid", $request->query->get("cityid"))
->getQuery()
->getResult();
$responseArray = array();
foreach($neighborhoods as $neighborhood){
$responseArray[] = array(
"id" => $neighborhood->getId(),
"name" => $neighborhood->getName()
);
}
// Return array with structure of the neighborhoods of the providen city id
return new JsonResponse($responseArray);
}
}
AppBundle/config/routing.yml
person_list_neighborhoods:
path: /get-neighborhoods-from-city
defaults: { _controller: "AppBundle:Person:listNeighborhoodsOfCity" }
methods: GET
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I use symfony 3.4.
I create create,delete,edit,show pages for my Project table ..but i get this error when try show one project
Neither the property "fee" nor one of the methods "fee()", "getfee()"/"isfee()" or "__call()" exist and have public access in class "AppBundle\Entity\Project".
My entity class(/Entity/Project.php)
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="project")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ProjectRepository")
*/
class Project
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Payment", mappedBy="id")
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Conversation", mappedBy="id")
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Attachment", mappedBy="id")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
* #Assert\NotBlank(message="please fill title")
* #Assert\Length(min=3,minMessage="message from annotation: field must be at least 3")
*/
private $title;
/**
* #ORM\Column(type="string", length=100)
* #Assert\NotBlank(message="please fill type")
*/
private $type;
/**
* #ORM\Column(type="integer")
* #Assert\NotBlank(message="please fill budget")
*/
private $budget;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime
*/
private $registerDate;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime
*/
private $endDate;
/**
* #ORM\Column(type="integer")
*/
private $prePay;
/**
* #ORM\Column(type="integer")
*/
private $fee;
/**
* #ORM\Column(type="integer", length=1)
*/
private $isPay;
/**
* #ORM\Column(type="integer", length=1)
*/
private $isPrePay;
/**
* #ORM\Column(name="attachmentId", type="string")
*
* #Assert\NotBlank(message="Please, upload the product brochure as a PDF file.")
* #Assert\File(mimeTypes={ "application/zip" })
*/
private $attachmentId;
/**
* #ORM\Column(type="smallint")
*/
private $status;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $user;
public function __construct()
{
$this->registerDate = new \DateTime();
$this->prePay = 0;
$this->fee = 0;
$this->isPay = 0;
$this->isPrePay = 0;
$this->status = 0; //#todo make this better
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
public function getTitle()
{
return $this->title;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getType()
{
return $this->type;
}
public function setType($type)
{
$this->type = $type;
}
public function getBudget()
{
return $this->budget;
}
public function setBudget($budget)
{
$this->budget = $budget;
}
public function getDescription()
{
return $this->description;
}
public function setDescription($description)
{
$this->description = $description;
}
public function getRegisterDate()
{
return $this->registerDate;
}
public function setRegisterDate($register_date)
{
$this->registerDate = $register_date;
}
public function getEndDate()
{
return $this->endDate;
}
public function setEndDate($end_date)
{
$this->endDate = $end_date;
}
public function getPrePay()
{
return $this->prePay;
}
public function setPrePay($pre_pay)
{
$this->prePay = $pre_pay;
}
public function geFee()
{
return $this->fee;
}
public function setFee($fee)
{
$this->fee = $fee;
}
public function getIsPay()
{
return $this->isPay;
}
public function setIsPay($is_pay)
{
$this->isPay = $is_pay;
}
public function setIsPrePay($is_prepay)
{
$this->isPrePay = $is_prepay;
}
public function getIsPrePay()
{
return $this->isPrePay;
}
public function getAttachment()
{
return $this->attachmentId;
}
public function setAttachment($attachment)
{
$this->attachmentId = $attachment;
//return $this;
}
public function getStatus()
{
return $this->status;
}
public function setStatus($status)
{
$this->status = $status;
}
public function setUserId($user_id)
{
$this->user = $user_id;
}
public function getUserId($user_id)
{
return $this->user;
}
}
My ProjectType (Form/ProjectType.php)
<?php
namespace AppBundle\Form;
use AppBundle\Entity\Project;
use AppBundle\Entity\User;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\BaseType;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
class ProjectType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title')
->add('type')
->add('budget',IntegerType::class)
->add('description',TextareaType::class)
->add('registerDate',DateTimeType::class)
->add('endDate',DateTimeType::class)
->add('prePay',IntegerType::class)
->add('fee',IntegerType::class,array('mapped'=>false))
->add('isPay',ChoiceType::class,[
'choices' => [
'Yes' => 1,
'No' => 0,
],
])
->add('isPrePay',ChoiceType::class,[
'choices' => [
'Yes' => 1,
'No' => 0,
],
])
->add('attachmentId',NumberType::class,array('mapped'=>false))
->add('status',ChoiceType::class,[
'choices' => [
'Pending Review' => 0,
'Pending PrePaid' => 1,
'In Process' => 2,
'End Work' => 3,
'Complete' => 4
],
])
->add('user',NumberType::class,['mapped'=>false]);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Project::class
));
}
/**
* {#inheritdoc}
*/
/*public function getBlockPrefix()
{
return 'appbundle_project';
}*/
}
My Project Controller file ( src/AppBundle/Controller/ProjectCntroller.php )
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien#symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Controller\Admin;
use AppBundle\Entity\Project;
use AppBundle\Form\ProjectType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
/**
* Project controller.
*
* #Route("/admin", name="admin_project_controller")
* #Security("has_role('ROLE_ADMIN')")
*/
class ProjectController extends Controller
{
/**
* Lists all project entities.
*
* #Route("/project", name="admin_project_index")
* #Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$projects = $em->getRepository(Project::class)->findAll();
return $this->render('admin/project/index.html.twig', array(
'projects' => $projects,
));
}
/**
* Creates a new project entity.
*
* #Route("/project/new", name="admin_project_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$project = new Project();
$form = $this->createForm(ProjectType::class, $project);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($project);
$em->flush();
return $this->redirectToRoute('admin_project_show', array('id' => $project->getId()));
}
return $this->render('admin/project/new.html.twig', array(
'project' => $project,
'form' => $form->createView(),
));
}
/**
* Finds and displays a project entity.
*
* #Route("/project/{id}", name="admin_project_show")
* #Method("GET")
*/
public function showAction(Project $project)
{
$deleteForm = $this->createDeleteForm($project);
return $this->render('admin/project/show.html.twig', array(
'project' => $project,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing project entity.
*
* #Route("/project/{id}/edit", name="admin_project_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Project $project)
{
$deleteForm = $this->createDeleteForm($project);
$editForm = $this->createForm(ProjectType::class, $project);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('admin_project_edit', array('id' => $project->getId()));
}
return $this->render('admin/project/edit.html.twig', array(
'project' => $project,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Deletes a project entity.
*
* #Route("/project/{id}", name="admin_project_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, Project $project)
{
$form = $this->createDeleteForm($project);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($project);
$em->flush();
}
return $this->redirectToRoute('admin_project_index');
}
/**
* Creates a form to delete a project entity.
*
* #param Project $project The project entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(Project $project)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('admin_project_delete', array('id' => $project->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
My index.twig file ( apop/Resource/views/admins/project/index.html.twig)
{% extends 'base.html.twig' %}
{% block body %}
<h1>Projects list</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Type</th>
<th>Budget</th>
<th>Description</th>
<th>Registerdate</th>
<th>Enddate</th>
<th>Prepay</th>
<th>Fee</th>
<th>Ispay</th>
<th>Isprepay</th>
<th>Attachmentid</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for project in projects %}
<tr>
<td>{{ project.id }}</td>
<td>{{ project.title }}</td>
<td>{{ project.type }}</td>
<td>{{ project.budget }}</td>
<td>{{ project.description }}</td>
<td>{% if project.registerDate %}{{ project.registerDate|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>{% if project.endDate %}{{ project.endDate|date('Y-m-d H:i:s') }}{% endif %}</td>
<td>{{ project.prePay }}</td>
<td>{{ project.fee }}</td>
<td>{% if project.isPay %}Yes{% else %}No{% endif %}</td>
<td>{% if project.isPrePay %}Yes{% else %}No{% endif %}</td>
<td>{{ project.attachmentId }}</td>
<td>{{ project.status }}</td>
<td>
<ul>
<li>
show
</li>
<li>
edit
</li>
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<ul>
<li>
Create a new project
</li>
</ul>
{% endblock %}
if i delete {{ project.fee }} from twig template i got same error but now for attachmentId and if delete {{ project.attachmentId }} theen these is no error.
Thanks.
You have typo mistake in entity class,
public function geFee()
It should,
public function getFee()
i was doing a multi upload files on symfony2.8 and i find always problems,
and i always got this :
"Expected argument of type "string", "array" given"
this is my entity /Article.php
<?php
namespace RoubBundle\Entity;
use Symfony\Component\HttpFoundation\File\File;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* Article
*
* #ORM\Table(name="article")
* #ORM\Entity(repositoryClass="RoubBundle\Repository\ArticleRepository")
*/
class Article
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", nullable=true)
*
* #Assert\File(
* maxSize="5242880",
* mimeTypes = {
* "image/png",
* "image/jpeg",
* "image/jpg",
* "image/gif"
* }
* )
*/
public $image= array();
/**
* #ORM\Column(type="string")
* #var string
*/
private $titre;
public function getTitre()
{
return $this->titre;
}
public function setTitre($titre)
{
$this->titre = $titre;
return $this;
}
public function getImage() {
return $this->image;
}
public function setImage(array $image) {
$this->image = $image;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
and this is my action NewAction in my controller /ArticleController.php
public function newAction(Request $request)
{
$article = new Article();
$form = $this->createForm('RoubBundle\Form\ArticleType', $article);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (null !== $article->getImage) {
foreach($file as $article->getImage) {
/** #var Symfony\Component\HttpFoundation\File\UploadedFile $file */
$file = $article->getImage();
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move(
$this->getParameter('images_directory'),
$fileName
);
array_push($article->getImage(), $fileName);
}
}
$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();
return $this->redirectToRoute('article_show', array('id' => $article->getId()));
}
return $this->render('RoubBundle:article:new.html.twig', array(
'article' => $article,
'form' => $form->createView(),
));
}
this is form /ArticleType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('titre')
->add('image', 'file', array(
'required' => false,
'data_class' => null,
"multiple" => "multiple"))
;
}
and i try this in my twig /new.html.twig
{{ form_start(form) }}
{{ form_widget(form.titre) }} </br>
{{ form_widget(form.image, { 'attr': { 'multiple': 'multiple' } }) }}
</br>
<input type="submit" value="Create" />
{{ form_end(form) }}
guys, i wish that someone could help me, i am really stressed about it
and thank you.
Your problem is that $image is of type string in your entity:
#ORM\Column(type="string", nullable=true)
So you need first to figure out how you want to save list of images in your database. The good way to do this would be creating a new table (and Entity) called article_images which looks like this for example:
$id
$imageUrl
$articleId
If you dont want another table you can try and save your images array as a json. To do this use
#ORM\Column(type="json")
on your $image field.
Second problem is your "moving" code. You are pushing values at the end of array, while you only want the "moved" ones. Here is what it could look like:
if ($article->getImage()) {
$movedImages = array();
foreach($article->getImage() as $index=>$file) {
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move(
$this->getParameter('images_directory'),
$fileName
);
array_push($movedImages, $fileName);
}
$article->setImage($movedImages);
}
$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();
return $this->redirectToRoute('article_show', array('id' => $article->getId()));
}
I have a problem with mu one-to-many relationships in Symfony2.
I have Company and User classes. One company has a few users as an HR and some users have company-employer.
There are parts of code:
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Company", inversedBy="hrs")
* #ORM\JoinColumn(name="company_id", referencedColumnName="id")
*/
protected $employer;
....
....
....
/**
* Set employer
*
* #param \JobFyBundle\Entity\Company $employer
* #return User
*/
public function setEmployer(\JobFyBundle\Entity\Company $employer = null)
{
$this->employer = $employer;
$employer->addHrs($this);
return $this;
}
/**
* Get employer
*
* #return \JobFyBundle\Entity\Company
*/
public function getEmployer()
{
return $this->employer;
}
}
It's a part of Company class
/**
* #ORM\Entity(repositoryClass="CompanyRepository")
* #ORM\Table(name="jobfy_company")
*/
class Company {
/**
* #ORM\Id()
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
...
...
...
/**
* Add hrs
*
* #param User $hr
* #return Company
* #internal param User $hrs
*/
public function addHrs(\JobFyBundle\Entity\User $hr)
{
$this->getHrs()->add($hr);
$hr->setEmployer($this);
return $this;
}
/**
* Remove hrs
*
* #param \JobFyBundle\Entity\User $hrs
*/
public function removeHr(\JobFyBundle\Entity\User $hrs)
{
$this->hrs->removeElement($hrs);
}
/**
* Get hrs
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getHrs()
{
return $this->hrs;
}
}
I try to make edit action to allow adding more hr's.
Here is part of CompanyController:
/**
* Displays a form to edit an existing Company entity.
*
* #Route("/{id}/edit", name="company_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Company $company)
{
$deleteForm = $this->createDeleteForm($company);
$editForm = $this->createForm('JobFyBundle\Form\CompanyType', $company, array('csrf_protection' => false));
$editForm->handleRequest($request);
$em = $this->getDoctrine()->getManager();
$people = $em->getRepository('JobFyBundle:User')->findAll();
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($company);
$em->flush();
return $this->redirectToRoute('company_show', array('id' => $company->getId()));
}
return $this->render('company/edit.html.twig', array(
'company' => $company,
'hrs' => $people,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
And it's a template of edit action.
{% extends 'base.html.twig' %}
{% block body %}
<div class="container">
<form name="company" method="post" class="form-new">
<h1 class="form-new-heading">Edit company</h1>
<div id="cv">
<div>
<label for="company_title">Company title</label>
<textarea id="company_title" name="company[title]" class="form-control"
required autofocus>{{ company.title }}</textarea>
<label for="company_url">Company url</label>
<textarea id="company_url" name="company[url]" class="form-control"
>{{ company.url }}</textarea>
<label for="company_about_us">About us</label>
<textarea id="company_about_us" name="company[about_us]"
class="form-control" rows="15">{{ company.getAboutUs }}</textarea>
<div>
<label for="company_hrs">HRs</label>
<select id="company_hrs" name="company[hrs][]" multiple="multiple" class="form-control">
{% for hr in hrs %}
<option value="{{ hr.id }}"
{% if hr.employer is not null and hr.employer.id == company.id %}
selected="selected"
{% endif %}
>{{ hr }}</option>
{% endfor %}
</select>
</div>
<button class="btn btn-lg btn-success" type="submit">Submit</button>
</div>
</div>
</form>
<h3>Show companies list</h3>
</div>
{% endblock %}
Everything works, except adding or editing hr's list.
Thank you for help!
I've solved a problem.
public function editAction(Request $request, Company $company)
{
$deleteForm = $this->createDeleteForm($company);
$editForm = $this->createForm('JobFyBundle\Form\CompanyType', $company, array('csrf_protection' => false));
$editForm->handleRequest($request);
$em = $this->getDoctrine()->getManager();
$people = $em->getRepository('JobFyBundle:User')->findAll();
foreach ($company->getHrs() as $hr){
$company->removeHr($hr);
}
if ($editForm->isSubmitted() && $editForm->isValid()) {
foreach ($_POST['company']['hrs'] as $hr_id){
$hr = $em->getRepository('JobFyBundle:User')->find($hr_id);
$company->addHrs($hr);
$hr->setEmployer($company);
}
$em->persist($company);
$em->flush();
return $this->redirectToRoute('company_show', array('id' => $company->getId()));
}
return $this->render('company/edit.html.twig', array(
'company' => $company,
'hrs' => $people,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
It can be useful for somebody, so I'll leave it there :)
Now I have problem with submitting post data in my form (my forms looks like:
Task: <input text>
Category: <multiple select category>
DueDate: <date>
<submit>
)
And after submitting my form, I'll get this error:
Found entity of type Doctrine\Common\Collections\ArrayCollection on association Acme\TaskBundle\Entity\Task#category, but expecting Acme\TaskBundle\Entity\Category
My sources:
Task Object Task.php
<?php
namespace Acme\TaskBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="tasks")
*/
class Task
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=200)
* #Assert\NotBlank(
* message = "Task cannot be empty"
* )
* #Assert\Length(
* min = "3",
* minMessage = "Task is too short"
* )
*/
protected $task;
/**
* #ORM\Column(type="datetime")
* #Assert\NotBlank()
* #Assert\Type("\DateTime")
*/
protected $dueDate;
/**
* #Assert\True(message = "You have to agree")
*/
protected $accepted;
/**
* #ORM\ManyToMany(targetEntity="Category", inversedBy="tasks")
*/
protected $category;
/**
* Constructor
*/
public function __construct()
{
$this->category = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set task
*
* #param string $task
* #return Task
*/
public function setTask($task)
{
$this->task = $task;
return $this;
}
/**
* Get task
*
* #return string
*/
public function getTask()
{
return $this->task;
}
/**
* Set dueDate
*
* #param \DateTime $dueDate
* #return Task
*/
public function setDueDate($dueDate)
{
$this->dueDate = $dueDate;
return $this;
}
/**
* Get dueDate
*
* #return \DateTime
*/
public function getDueDate()
{
return $this->dueDate;
}
/**
* Add category
*
* #param \Acme\TaskBundle\Entity\Category $category
* #return Task
*/
public function addCategory(\Acme\TaskBundle\Entity\Category $category)
{
$this->category[] = $category;
return $this;
}
/**
* Remove category
*
* #param \Acme\TaskBundle\Entity\Category $category
*/
public function removeCategory(\Acme\TaskBundle\Entity\Category $category)
{
$this->category->removeElement($category);
}
/**
* Get category
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCategory()
{
return $this->category;
}
}
Category Object Category.php
<?php
namespace Acme\TaskBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="categories")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=200, unique=true)
* #Assert\NotNull(message="Choose a category", groups = {"adding"})
*/
protected $name;
/**
* #ORM\ManyToMany(targetEntity="Task", mappedBy="category")
*/
private $tasks;
public function __toString()
{
return strval($this->name);
}
/**
* Constructor
*/
public function __construct()
{
$this->tasks = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add tasks
*
* #param \Acme\TaskBundle\Entity\Task $tasks
* #return Category
*/
public function addTask(\Acme\TaskBundle\Entity\Task $tasks)
{
$this->tasks[] = $tasks;
return $this;
}
/**
* Remove tasks
*
* #param \Acme\TaskBundle\Entity\Task $tasks
*/
public function removeTask(\Acme\TaskBundle\Entity\Task $tasks)
{
$this->tasks->removeElement($tasks);
}
/**
* Get tasks
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTasks()
{
return $this->tasks;
}
}
TaskType TaskType.php
<?php
namespace Acme\TaskBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Acme\TaskBundle\Form\Type\Category;
class TaskType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\TaskBundle\Entity\Task',
'cascade_validation' => true,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('task', 'text', array('label' => 'Task'))
->add('dueDate', 'date', array('label' => 'Due Date'))
->add('category', new CategoryType(), array('validation_groups' => array('adding')))
//->add('accepted', 'checkbox')
->add('save', 'submit', array('label' => 'Submit'));
}
public function getName()
{
return 'task';
}
}
CategoryType CategoryType.php
<?php
namespace Acme\TaskBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CategoryType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => null,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'entity', array(
'class' => 'AcmeTaskBundle:Category',
'query_builder' => function($repository) { return $repository->createQueryBuilder('c')->orderBy('c.id', 'ASC'); },
'property' => 'name',
'multiple' => true,
'label' => 'Categories',
));
}
public function getName()
{
return 'category';
}
}
and my Controller DefaultController.php:
public function newAction(Request $request)
{
$task = new Task();
$task->setTask('Write name here...');
$task->setDueDate(new \DateTime('tomorrow'));
$form = $this->createForm('task', $task);
$form->handleRequest($request);
if($form->isValid())
{
$this->get('session')->getFlashBag()->add(
'success',
'Task was successfuly created'
);
$em = $this->getDoctrine()->getManager();
/*
$category = $this->getDoctrine()->getManager()->getRepository('AcmeTaskBundle:Category')->findOneByName($form->get('category')->getData());
$task->setCategory($category);
*/
$em->persist($task);
try {
$em->flush();
} catch (\PDOException $e) {
// sth
}
//$nextAction = $form->get('saveAndAdd')->isClicked() ? 'task_new' : 'task_success';
//return $this->redirect($this->generateUrl($nextAction));
}
return $this->render('AcmeTaskBundle:Default:new.html.twig', array('form' => $form->createView()));
}
So, I looked at this problem at the google, but there were different kinds of problems. Any idea?
UPDATE
Full error message:
[2013-09-30 14:43:55] request.CRITICAL: Uncaught PHP Exception Doctrine\ORM\ORMException: "Found entity of type Doctrine\Common\Collections\ArrayCollection on association Acme\TaskBundle\Entity\Task#category, but expecting Acme\TaskBundle\Entity\Category" at /var/www/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 762 {"exception":"[object] (Doctrine\\ORM\\ORMException: Found entity of type Doctrine\\Common\\Collections\\ArrayCollection on association Acme\\TaskBundle\\Entity\\Task#category, but expecting Acme\\TaskBundle\\Entity\\Category at /var/www/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:762)"} []
UPDATE 2
My TWIG template new.html.twig
<html>
<head>
<title>Task create</title>
</head>
<body>
{% for flashMessage in app.session.flashbag.get('success') %}
<div style="display: block; padding: 15px; border: 1px solid green; margin: 15px; width: 450px;">
{{ flashMessage }}
</div>
{% endfor %}
{{ form_start(form, {'action': path ('task_new'), 'method': 'POST', 'attr': {'novalidate': 'novalidate' }}) }}
{{ form_errors(form) }}
<div>
{{ form_label(form.task) }}:<br>
{{ form_widget(form.task) }} {{ form_errors(form.task) }}<br>
</div>
<div>
{{ form_label(form.category) }}:<br>
{{ form_widget(form.category) }} {{ form_errors(form.category) }}
</div>
<div>
{{ form_label(form.dueDate) }}:<br>
{{ form_widget(form.dueDate) }} {{ form_errors(form.dueDate) }}<br>
</div>
{{ form_end(form) }}
</body>
</html>
You can improve the controller code by changing your setters in the entities:
In Task:
public function addCategory(Category $category)
{
if (!$this->categories->contains($category)) {
$this->categories->add($category);
$category->addTask($this); // Fix this
}
}
And in Category:
public function addTask(Task $task)
{
if (!this->tasks->contains($task)) {
$this->tasks->add($task);
$task->addCategory($this);
}
}
This will keep the elements in the ArrayCollection unique so you won't have to do that checking in your code and will also set the inverse side automatically.
So I found my solution! This code works:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('task', 'text', array('label' => 'Task'))
->add('dueDate', 'date', array('label' => 'Date', 'format' => 'ddMMMMyyyy'))
->add('category', 'entity', array('required' => true, 'multiple' => true, 'class' => 'AcmeTaskBundle:Category', 'query_builder' => function($repository) { return $repository->createQueryBuilder('c')->orderBy('c.id', 'ASC'); },))
->add('save', 'submit', array('label' => 'Send'));
}
And my controller is working in this form:
if($form->isValid())
{
$this->get('session')->getFlashBag()->add(
'success',
'Task successfuly added'
);
$em = $this->getDoctrine()->getManager();
foreach($form->get('category')->getData() as $cat)
{
$task->removeCategory($cat);
$task->addCategory($cat);
}
$em->persist($task);
try {
$em->flush();
} catch (\PDOException $e) {
// sth
}
}
I'm forced to use $task->removeCategory($cat) because I'll get error of dublication primary indexes if it will not be here.
Now I'm trying to resolve my problem with embedded and non-embedded forms -> Symfony2, validation embedded and non-embedded forms with same parameters and different results?
I believe that my questions will be helpful for beginners with Symfony2 having same problems.
You are defining a manyToMany relationship from task to category, which means you can have more than one category for each task. If you are trying to have multiple categories in a task, you can try changing this line
->add('category', new CategoryType(), array('validation_groups' => array('adding')))
for something like
->add('category', 'collection', array('type' => new CategoryType()))
check symfony's documentation on form collection and this cookbook
I am not sure, but try to add a setCategory method to your Task entity, because currently you only have the add function and thats why the form component is calling the addFunction instead of the set for the whole arraycollection.
I think problem in your form.
Your task have ManyToMany relation with categotry and stored in field category(logical it is a categories). But in the form you set '->add('category', new CategoryType())' which means that you add new type that is a array or something(data_class not defined) and this type contains another one field.
Solution is to directly define field in your form(without using standalone form type) Or extend category form type from entity type(by default type extended form type).