I have tried searching around and even the example in the Symfony2 documentation, and have been struggling with writing a query to select all blog posts by post category and to order them in descending order by Id.
However I have the following error when i run the code. Any suggestions?
ContextErrorException in SimpleArrayType.php line 51:
Warning: implode(): Invalid arguments passed
I am creating a blog, for learning purposes and am trying to retrieve posts from my posted table with the following columns.
Id |postTitle | postDescription | postContent | postCategory
My Entity looks like this, (showing most relevant sections)
/**
* posted
*
#ORM\Table()
* #ORM\Entity
*/
class posted
{
/**
* #ORM\Column(type="string", length=500)
*/
protected $postTitle;
/**
* #ORM\Column(type="string", length=500)
*/
protected $postDescription;
/**
* #ORM\Column(type="string", length=500)
*/
protected $postContent;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="datetime", name="posted_at")
*/
protected $datePosted;
/**
*#var array
* #ORM\Column(type="simple_array", length=250)
*/
protected $postCategory;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set postCategory
*
* #param string $postCategory
* #return posted
*/
public function setPostCategory($postCategory)
{
$this->postCategory = $postCategory;
return $this;
}
/**
* Get postCategory
*
* #return string
*/
public function getPostCategory()
{
return $this->postCategory;
}
My Controller looks like
/**
* this is the EPL page of posts of EPL category
*
* #Route("/EPL", name="eplposts")
* #Method("GET")
* #Template()
*/
public function eplAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('BlogBundle:posted')->findBy(array('postCategory' => 'English Premier League','id' => 'desc'));
return $this->render('BlogBundle:Default:EPLpost.html.twig',array(
'entities' => $entities,
));
}
I suggest that you create your own query method in the repository of your entity, for example, something like this :
class BoardRepository extends EntityRepository
{
public function findByCategory($category)
{
$builder = $this->createQueryBuilder('p');
$builder
->where($builder->expr()->like('p.postCategory', '%'.$category.','))
->orWhere($builder->expr()->like('p.postCategory', ','.$category.'%'))
;
return $builder->getQuery()->execute();
}
}
Related
Since last week I have started learning Symfony, and while the general stuff it quite easy to learn, the Doctrine seems to be a big pain.
Currently, I have made two entities using the following signature:
<?php
namespace NutritionApiBundle\Entity;
// ...
use Doctrine\Common\Collections\ArrayCollection;
// ...
/**
* Company
*
* #ORM\Table(name="company")
* #ORM\Entity(repositoryClass="NutritionApiBundle\Repository\CompanyRepository")
*/
class Company {
/**
* #var string
*
* #ORM\Column(name="id", type="guid")
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
// ...
/**
* #var string
* #ORM\OneToMany(targetEntity="NutritionApiBundle\Entity\Product", mappedBy="company")
*/
protected $products;
public function __construct() {
$this->products = new ArrayCollection();
}
// ...
}
and
<?php
namespace NutritionApiBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
// ...
/**
* Class Product
*
* #package NutritionApiBundle\Entity
*
* #ORM\Entity
* #ORM\Table(name="product")
*/
class Product {
/**
* #var string
* #ORM\Column(type="guid")
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
protected $id;
// ...
/**
* #var Company
*
* #ORM\Column(type="guid", name="company", nullable=false)
* #ORM\ManyToOne(targetEntity="NutritionApiBundle\Entity\Company", inversedBy="products")
* #ORM\JoinColumn(name="company", referencedColumnName="id")
*/
protected $company;
// ...
/**
* Return the product company
*
* #return Company
*/
public function getCompany() {
return $this->company;
}
/**
* Set the product company.
*
* #param Company $company
*
* #return Product
*/
public function setCompany( Company $company ) {
$this->company = $company;
return $this;
}
}
But when I try to execute the following code:
$product = $this->getDoctrine()->getRepository(Product::class)->findOneBy(['id' => '0642d735-fcfd-11e7-afae-0242c0a86002']);
return $this->render( '#NutritionApi/Default/index.html.twig', [ 'product' => $product ] );
And inside the index.html.twig I have this code:
{{ dump(product.company) }}
The output is the following:
"e65af24f-fd0a-11e7-afae-0242c0a86002"
While I need the full company object as output.
Do you see anything wrong with my code? I have read my code and my annotations multiple times in order to spot a mistake but I cannot find anything.
The only thing that I guess it could be the problem is the GUID id I use for the entities in my DB, but I am not sure this is the problem.
Any suggestion, please?
You may have to remove
#ORM\Column(type="guid", name="company", nullable=false)
From Product $company property.
I'm writing an application using Zend Framework 3. To manage database I decided to use Doctrine. I have two tables pages and pages_meta(something based on wordpress db). They are realted to each other in one-to-many, many-to-one relation. In pages_meta I have key page_id. Now when I try to get meta form Page Entity I got following error:
File: /home/platne/serwer18346/vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php:169
Message: Call to a member function setValue() on null
Now the application code:
Page Entity(removed some code to show important part):
namespace Core\Model;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Class Page
* #package Core\Model
* #ORM\Entity
* #ORM\Table(name="pages")
*/
class Page
{
/**
* #var int
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(name="id")
*/
protected $id;
//other fields definition(here is slug to found by)
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="\Core\Model\PageMeta", mappedBy="pages")
* #ORM\JoinColumn(name="id", referencedColumnName="page_id")
*/
protected $meta;
/**
* Page constructor.
*/
public function __construct()
{
$this->meta = new ArrayCollection();
}
/**
* #return int
*
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $key
* #return ArrayCollection
*/
public function getPageMeta($key = null){
if(!$key) return $this->meta;
return $this->meta->current(); //this is causing the problem tried other functions as well
}
}
PageMeta Entity(same here I removed some code):
namespace Core\Model;
use Doctrine\ORM\Mapping as ORM;
/**
* Class PageMeta
* #package Core\Model
* #ORM\Entity
* #ORM\Table(name="page_meta")
*/
class PageMeta
{
/**
* #var int
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(name="id")
*/
protected $id;
/**
* #var int
* #ORM\Column(type="integer", name="page_id")
*/
protected $page_id;
/**
* #var Page
* #ORM\ManyToOne(targetEntity="\Core\Model\Page", inversedBy="page_meta")
* #ORM\JoinColumn(name="page_id", referencedColumnName="id")
*/
protected $page;
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #return int
*/
public function getPageId(): int
{
return $this->page_id;
}
/**
* #param int $page_id
* #return PageMeta
*/
public function setPageId(int $page_id): PageMeta
{
$this->page_id = $page_id;
return $this;
}
//other field definition
/**
* #return Page
*/
public function getPage(){ //this works fine
return $this->page;
}
}
In the controller:
$this->getEntityManager()->getRepository(Page::class);
$page = $pagesTable->findOneBySlug($slug);
//check if page exists
$page->getPageMeta('test'); //this line cause the problem.
Full stack error you can see on page: http://bibliotekadomowa.pl/o-nas
I think it may be an issue with the "mappedBy" param in Page, try changing that to
mappedBy="page"
As it should match the variable name not the table name
In my User entity, I have this:
/**
* #ORM\Entity
* #ORM\Table(name="users")
*/
class User extends BaseUser
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
* #ORM\OneToMany(targetEntity="Blog\BlogBundle\Entity \Entry",mappedBy="author")
*/
protected $entries;
This is my full Entry entity.
<?php
namespace Blog\BlogBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Entry
*
* #ORM\Table(name="entry")
* #ORM\Entity(repositoryClass="Blog\BlogBundle\Repository\EntryRepository")
*/
class Entry
{
/**
* #var int
*
* #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="book", type="text")
*/
private $book;
/**
* #var \DateTime
*
* #ORM\Column(name="timestamp", type="datetime")
*/
private $timestamp;
/**
* #var AppBundle\Entity
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User",inversedBy="entries")
* #ORM\JoinColumn(name="author", referencedColumnName="id")
*/
private $author;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
* #ORM\OneToMany(targetEntity="Blog\BlogBundle\Entity\Reviews",mappedBy="book_id")
*/
protected $reviews;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
*
* #return Entry
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set book
*
* #param string $book
*
* #return Entry
*/
public function setBook($book)
{
$this->book = $book;
return $this;
}
/**
* Get book
*
* #return string
*/
public function getBook()
{
return $this->book;
}
/**
* Set timestamp
*
* #param \DateTime $timestamp
*
* #return Entry
*/
public function setTimestamp($timestamp)
{
$this->timestamp = $timestamp;
return $this;
}
/**
* Get timestamp
*
* #return \DateTime
*/
public function getTimestamp()
{
return $this->timestamp;
}
/**
* Set author
*
* #param \AppBundle\Entity\User $author
*
* #return Entry
*/
public function setAuthor(\AppBundle\Entity\User $author = null)
{
$this->author = $author;
return $this;
}
/**
* Get author
*
* #return \AppBundle\Entity\User
*/
public function getAuthor()
{
return $this->author;
}
/**
* Get author ID
*
* #return \AppBundle\Entity\User
*/
public function getAuthorId()
{
$id = $this->author;
return $this->$id;
}
public function __toString()
{
try {
return (string) $this->id;
} catch (Exception $exception) {
return '';
}
}
}
From this piece of code I am trying to retrieve Author ID, but instead author name is being returned. I presume this is because I am converting to string at the end. If I remove it, I get this error: symfony2 Catchable Fatal Error: Object of class could not be converted to string
To get the link, I am doing the following:
Setting path author with parameter of id in routing.yml of the bundle which triggers authorAction($id) inside BookController. Expecting an integer to be passed.
authorAction($id) sets up Doctrine Manager, calls getAllBooksByAuthor() function in a repository where a relevant query returns all books by author with id and renders the twig template.
The link is generated in the twig template, but instead parameter passed is author name - which is a string, not an integer.
How can I do it so author ID is passed instead of author name?
I'm stuck here and I need Entry entity to be able to handle both strings and integers.
Specifically this is the change:
/**
* Get author ID
*
* #return intger
*/
public function getAuthorId()
{
return $this->author->getId();
}
Note: the #return documentation should be changed to show it's returning an integer.
I have a two Entitys Videoand Comment.
One video can have many comments (OneToMany).
Entity/Video.php
class Video
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="integer")
* #ORM\OneToMany(targetEntity="Comment")
* #ORM\JoinColumn(name="id", referencedColumnName="videoId")
*/
private $comments;
/**
* Set comments
*
* #param integer $comments
* #return comments
*/
public function setComments($comments)
{
$this->comments = $comments;
return $this;
}
/**
* Get comments
*
* #return integer
*/
public function getComments()
{
return $this->comments;
}
}
Entity/Comment.php
class Comment
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="integer")
* #ORM\ManyToOne(targetEntity="Video")
* #ORM\JoinColumn(name="videoId", referencedColumnName="id")
*/
private $videoId;
/**
* #ORM\Column(type="text")
*/
private $comment;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set videoId
*
* #param integer $videoId
* #return Comment
*/
public function setVideoId($videoId)
{
$this->videoId = $videoId;
return $this;
}
/**
* Get videoId
*
* #return integer
*/
public function getVideoId()
{
return $this->getVideo($this->videoId);
}
/**
* Set comment
*
* #param string $comment
* #return Comment
*/
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
/**
* Get comment
*
* #return string
*/
public function getComment()
{
return $this->comment;
}
}
VideoEntity: id PK
CommentEntity: videoId FK
I call the video in my controller like:
$repository = $this->getDoctrine()->getRepository('AppBundle:Video');
$video = $repository->findBy(array('id' => 1));
After this call, I have a filled video entity.
But video.comments are not filled with the comment entity.
It have only a integer.
Is it possible to fill the video.comments with the comment entity inside the video entity (video.id == comment.videoId)?
Example:
array
-- video entity
---- id
---- comments
------ array
-------- comment entity
---------- comment
-------- comment entity
---------- comment
-------- comment entity
---------- comment
I would be grateful for a best practice.
Thanks.
I believe you want to EAGER load those comments:
/**
* #ORM\Column(type="integer")
* #ORM\OneToMany(targetEntity="Comment",fetch="EAGER")
* #ORM\JoinColumn(name="id", referencedColumnName="videoId")
*/
private $comments;
Entity/Video.php
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Comment", mappedBy="videoId")
* #ORM\JoinColumn(name="id", referencedColumnName="video_id")
*/
private $comments;
Entity/Comment.php
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Video")
* #ORM\JoinColumn(name="video_id", referencedColumnName="id")
*/
private $videoId;
After I successfuly created TaskBundle with One-to-Many relation between category and tasks, now I'm trying to create a new TaskBundle with Many-to-Many relation. I get also problem with checking checkbox in this relation, but now it is not a primary problem (maybe after solving this). I deleted all tables, which is TaskBundle using and trying to create a new, but here is problem (description at the bottom).
My Task object:
<?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 is 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")
* #ORM\JoinTable(name="categories")
*/
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;
}
}
and Category object
<?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="Categories cannot be empty", 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;
}
}
So, after i put doctrine:schema:update --force i'll get error: Table 'symfony.categories' already exists. I've tried to delete all caches, but same problem. Any idea?
There's only problem, if it is as m2m relation.
PS: I was looking for this problem at the Google, but no one answers at this problem. There were only questions, but not correct answers, where the problem is and how to solve it.
Looks like you already have table named "categories" in that database. Remove this line #ORM\JoinTable(name="categories") and try without it.
P.S. "Categories" is really a strange name for join table. You should probably follow some conventions and let doctrine name it. Common names for join tables are category_task or category2task as they are more self-explanatory. Nothing that important, just trying to suggest what I consider good practice.
The thing is that doctrine doesn't understand how your existing table should be used. But you can give him some help.
You have two options :
You don't care about the existing table : simple, you can remove the #ORM\JoinTable(name="categories") annotation, and doctrine will create an other table etc.
You want to keep your existing table, which sounds pretty logical : you have to be more explicit in your annotation by adding #ORM\JoinColumn annotation.
Here is an example:
class
<?php
...
/**
* #ORM\Entity
* #ORM\Table(name="tasks")
*/
class Task
{
...
/**
* #ORM\ManyToMany(targetEntity="Category", inversedBy="tasks")
* #ORM\JoinTable(name="categories",
* joinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="task_id", referencedColumnName="id")})
*/
protected $category;
...
}
and Category object
<?php
...
/**
* #ORM\Entity
* #ORM\Table(name="categories")
*/
class Category
{
...
/**
* #ORM\ManyToMany(targetEntity="Task", mappedBy="category")
* #ORM\JoinTable(name="categories",
* joinColumns={#ORM\JoinColumn(name="task_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id")})
*/
private $tasks;
...
Doing so, you will be able to keep your table without any doctrine error.
My fix for this, as far as I can tell, was a case-sensitivity issue with table names. Doctrine let me create a Users and a users table but afterwards would die on migrations:diff or migrations:migrate .
I used the -vvv option to get more detail on this error message; it seems that the error happens when Doctrine is loading up its own internal representation of the current database's schema. So if your current database has table names that Doctrine doesn't understand (like two tables that are identical, case-insensitive) then it will blow up in this fashion.
Seems like most of the answers above assume that the error is in your code, but in my case it was in the database.
I got this error with 2 ManyToMany targeting the same entity (User in the exemple below).
To create the table name doctrine use the entity and target entity name.
So in my case it was trying to create two time the table thread_user
To debug this it's easy. Just use the '#ORM\JoinTable' annotation and specify the table name.
Here is a working exemple.
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User")
* #ORM\JoinTable(name="thread_participant")
*/
private $participants;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\User")
* #ORM\JoinTable(name="thread_recipient")
*/
private $recipients;
in Symfony4.1 you can force the migration using the migration version
doctrine:migrations:execute <migration version>
ex
for migration version123456.php use
doctrine:migrations:execute 123456
there is another using the table name ,you can search it in your project . Maby be demo,I think it...
sorry for my chinese english !
Try to drop everything inside of your proxy directory.
I fix same issue after check other entities on each bundles, be aware of this.