I'm developing a rest api application with symfony in backend.
My problem is that when I try to lauch a GET request, the application runs without giving any response even after even after some ten minutes.
this is the request method:
/**
* CounterRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class CounterRepository extends \Doctrine\ORM\EntityRepository
{
/**
* #param string $name
* #param int $date
* #return mixed
* #throws \Exception
*/
public function getValuesByNameAndDate(string $name, int $date)
{
$query = $this
->createQueryBuilder('c')
->leftJoin('c.values', 'v', 'WITH')
->addSelect('v')
->where('c.name = :name')
->andWhere('v.date = :date')
->setParameters(
array(
'date' => $date,
'name' => $name
)
)
->getQuery();
return $query->getResult();
}
}
The CounterValue Entity:
/**
* CounterValue
*
* #ORM\Table(name="counter_value")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CounterValueRepository")
*/
class CounterValue
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var float
*
* #ORM\Column(name="value", type="float")
*/
private $value;
/**
* #var int
*
* #ORM\Column(name="date", type="integer")
*/
private $date;
/**
* #var Counter
*
* #ORM\ManyToOne(targetEntity="Counter", inversedBy="values")
* #ORM\JoinColumn()
*/
private $counter;
/**
* #var City
*
* #ORM\ManyToOne(targetEntity="City", inversedBy="values"))
* #ORM\JoinColumn()
*/
protected $city;
public function __construct()
{
$date = new \DateTime('-1 day');
$this->date = strtotime($date->format('d-m-Y'));
}
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set value.
*
* #param float $value
*
* #return CounterValue
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* Get value.
*
* #return float
*/
public function getValue()
{
return $this->value;
}
/**
* Set date.
*
* #param int $date
*
* #return CounterValue
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date.
*
* #return int
*/
public function getDate()
{
return $this->date;
}
/**
* #return Counter
*/
public function getCounter(): Counter
{
return $this->counter;
}
/**
* #param Counter $counter
*/
public function setCounter(Counter $counter): void
{
$this->counter = $counter;
}
/**
* #return City
*/
public function getCity(): City
{
return $this->city;
}
/**
* #param City $city
*/
public function setCity(City $city): void
{
$this->city = $city;
}
}
/**
* Counter
*
* #ORM\Table(name="counter")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CounterRepository")
*/
class Counter
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, unique=false)
*/
private $name;
/**
* #var XmlFile
*
* #ORM\ManyToOne(targetEntity="XmlFile", inversedBy="counters", cascade={"remove"})
* #ORM\JoinColumn(nullable=false)
*/
private $xmlFile;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="CounterValue", mappedBy="counter", cascade={"persist"})
*/
private $values;
public function __construct()
{
$this->values = new ArrayCollection();
}
/**
* Get id.
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name.
*
* #param string $name
*
* #return Counter
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name.
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set xmlFile
*
* #param XmlFile $xmlFile
*/
public function setXmlFile(XmlFile $xmlFile)
{
$this->xmlFile = $xmlFile;
}
/**
* Get xmlFile
*
* #return XmlFile
*/
public function getXmlFile(): XmlFile
{
return $this->xmlFile;
}
/**
* #return ArrayCollection
*/
public function getValues(): ArrayCollection
{
return $this->values;
}
/**
* #param ArrayCollection $values
*/
public function setValues(ArrayCollection $values): void
{
$this->values = $values;
}
/**
* Add $value
*
* #param CounterValue $value
*/
public function addValue(CounterValue $value)
{
$value->setCounter($this);
if(!$this->values->contains($value)){
$this->values->add($value);
}
}
}
And finally my method in controller
$em = $this->get('doctrine.orm.entity_manager');
$counterRep = $em->getRepository('AppBundle:Counter');
return $counterRep->getValuesByNameAndDate('L.IRATHO.E2G.CSFB.ExecSuccOut', 1533600000);
Just return a Json response like this.
public function listAction(Request $request)
{
try
{
$em = $this->get('doctrine.orm.entity_manager');
$counterRep = $em->getRepository('AppBundle:Counter')->getValuesByNameAndDate('L.IRATHO.E2G.CSFB.ExecSuccOut', 1533600000);
return new JsonResponse(['success' => true, 'code' => Response::HTTP_OK, 'data' => $counterRep]);
}
catch (\Exception $exception)
{
return new JsonResponse(['success' => false,'code' => $exception->getCode() ,'message' => $exception->getMessage()]);
}
}
Controller action should return instance of
Symfony\Component\HttpFoundation\Response
You try to return result of query builder $query->getResult()
You need to change it to something like
public function counterValuesAction(Request $request) {
try {
$em = $this->get('doctrine.orm.entity_manager');
$counterRep = $em->getRepository('AppBundle:Counter');
$values = $counterRep->getValuesByNameAndDate('L.IRATHO.E2G.CSFB.ExecSuccOut', 1533600000);
} catch (\Exception $e) {
return new Response($values);
}
}
Solution for Symfony 4+:
<?php
namespace App\Controller;
class CounterController extends AbstractController
{
public function listAction(
CounterRepository $repository // DI works like this in Controllers...
) {
$result = $repository->getValuesByNameAndDate('L.IRATHO.E2G.CSFB.ExecSuccOut', 1533600000);
// use JsonResponse object to create JSON response
return $this->json($result, Response::HTTP_OK);
}
}
// routes.yaml
counter_list:
path: /counter
controller: App\Controller\CounterController::listAction
methods: GET
Clear cache and try to send GET request to http://your-dev-host/counter
How does it work?
Controller
You need to create controller CounterController class with action function listAction. It is good practice to add Action postfix to action function.
You can define services or other DI objects as parameters in action functions. DI will set it. For example:
class MyController extends AbstractController
{
public function listAction(
Request $request,
SerializerInterface $serializer,
ValidatorInterface $validator,
CounterRepository $repository
) {
// ...
}
}
In order to send good response with JSON and all headers that is needed you need to use AbstractController::json function. It creates JsonResponse object. You can check it implementation.
More information about symfony controllers you can find in this article https://symfony.com/doc/current/controller.html
Routing
Next step is to create route for your new controller action. You can do it in 2 ways:
Adding record to config/routes.yaml file as i did
Use annotations (Annotations is bad practice because comments should not break programm)
More information about routing you can find in this article https://symfony.com/doc/current/routing.html
It does not work for me! How can I debug it?
First, dont panic and read error message. Also, you can check if routing works well. You can do it using command
$ bin/console debug:router
----------------------- -------- -------- ------ -------------------------------------
Name Method Scheme Host Path
----------------------- -------- -------- ------ -------------------------------------
_preview_error ANY ANY ANY /_error/{code}.{_format}
register_token POST ANY ANY /auth/register
refresh_token POST ANY ANY /auth/refresh
auth_login POST ANY ANY /auth/login
restroom_list GET ANY ANY /api/v1/restroom
----------------------- -------- -------- ------ -------------------------------------
In table you need to check your new url and how Symfony sees it.
Second, try to send request to this URL using curl and check response.
$ curl http://localhost/auth/login
Related
When i'm viewing www.example.com/product/10 this product is link to a User Id. Now i would like to show only Comment that is link to the User id of the product a i'm viewing.
The table Comment is link to the table User, so each comment have is user id. The table Product (Post) is also link to the table user , each product have is user id.
For now the table Comment and Product are not yet link , i think they should be so i can perform a query, but i'm not sure.
I'm using FosCommentBundle for the comment.
Controller:
public function productAction($id, Request $request)
{
$session = $this->getRequest()->getSession();
$em = $this->getDoctrine()->getManager();
$findEntities = $em->getRepository('FLYBookingsBundle:Post')->findBy(array('id' => $id));
$entities = $this->get('knp_paginator')->paginate($findEntities, $this->get('request')->query->get('page', 1), 9
);
if ($session->has('cart'))
$cart = $session->get('cart');
else
$cart = false;
if (!$entities) {
throw $this->createNotFoundException('Unable to find Post entity.');
}
$id = 'thread_id';
$thread = $this->container->get('fos_comment.manager.thread')->findThreadById($id);
if (null === $thread) {
$thread = $this->container->get('fos_comment.manager.thread')->createThread();
$thread->setId($id);
$thread->setPermalink($request->getUri());
// Add the thread
$this->container->get('fos_comment.manager.thread')->saveThread($thread);
}
$comments = $this->container->get('fos_comment.manager.comment')->findCommentTreeByThread($thread);
return $this->render('FLYBookingsBundle:Post:product.html.twig', array('entity' => $entities,
'cart' => $cart,'comments' => $comments,
'thread' => $thread));
}
Product.html.twig
<div id="fos_comment_thread" data-thread="{{ thread.id }}">
{% include 'FOSCommentBundle:Thread:async.html.twig' with {
'comments': comments,
'thread': thread
} %}
Comment.php
<?php
namespace Application\Sonata\CommentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\CommentBundle\Entity\Comment as BaseComment;
use FOS\CommentBundle\Model\SignedCommentInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Application\Sonata\UserBundle\Entity\User;
/**
* #ORM\Entity
* #ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
*/
class Comment extends BaseComment implements SignedCommentInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\generatedValue(strategy="AUTO")
*/
protected $id;
/**
* Thread of this comment
*
* #var Thread
* #ORM\ManyToOne(targetEntity="Application\Sonata\CommentBundle\Entity\Thread")
*/
protected $thread;
/**
* Author of the comment
*
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User")
* #var User
*/
protected $author;
/**
* Sets the author of the Comment
*
* #param UserInterface $user
*/
public function setAuthor(UserInterface $author)
{
$this->author = $author;
}
/**
* Gets the author of the Comment
*
* #return UserInterface
*/
public function getAuthor()
{
return $this->author;
}
public function getAuthorName()
{
if (null === $this->getAuthor()) {
return 'Anonymous';
}
return $this->getAuthor()->getUsername();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
Post.php
<?php
namespace FLY\BookingsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Application\Sonata\UserBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Form\Type\VichImageType;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\Form\Extension\Core\Type\FileType;
/**
* Post
*
* #ORM\Table(name="post")
* #ORM\Entity(repositoryClass="FLY\BookingsBundle\Entity\PostRepository")
* #Vich\Uploadable
*/
class Post
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #Assert\Length(min=2, max=20)
*
* #ORM\Column(name="username", type="string", length=45, nullable=true)
*/
private $username;
/**
* #var string
*
* #Assert\Regex("/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/")
*
* #ORM\Column(name="email", type="string", length=45, nullable=false)
*/
private $email;
/**
* #ORM\ManyToOne(targetEntity="FLY\BookingsBundle\Entity\Tva")
* #ORM\joinColumn(onDelete="SET NULL")
*/
private $tva;
/**
* #ORM\ManyToOne(targetEntity="FLY\BookingsBundle\Entity\Media")
* #ORM\joinColumn(onDelete="SET NULL")
*/
private $image;
/**
* #var string
*
* #Assert\Length(max=350)
*
* #ORM\Column(name="description", type="text" , length=125, nullable=true)
*/
private $description;
/**
* #var float
*
* #Assert\NotBlank()
*
*
* #Assert\Regex(
* pattern= "/^[1-9]\d{0,7}(?:\.\d{1,4})?$/",
* message= "The First number can't start with 0"
* )
*
* #ORM\Column(name="price", type="float")
*/
private $price;
/**
*
*
* #ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User")
* #ORM\JoinColumn(onDelete="CASCADE")
* #Security("user.getId() == post.getUser()")
*/
private $user;
/**
* #ORM\OneToOne(targetEntity="Quantity", cascade={"remove"})
* #ORM\JoinColumn(name="sold_id", referencedColumnName="id")
*/
protected $sold;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
*
* #return Post
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set email
*
* #param string $email
*
* #return Post
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set price
*
* #param float $price
* #return Post
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Get price
*
* #return float
*/
public function getPrice()
{
return $this->price;
}
/**
* #return User
*/
public function getUser()
{
return $this->user;
}
/*
* #param User $user
*/
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
/**
* Set tva
*
* #param \FLY\BookingsBundle\Entity\Tva $tva
* #return Post
*/
public function setTva(\FLY\BookingsBundle\Entity\Tva $tva)
{
$this->tva = $tva;
return $this;
}
/**
* Get tva
*
* #return \FLY\BookingsBundle\Entity\Tva
*/
public function getTva()
{
return $this->tva;
}
/**
* Set image
*
* #param \FLY\BookingsBundle\Entity\Media $image
* #return Post
*/
public function setImage(\FLY\BookingsBundle\Entity\Media $image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return \FLY\BookingsBundle\Entity\Media
*/
public function getImage()
{
return $this->image;
}
/**
* Set description
*
* #param string $description
* #return Post
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set sold
*
* #param integer $sold
* #return Post
*/
public function setSold($sold)
{
$this->sold = $sold;
return $this;
}
/**
* Get sold
*
* #return integer
*/
public function getSold()
{
return $this->sold;
}
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName")
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*
* #return User
*/
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
if ($image) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTime('now');
}
return $this;
}
/**
* #return File
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #param string $imageName
*
* #return User
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
}
ADD:
<?php
namespace Application\Sonata\CommentBundle\Entity;
use FLY\BookingsBundle\Entity\Post;
use Application\Sonata\UserBundle\Entity\User;
use Doctrine\ORM\EntityRepository;
class CommentRepository extends EntityRepository
{
/**
* Get Comments for a single Product.
* #param Post $post
* #return mixed
*/
public function getCommentsForSinglePost(Post $post)
{
$qb = $this->createQueryBuilder('c')
->where('c.post = :postId')
->setParameter('postId', $post->getId());
$query = $qb->getQuery();
return $query->execute();
}
}
Relation from Comment to Post(Product):
/**
* #ORM\ManyToOne(targetEntity="FLY\BookingsBundle\Entity\Post")
* #ORM\JoinColumn(nullable=true)
*/
private $post;
/**
* Set post
*
* #param \FLY\BookingsBundle\Entity\Post $post
* #return Comment
*/
public function setUser(\FLY\BookingsBundle\Entity\Post $post = null)
{
$this->post = $post;
return $this;
}
/**
* Get post
*
* #return \FLY\BookingsBundle\Entity\Post
*/
public function getPost()
{
return $this->post;
}
modication in controller:
public function productAction($id, Request $request, $post)
{
$session = $this->getRequest()->getSession();
$em = $this->getDoctrine()->getManager();
$findEntities = $em->getRepository('FLYBookingsBundle:Post')->findBy(array('id' => $id));
$entities = $this->get('knp_paginator')->paginate($findEntities, $this->get('request')->query->get('page', 1), 9
);
if ($session->has('cart'))
$cart = $session->get('cart');
else
$cart = false;
if (!$entities) {
throw $this->createNotFoundException('Unable to find Post entity.');
}
$post = 'thread_id';
$thread = $em->getRepository('ApplicationSonataCommentBundle:Comment')->getCommentsForSinglePost($post);
if (null === $thread) {
$thread = $this->container->get('fos_comment.manager.thread')->createThread();
$thread->setId($post);
$thread->setPermalink($request->getUri());
// Add the thread
$this->container->get('fos_comment.manager.thread')->saveThread($thread);
}
$comments = $this->container->get('fos_comment.manager.comment')->findCommentTreeByThread($thread);
return $this->render('FLYBookingsBundle:Post:product.html.twig', array('entity' => $entities,
'cart' => $cart,'comments' => $comments,'post' => $post,
'thread' => $thread));
}
Error:
Controller
"FLY\BookingsBundle\Controller\PostController::productAction()"
requires that you provide a value for the "$post" argument (because
there is no default value or because there is a non optional argument
after this one).
Considering you have Many-To-One association from Comment to Product. Here is how you should write a new method in CommentRepository to get list of comments for a single product.
/**
* Get Comments for a single Product.
* #param Product $product
* #return mixed
*/
public function getCommentsForSingleProduct(Product $product)
{
$qb = $this->createQueryBuilder('c')
->where('c.product = :productId')
->setParameter('productId', $product->getId());
$query = $qb->getQuery();
return $query->execute();
}
You can add any other condition as per your requirement. or add sort, or pagination etc..
Note : I haven't added user association. Let me know if you need anything else.
I need to get maximum ID of a table inside of symfony 2.7 entity. But instead of having the id I'm getting this issue.
Notice: Undefined property: AppBundle\Entity\BlogPost::$container
This is my BlogPost entity,
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* BlogPost
*
* #ORM\Table()
* #ORM\Entity
*/
class BlogPost {
const SERVER_PATH_TO_IMAGE_FOLDER = '/uploads';
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="body", type="text")
*/
private $body;
/**
* #var string
*
* #ORM\Column(name="filename", type="text")
*/
private $filename;
/**
* Set filename
*
* #param string $filename
* #return BlogPost
*/
public function setFilename($filename) {
$this->filename = $filename;
return $this;
}
public function setUploader(UploadedFile $file) {
$em = $this->container->get('doctrine.orm.entity_manager');
$highest_id = $em->createQueryBuilder()
->select('MAX(b.id)')
->from('AppBundle:BlogPost', 'b')
->getQuery()
->getSingleScalarResult();
var_dump($highest_id);
exit();// exit for check value
$url = 'uploads/events';
$file_name = 'fsdf.' . $file->guessExtension();
$file->move($url, $file_name);
}
/**
* Get filename
*
* #return string
*/
public function getFilename() {
return $this->filename;
}
/**
* #var boolean
*
* #ORM\Column(name="draft", type="boolean")
*/
private $draft;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return BlogPost
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle() {
return $this->title;
}
/**
* Set body
*
* #param string $body
* #return BlogPost
*/
public function setBody($body) {
$this->body = $body;
return $this;
}
/**
* Get body
*
* #return string
*/
public function getBody() {
return $this->body;
}
/**
* Set draft
*
* #param boolean $draft
* #return BlogPost
*/
public function setDraft($draft) {
$this->draft = $draft;
return $this;
}
/**
* Get draft
*
* #return boolean
*/
public function getDraft() {
return $this->draft;
}
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="blogPosts")
*/
private $category;
public function setCategory(Category $category) {
$this->category = $category;
}
public function getCategory() {
return $this->category;
}
/**
* Unmapped property to handle file uploads
*/
public $file;
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null) {
$this->file = $file;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile() {
return $this->file;
}
/**
* Manages the copying of the file to the relevant place on the server
*/
public function upload() {
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
// we use the original file name here but you should
// sanitize it at least to avoid any security issues
// move takes the target directory and target filename as params
$this->getFile()->move(
self::SERVER_PATH_TO_IMAGE_FOLDER, $this->getFile()->getClientOriginalName()
);
// set the path property to the filename where you've saved the file
$this->filename = $this->getFile()->getClientOriginalName();
// clean up the file property as you won't need it anymore
$this->setFile(null);
}
/**
* Lifecycle callback to upload the file to the server
*/
public function lifecycleFileUpload() {
$this->upload();
}
/**
* Updates the hash value to force the preUpdate and postUpdate events to fire
*/
public function refreshUpdated() {
// $this->setUpdated(new \DateTime());
}
// ... the rest of your class lives under here, including the generated fields
// such as filename and updated
}
This is the part I'm trying to get max id,
public function setUploader(UploadedFile $file) {
$em = $this->container->get('doctrine.orm.entity_manager');
$highest_id = $em->createQueryBuilder()
->select('MAX(b.id)')
->from('AppBundle:BlogPost', 'b')
->getQuery()
->getSingleScalarResult();
var_dump($highest_id);
exit();// exit for check value
$url = 'uploads/events';
$file_name = 'fsdf.' . $file->guessExtension();
$file->move($url, $file_name);
}
With the help of comments and few research I figured out the issue is in 'entity_manager' part. Is there a way to call doctrine queries inside Entity?
If I were you, i would do something like that :
Controller:
$blogPost= new BlogPost () ;
$em = $this->getDoctrine()->getManager();
//..your code
// I assume you want to do that after a form post
$blogPost = $form->getData();
$id = $em->getRepository('AppBundle:BlogPost')->getMaxId();
$blogPost->setUploader($id);
//...
Repository:
public function getMaxId()
{
$qb = $this->createQueryBuilder('u');
$qb->select('u, MAX(id) as idMax');
return $qb->getQuery()->getSingleResult();
}
Entity:
public function setUploader(UploadedFile $file, $id)
{
var_dump($id);
$url = 'uploads/events';
$file_name = 'fsdf.'.$id.$file->guessExtension();
$file->move($url, $file_name);
}
It should work
I would suggest to hold the EntityManager as a class variable inside your Entity and either instantiate it via the constructor or via a setter-method which you call before you use the setUploader function.
This should be the cleanest and best readable solution.
Form another thread I found this and it's working for me.
global $kernel;
if ( 'AppCache' == get_class($kernel) )
{
$kernel = $kernel->getKernel();
}
$em = $kernel->getContainer()->get( 'doctrine.orm.entity_manager');
I can't use it in controller cause I have an admin class instead of controller on this. Since lot of people suggesting this using entity_manager inside entity is not good practice I'm using the code inside admin class instead of entity.
This is the original thread..
How to use entityManager inside Entity?
Try this in your Controller:
$blogPost= new BlogPost () ;
$em = $this->getDoctrine()->getManager();
$blogPost = $form->getData();
$maxId = $em->getRepository('AppBundle:BlogPost')->createQueryBuilder('b')
->where("MAX(b.id) as maxId")
->getQuery()
->getSingleResult();
I use DoctrineBehaviors to apply translation of my entity, and JordiLlonchCrudGenerator to generate my crud, and LexikFormFilterBundle to generate my form filters type.
My form type
class PageFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', 'filter_text')
->add('content', 'filter_text')
;
$listener = function(FormEvent $event)
{
// Is data empty?
foreach ($event->getData() as $data) {
if(is_array($data)) {
foreach ($data as $subData) {
if(!empty($subData)) return;
}
}
else {
if(!empty($data)) return;
}
}
$event->getForm()->addError(new FormError('Filter empty'));
};
$builder->addEventListener(FormEvents::POST_BIND, $listener);
}
When i try to filters my entities, the error said hat no field called title in Class Entity\Page.
I understand this problem but i have no idea how to resolve this error, because the field title is into the entity PageTranslation, here my function filters :
protected function filter()
{
$request = $this->getRequest();
$session = $request->getSession();
$filterForm = $this->createForm(new PageFilterType());
$em = $this->getDoctrine()->getManager();
$queryBuilder = $em->getRepository('PageBundle:Page')
->createQueryBuilder('e')
->select('e')
->where('e.deletedAt IS NULL')
;
// Reset filter
if ($request->get('filter_action') == 'reset') {
$session->remove('PageControllerFilter');
}
// Filter action
if ($request->get('filter_action') == 'filter') {
// Bind values from the request
$filterForm->bind($request);
if ($filterForm->isValid()) {
// Build the query from the given form object
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($filterForm, $queryBuilder);
// Save filter to session
$filterData = $filterForm->getData();
$session->set('PageControllerFilter', $filterData);
}
} else {
// Get filter from session
if ($session->has('PageControllerFilter')) {
$filterData = $session->get('PageControllerFilter');
$filterForm = $this->createForm(new PageFilterType(), $filterData);
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($filterForm, $queryBuilder);
}
}
return array($filterForm, $queryBuilder);
}
I think that i should customize this line but i don't know how
$queryBuilder = $em->getRepository('PageBundle:Page')
->createQueryBuilder('e')
->select('e')
->where('e.deletedAt IS NULL')
;
Any solution for that ?
Also, i have created a trash for each entity, for exemple if one page is deleted the user can find it on trash,
Exemple : http://snapplr.com/snap/xxmk
So i have no problem with the action restore all, but remove all is not functional
This is my action
public function emptyTrashAction(){
$em = $this->getDoctrine()->getEntityManager();
$entities=$em->getRepository('PageBundle:Page')->findByRemoved();
if($entities){
foreach ($entities as $entity) {
$em->remove($entity);
$em->flush();
}
$this->get('session')->getFlashBag()->add('success', 'La corbeille est vide !!');
return $this->redirect($this->generateUrl('pa_trash'));
}else{
$this->get('session')->getFlashBag()->add('error', 'La corbeille est déjà vide !! ');
return $this->redirect($this->generateUrl('pa'));
}
}
What i wanna do, is to delete all entities where the feild DeletedAt is not empty, how can i do this ?
Thanks //
This is my entity Page Class
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* Page
* #ORM\Table(name="page")
* #ORM\Entity(repositoryClass="Core\PageBundle\Entity\PageRepository")
*
*/
class Page
{
use ORMBehaviors\Translatable\Translatable;
use ORMBehaviors\Timestampable\Timestampable;
use ORMBehaviors\SoftDeletable\SoftDeletable;
use ORMBehaviors\Blameable\Blameable;
public function __call($method, $arguments)
{
return \Symfony\Component\PropertyAccess\PropertyAccess::createPropertyAccessor()->getValue($this->translate(), $method);
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="nbview", type="integer", nullable=true)
*/
private $nbview;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nbview
*
* #param integer $nbview
* #return Page
*/
public function setNbview($nbview)
{
$this->nbview = $nbview;
return $this;
}
/**
* Get nbview
*
* #return integer
*/
public function getNbview()
{
return $this->nbview;
}
public function getUpdateLogMessage(array $changeSets = [])
{
return 'Changed: '.print_r($changeSets, true);
}
public function getRemoveLogMessage()
{
return 'removed!';
}
And this is the translation page class
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #ORM\Table(name="page_lang")
* #ORM\Entity()
*/
class PageTranslation
{
use ORMBehaviors\Translatable\Translation;
use ORMBehaviors\Sluggable\Sluggable;
/**
* #inheritdoc
*/
public function getSluggableFields()
{
return ['title'];
}
/**
* #inheritdoc
*/
public function getSlug()
{
if (!$this->slug) {
$this->generateSlug();
}
return $this->slug;
}
/**
* #var string $title
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string $content
*
* #ORM\Column(name="content", type="text")
*/
private $content;
/**
* #var string $meta
*
* #ORM\Column(name="meta", type="text", nullable=true)
*/
private $meta;
public function getId(){
return $ths->id;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set title
*
* #param string $title
* #return Page
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Set content
*
* #param string $content
* #return Page
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* #param $method
* #param $args
*
* #return mixed
*/
/**
* Set meta
*
* #param string $meta
* #return PageTranslation
*/
public function setMeta($meta)
{
$this->meta = $meta;
return $this;
}
/**
* Get meta
*
* #return string
*/
public function getMeta()
{
return $this->meta;
}
}
I've generated the form through entity generator,
I've extended the Cobrand Controller
class CobrandController extends Controller
{
public function createAction()
{
// the key used to lookup the template
$templateKey = 'edit';
if (false === $this->admin->isGranted('CREATE')) {
throw new AccessDeniedException();
}
$object = $this->admin->getNewInstance();
$this->admin->setSubject($object);
/** #var $form \Symfony\Component\Form\Form */
$form = $this->admin->getForm();
$form->setData($object);
if ($this->getRestMethod()== 'POST') {
// $cobrand = new Cobrand();
$em=$this->getDoctrine()->getManager();
$cobrand=new Cobrand($em);
$form->bind($this->get('request'));
$isFormValid = $form->isValid();
// persist if the form was valid and if in preview mode the preview was approved
if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) {
$this->admin->create($object);
if ($this->isXmlHttpRequest()) {
return $this->renderJson(array(
'result' => 'ok',
'objectId' => $this->admin->getNormalizedIdentifier($object)
));
}
$this->addFlash('sonata_flash_success','flash_create_success');
// redirect to edit mode
return $this->redirectTo($object);
}
// show an error message if the form failed validation
if (!$isFormValid) {
if (!$this->isXmlHttpRequest()) {
$this->addFlash('sonata_flash_error', 'flash_create_error');
}
} elseif ($this->isPreviewRequested()) {
// pick the preview template if the form was valid and preview was requested
$templateKey = 'preview';
$this->admin->getShow();
}
}
$view = $form->createView();
// set the theme for the current Admin Form
$this->get('twig')->getExtension('form')->renderer->setTheme($view, $this->admin->getFormTheme());
return $this->render($this->admin->getTemplate($templateKey), array(
'action' => 'create',
'form' => $view,
'object' => $object,
));
}
}
Here's my entity code,
class Cobrand
{
/**
* #var \DateTime
*/
private $created;
/**
* #var \DateTime
*/
private $updated;
/**
* #var string
*/
private $name;
/**
* #var string
*/
private $code;
/**
* #var string
*/
private $logo;
/**
* #var boolean
*/
private $cobrandedProductsOnly;
/**
* #var integer
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $productPrices;
/**
* #var \Doctrine\Common\Collections\Collection
*/
private $promocodes;
/**
* Constructor
*/
public function __construct()
{
$this->productPrices = new \Doctrine\Common\Collections\ArrayCollection();
$this->promocodes = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Set created
*
* #param \DateTime $created
* #return Cobrand
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param \DateTime $updated
* #return Cobrand
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Set name
*
* #param string $name
* #return Cobrand
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set code
*
* #param string $code
* #return Cobrand
*/
public function setCode($code)
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
}
}
User will enter the values on the form and I wan't to access those values in the createAction method of controller.
I want to change the value of $name in the controller.
How to access this ?
Thanks,
Faisal Nasir
Try this after binding request
$form->get('name')->setData('new value');
I have created the EntityClass:
<?php
namespace Rota\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\component\OptionsResolver\OptionsResolverIntrerface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* RotaObj
*
* #ORM\Table()
* #ORM\Entity
*/
class RotaMain
{
public function __construct()
{
$this->rotaShifts = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="MyUserId", type="integer")
*/
private $myUserId;
/**
* #var date
*
* #ORM\Column(name="RotaStartDate", type="date")
*/
private $startDate;
/**
* #var date
*
* #ORM\Column(name="RotaReviewDate", type="date")
*/
private $reviewDate;
/**
* #var integer
*
* #ORM\Column(name="RotaRollingWeeks", type="integer")
*/
private $rollingWeeks;
/**
* #var integer
*
* #ORM\Column(name="restDayCount", type="integer")
*/
private $restDayCount;
/**
* #var integer
*
* #ORM\Column(name="totalDayCount", type="integer")
*/
private $totalDayCount;
/**
* #ORM\OneToMany(targetEntity="RotaShift",mappedBy="rotaMain",cascade={"persist"})
*/
protected $rotaShifts;
/**
* #var string
*
* #ORM\Column(name="shiftOrder",type="string",length=4000,nullable=true)
*/
private $shiftOrder;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set myUserId
*
* #param integer $myUserId
* #return RotaObj
*/
public function setMyUserId($myUserId)
{
$this->myUserId = $myUserId;
return $this;
}
/**
* Get myUserId
*
* #return integer
*/
public function getMyUserId()
{
return $this->myUserId;
}
/**
* Set startDate
*
* #param \DateTime $startDate
* #return RotaObj
*/
public function setStartDate($startDate)
{
$this->startDate = $startDate;
return $this;
}
/**
* Get startDate
*
* #return \DateTime
*/
public function getStartDate()
{
return $this->startDate;
}
/**
* Set reviewDate
*
* #param \DateTime $reviewDate
* #return RotaObj
*/
public function setReviewDate($reviewDate)
{
$this->reviewDate = $reviewDate;
return $this;
}
/**
* Get reviewDate
*
* #return \DateTime
*/
public function getReviewDate()
{
return $this->reviewDate;
}
/**
* Set rollingWeeks
*
* #param integer $rollingWeeks
* #return RotaObj
*/
public function setRollingWeeks($rollingWeeks)
{
$this->rollingWeeks = $rollingWeeks;
return $this;
}
/**
* Get rollingWeeks
*
* #return integer
*/
public function getRollingWeeks()
{
return $this->rollingWeeks;
}
/**
* Add rotaShifts
*
* #param \Rota\Bundle\Entity\RotaShift $rotaShifts
* #return RotaMain
*/
public function addRotaShift(\Rota\Bundle\Entity\RotaShift $rotaShift)
{
$this->rotaShifts[] = $rotaShift;
return $this;
}
/**
* Remove rotaShifts
*
* #param \Rota\Bundle\Entity\RotaShift $rotaShifts
*/
public function removeRotaShift(\Rota\Bundle\Entity\RotaShift $rotaShifts)
{
$this->rotaShifts->removeElement($rotaShifts);
}
/**
* Get rotaShifts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getRotaShifts()
{
return $this->rotaShifts;
}
/**
* Set restDayCount
*
* #param integer $restDayCount
* #return RotaMain
*/
public function setRestDayCount($restDayCount)
{
$this->restDayCount = $restDayCount;
return $this;
}
/**
* Get restDayCount
*
* #return integer
*/
public function getRestDayCount()
{
return $this->restDayCount;
}
/**
* Set totalDayCount
*
* #param integer $totalDayCount
* #return RotaMain
*/
public function setTotalDayCount($totalDayCount)
{
$this->totalDayCount = $totalDayCount;
return $this;
}
/**
* Get totalDayCount
*
* #return integer
*/
public function getTotalDayCount()
{
return $this->totalDayCount;
}
/**
* Set shiftOrder
*
* #param string $shiftOrder
* #return RotaMain
*/
public function setShiftOrder($shiftOrder)
{
$this->shiftOrder = $shiftOrder;
return $this;
}
/**
* Get shiftOrder
*
* #return string
*/
public function getShiftOrder()
{
return $this->shiftOrder;
}
}
This class holds collection of:
<?php
namespace Rota\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* RotaShift
*
* #ORM\Table()
* #ORM\Entity
*/
class RotaShift
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $_id;
/**
* #var integer
*
* #ORM\Column(name="startTime", type="integer")
*/
private $_startTime;
/**
* #var integer
*
* #ORM\Column(name="endTime", type="integer")
*/
private $endTime;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=50)
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="RotaMain", inversedBy="rotaShifts")
*/
private $rotaMain;
/**
* Get _id
*
* #return integer
*/
public function getId()
{
return $this->_id;
}
/**
* Set _startTime
*
* #param integer $startTime
* #return RotaShift
*/
public function setStartTime($startTime)
{
$this->_startTime = $startTime;
return $this;
}
/**
* Get _startTime
*
* #return integer
*/
public function getStartTime()
{
return $this->_startTime;
}
/**
* Set endTime
*
* #param integer $endTime
* #return RotaShift
*/
public function setEndTime($endTime)
{
$this->endTime = $endTime;
return $this;
}
/**
* Get endTime
*
* #return integer
*/
public function getEndTime()
{
return $this->endTime;
}
/**
* Set name
*
* #param string $name
* #return RotaShift
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set rotaMain
*
* #param \Rota\Bundle\Entity\RotaMain $rotaMain
* #return RotaShift
*/
public function setRotaMain(\Rota\Bundle\Entity\RotaMain $rotaMain = null)
{
$this->rotaMain = $rotaMain;
return $this;
}
/**
* Get rotaMain
*
* #return \Rota\Bundle\Entity\RotaMain
*/
public function getRotaMain()
{
return $this->rotaMain;
}
}
I have then created a Form EntityType class for the RotaMain object as follows:
<?php
namespace Rota\Bundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class RotaMainType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder-> add('ReviewDate','date');
$builder->add('RollingWeeks','integer');
$builder->add('StartDate','date');
$builder->add('RestDayCount','integer',array('label' => 'Number of rest days'));
$builder->add('TotalDayCount','integer',array('label' => 'Total number of days in shift pattern'));
$builder->add('rotaShifts','collection',array('type'=> new RotaShiftType(),'label' => false,'allow_add' => true,));
$builder->add('Save','submit');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Rota\Bundle\Entity\RotaMain',
));
}
public function getName()
{
return 'rotaMain';
}
}
When I try to set a form with a fully populated RotaMain object:
$form = $this->createForm(new RotaMainType(),$RotaMain);
I get the following error:
The form's view data is expected to be of type scalar, array or an instance of
\ArrayAccess, but is an instance of class Rota\Bundle\Entity\RotaMain. You can avoid
this error by setting the "data_class" option to "Rota\Bundle\Entity\RotaMain" or by
adding a view transformer that transforms an instance of class
Rota\Bundle\Entity\RotaMain to scalar, array or an instance of \ArrayAccess.
I have set the data_class in the RotaMainType object so am not sure where I am going wrong? If I pass an empty RotaMain object to the form it builds as expected.
The population of RotaMain happens in the controller. The form is part one of two part process. If user has completed first part gone away and come back I want reutnr the first part fo them to review before going onto the second part of the process. Controller action:
public function setRotaAction(Request $request,$userId)
{
//Check to see if user has part set up a rota - return completed form for review
$RotaMainRepos = $this->getDoctrine()->getManager()->getRepository("RotaBundle:RotaMain");
$id = $this->getUser()->getID();
$criteria = array("myUserId"=>$id);
$result = $RotaMainRepos->findBy($criteria);
if($result == null)
{
$RotaMain = new RotaMain();
$RotaMain->setmyUserId($userId);
$form = $this->createForm(new RotaMainType(),$RotaMain);
}
else
{
$RotaMain = $result[0];
$rotashiftRepo = $this->getDoctrine()->getManager()->getRepository("RotaBundle:RotaShift");
$rotaShifts = $rotashiftRepo->findByRotaMain($RotaMain);
foreach($rotaShifts as $rotaShift)
{
$RotaMain->addRotaShift($rotaShift);
}
$form = $this->createForm(new RotaMainType(),$RotaMain);
}
$form->handleRequest($request);
if($form->isValid())
{
$early = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($early);
$shifts = $early->getRotaShifts();
foreach($shifts as $shift)
{
$shift->setRotaMain($early);
$em->persist($shift);
}
$em->flush();
$shiftOrder = new ShiftOrder($shifts,$early->getRestDayCount(),$early->getTotalDayCount());
return $this->render("RotaBundle:Default:shiftOrder.html.twig",array("shiftOrder" => $shiftOrder));
}
return $this->render('RotaBundle:Default:setRota.html.twig',array("form" => $form->createView(),));
}
You have to bind a newly created or existing entity/object of the same type as the configured data_class to your form.
If you don't set the variable you're passing to your form to an object of the expected data_class symfony won't create the object but throw this exception.
In your case you might want to use a SensioFrameworkExtraBundle's #ParamConverter to fetch your entity from database and have your controller cleaned up.
/**
* #Route("/whatever/{id}")
* #ParamConverter("rotaMain", class="RotaBundle:RotaMain", options={"mapping": {"MyUserId": "id"}})
*/
public function editAction(RotaMain $rotaMain, Request $request)
{
$form = $this->createForm(new RotaMainType(), $rotaMain);
$form->handleRequest($request);
if ($form->isValid()) {
//
}
}
... or ...
public function newAction(Request $request)
{
$form = $this->createForm(new RotaMainType(), $rotaMain = new RotaMain());
$form->handleRequest($request);
if ($form->isValid()) {
//
}
}
Found the answer to this - it was the way I was accessing and setting MyRotaShift entities in RotaMain. My addRotashift() function was not correctly adding rotaShifts to the Doctrine ArrayColleciton. On changing my controller code to:
foreach($rotaShifts as $rotaShift)
{
$RotaMain->getRotaShifts()->add($rotaShift);
}
it all works. Thought I was going mad for a while!!!
Turns out not mad but I should have read the Doctrine docs before pushing ahead. If I had I would have realized that is uses Lazy loading and saved myself a load of bother!!!
Have accepted nifr's answer as it provides a good way to do what I was trying to accomplish