Simple example, we've got
/**
* #ORM\Column(name="api_keyID", type="integer", nullable=false)
*/
private $api_keyID;
/**
* #return integer
*/
public function getApi_keyID()
{
return $this->api_keyID;
}
/**
* #param integer $api_keyID
* #return object
*/
public function setApi_keyID($data)
{
$this->api_keyID = $data;
return $this;
}
Look at method name and column name. When i try
//...
->findOneByApi_keyID($some);
I'm getting an error like
Entity 'entity\path' has no field 'apiKeyID'. You can therefore not call 'findOneByApi_keyID' on the entities' repository
So doctrine\symfony eats underscore? О.о And i cannot use it in column name?
is the way out
$repository->findBy(array('is_enabled' => true));
Founded here
Magic Doctrine2 finders when field has underscore?
Related
I am stuck at this case, I reproduced it in an example from symfony documentation, here it how it looks:
FIXTURES
/**
* #ORM\Entity
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category", fetch="EAGER")
*/
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
public function products(): Collection
{
return $this->products;
}
public function id()
{
return $this->id;
}
}
and related Product class
/**
* #ORM\Entity
*/
class Product
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
public function __construct($category)
{
$this->category = $category;
}
public function id()
{
return $this->id;
}
public function category()
{
return $this->category;
}
}
TEST
Now I have this snippet of test code where I want to fetch Category and be able to get its Products:
$cat = new Category();
$prod = new Product($cat);
$this->entityManager->persist($prod);
$this->entityManager->persist($cat);
$this->entityManager->flush();
$crepo = $this->getEntityManager()->getRepository(Category::class);
$c = $crepo->findAll()[0];
var_dump(get_class($c->products()), $c->products()->count())
What I am getting is products of class PersistentCollection which is expected, but the count is 0 while there should be 1 product.
I can see that in the database I have proper category and product records with proper foreign key set.
WORKAROUND
I am debugging PersistentCollection for products and can see that its flag is set to initialized = true. With this I am able to force this to work by calling
$c->products()->setInitialized(false);
$c->products()->initialize();
But afaik this is not how it should work, should it ?
I managed to found an answer. It basically works but not when run in the same process. If I split the script in two - first one persists, second retrieves the data then the products collection will contain products related to category.
This is because when it is done in single process doctrine does not know that the category in question has products, and since it retrieves the same object it just saved and that was created few lines above, the entity manager won't populate the collection using database but will use the one from the category object. And the category object does not have products in products collection, since there is no call like $this->products()->add($category) neither in Product constructor or anywhere else. Only forcing to reinitialize the collection works since then it really retrieves products from database
I have 2 entities Submission and Documents. 1 Submission can have Multiple documents.
Submission Entity:
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Document", mappedBy="submission",cascade={"persist", "remove" })
* #ORM\JoinColumn(name="id", referencedColumnName="submission_id")
*/
protected $document;
/**
* #return mixed
*/
public function getDocument()
{
return $this->document->toArray();
}
public function setDocument(Document $document)
{
$this->document[] = $document;
return $this;
}
Document Entity:
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Submission", inversedBy="document")
* #ORM\JoinColumn(name="submission_id", referencedColumnName="id",onDelete="cascade", nullable=true)
*/
protected $submission;
public function getSubmission()
{
return $this->submission;
}
/**
* #param mixed $submission
*/
public function setSubmission($submission)
{
$this->submission = $submission;
}
After receiving files dropzonejs - I'm saving them into Document object, and then, i'm try to save this object into Submission, and persist.
$document = new Document();
$em = $this->getDoctrine()->getManager();
$media = $request->files->get('file');
foreach($media as $req){
$document->setFile($req);
$document->setPath($req->getPathName());
$document->setName($req->getClientOriginalName());
$em->persist($document);
}
$submission->setSubmissionStatus(true);
foreach($document as $item){
$submission->setDocument($item);
}
$submission->setUser($user);
$em = $this->getDoctrine()->getManager();
$em->persist($submission);
$em->flush();
Problem is that all the time, i'm receiving error that submission_title is not set, but that's not true, because i have set this field before. I haven't got idea, what is wrong.
I think you'll get some mileage out of following the tutorial over at http://symfony.com/doc/current/doctrine/associations.html, if you haven't already.
I can see that your getters / setters aren't optimal for associating more than one Document with your Submission.
As they write in the Symfony docs, where they want to associate one category with many products, they have the following code:
// src/AppBundle/Entity/Category.php
// ...
use Doctrine\Common\Collections\ArrayCollection;
class Category
{
// ...
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
}
From the docs:
The code in the constructor is important. Rather than being
instantiated as a traditional array, the $products property must be of
a type that implements Doctrine's Collection interface. In this case,
an ArrayCollection object is used. This object looks and acts almost
exactly like an array, but has some added flexibility. If this makes
you uncomfortable, don't worry. Just imagine that it's an array and
you'll be in good shape.
So, you'll want to be sure the constructor for your Document entity has something like $this->submissions = new ArrayCollection();. I've changed the property to a plural name, because I think it's more semantically correct. But you can keep your $submission property name, if you like.
Next is to add a addSubmission, removeSubmission, and a getSubmissions method.
Then, your class might end up looking like this:
<?php
// src/AppBundle/Entity/Submission.php
namespace AppBundle\Entity
use Doctrine\Common\Collections\ArrayCollection;
class Submission
{
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Document", mappedBy="submission",cascade={"persist", "remove" })
* #ORM\JoinColumn(name="id", referencedColumnName="submission_id")
*
* #var ArrayCollection()
*/
protected $documents;
...
/**
* Instantiates the Submission Entity
*
* #return void
*/
public function __construct()
{
$this->documents = new ArrayCollection();
}
/**
* Returns all documents on the Submission
*
* #return mixed
*/
public function getDocuments()
{
return $this->documents;
}
/**
* Add document to this Submission
*
* #param Document $document The object to add to the $documents collection.
*
* #return Submission
*/
public function setDocument(Document $document)
{
$this->documents[] = $document;
return $this;
}
/**
* Remove a document from this Submission
*
* #param Document $document The object to remove from the $documents collection.
*
* #return Submission
*/
public function removeDocument(Document $document)
{
$this->documents->removeElement($document);
return $this;
}
}
I have a problem of recognition constrains() method in Symfony2. I have a relationship between the groups & Roles entities: So a group must have a mandatory role and the role may or may not have one or more groups. So in my addRoles function ( Groups $grp) I have checked each time if the group has a role so we joust if not assigning a role. But when inserting,
I encounter a problem:
PHP Fatal error: Call to undefined method
MemberShipManagement\GroupsBundle\Entity\Roles::contains() in
/var/www/Project_Console/src/MemberShipManagement/GroupsBundle/Entity/Roles.php
on line 118,
Class Groups:
/**
* #var Roles $role
*
* #ORM\ManyToOne(targetEntity="Roles", inversedBy="groups")
* #ORM\JoinColumn(name="role_id", referencedColumnName="id", nullable=false)
*
* #Assert\Valid()
*/
protected $role;
Class Roles:
/**
* #var ArrayCollection $groups
*
* #ORM\OneToMany(targetEntity="Groups", mappedBy="role", cascade={"remove"} )
*#Assert\Valid()
*/
protected $groups;
/**
* Add group
* #param Groups $grp
*/
public function addRoles(Groups $grp) {
// $grp->setRole($this);
if (!$this->groups->contains($grp)) {
$this->groups->add($grp);
}
return $this;
}
/**
* Remove groups
* #param Groups $groups
*/
public function removeRoles(Groups $groups)
{
if ($this->groups->contains($groups)) {
$this->groups->removeElement($groups);
}
return $this;
}
public function __construct()
{
$this->groups = new ArrayCollection();
}
thank you :)
Maybe you could try to check if the data exists before calling the contains method like,
public function addRoles(Groups $grp) {
// $grp->setRole($this);
if ( !isEmpty($this->groups) ){
if (!$this->groups->contains($grp)) {
$this->groups->add($grp);
}
}
return $this;
}
since the error you get seems to be derived from the fact that $groups are not interpreted as ArrayCollection defined in doctrine.(if so, you could've called contains method defined there)
http://www.doctrine-project.org/api/common/2.4/class-Doctrine.Common.Collections.ArrayCollection.html
As long as other examples using contains method are found like this(https://groups.google.com/forum/#!topic/doctrine-user/i6IhBPHALkk) your approach looks correct.
Otherwise you could try to change $role to private instead of protected?
I get this exeption when I submit my form:
Found the public method "addRemote", but did not find a public "removeRemote" on class App\CoreBundle\Entity\Scene
The weired think is that the remove method exist ...
But i wrote it myself (When I did php app/console doctrine:generate:entities) doctrine didn't generated it. Did I make something wrong ?
/**
* #var array $remote
*
* #ORM\Column(name="remote", type="array", nullable=true)
*/
private $remote;
/**
* Set remote
*
* #param array $remote
* #return Scene
*/
public function addRemote($value, $key=null) {
if($key!=null){
$this->remote[$key] = $value;
}else{
$this->remote[] = $value;
}
return $this;
}
/**
* Remove remote
*/
public function removeRemote(){
unset($this->remote);
}
I allso tried:
/**
* Remove remote
*/
public function removeRemote($key=null){
if($key!=null && array_key_exists($key, $this->remote)){
unset($this->remote[$key]);
}
unset($this->remote);
return $this;
}
You have bigger problem than this; you are abusing your forms :)
Add.. and Remove... methods should be used for relations, not columns as per your code. Also, both add and remove methods must accept parameter that will be either added or removed.
If you still need an array, than getRemotes() method should return key=>value array. Adder and remover will later get that key, based on what user have picked in choice form type.
I have two entities one is main and second is additional, they joined as OneToOne. I won't show all, i think it's not necessary:
apiKey
/**
* #ORM\OneToOne(targetEntity="Eve\ApiBundle\Entity\Account\apiKeyInfo", inversedBy="apiKey_byKeyID")
* #ORM\JoinColumn(name="keyID", referencedColumnName="keyID")
*/
private $apiKeyInfo_byKeyID;
public function get_apiKeyInfo_byKeyID()
{
return $this->apiKeyInfo_byKeyID;
}
apiKeyInfo
/**
* #ORM\OneToOne(targetEntity="Eve\ProfileBundle\Entity\apiKey", mappedBy="apiKeyInfo_byKeyID")
*/
private $apiKey_byKeyID;
public function get_apiKey_byKeyID()
{
return $this->apiKey_byKeyID;
}
/**
* #ORM\Column(name="type", type="string", length=255)
*/
private $type;
/**
* #param string $type
* #return apiKeyInfo
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* #return string
*/
public function getType()
{
return $this->type;
}
Relation i call in twig (apiKey is goten in php part)
apiKey.get_apiKeyInfo_byKeyID.type
It works fine when db tables is full of data, but when "apiKeyInfo" table doesn't have same keyID it throw me exception:
Entity was not found.
I understand why, because it cannot find entries with same keyID ... But i don't know how to deal with it.
So question is...
How can i make result, of this relation, can be null?
Trouble was in incorrect descriptions of entity. Problem solved.