Doctrine2: schema-tool Mappedsuperclass problem - php

baseclass.php
---------------------------------------------------------
/**
*
* #MappedSuperclass
*
*/
class Baseclass {
// code
}
aclass.php
----------------------------------------------------------
/**
* #Entity #Table(name="something")
*/
class Aclass extends Baseclass{
// code
}
with this code above, when I try to execute
doctrine schema-tool:create
I get BaseClass not found error, but when I change the name of the
Aclass name to Dclass (alphabetically after BaseClass ) everything
works fine. I remember seeing some bug report somewhere that says,
it's something to do with alphabetical order, but I can not find that
report and I wonder if there is a solution for this problem? I use
doctrine 2.0 stable by the way.

You should set up autoloading of your classes in your doctrine-cli.php script.

Related

symfony 2 - Attempted to call an undefined method named "findBy" of class "testBundle\Entity\test"

I can't get data out of the database. Here's the code:
$testRepository= $this->getDoctrine()->getRepository('testBundle:test');
$potds = $testRepository->findBy(
array(),
);
Here's the entity class:
* #ORM\Table()
* #ORM\Entity(repositoryClass="testBundle\Entity\test")
* #ORM\HasLifecycleCallbacks
*/
class test
{ /* ... */ }
Here's the code of the Repository:
namespace testBundle\Entity;
/**
* TestRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class testRepository extends \Doctrine\ORM\EntityRepository
{
}
I get this error message: symfony 2 - Attempted to call an undefined method named "findBy" of class "testBundle\Entity\test"
Inserting data with Doctrine works, so there should be everything right with the Entity.
You have incorrect repository class definition:
#ORM\Entity(repositoryClass="testBundle\Entity\test")
Should be:
#ORM\Entity(repositoryClass="testBundle\Entity\testRepository")
For now this code:
$testRepository= $this->getDoctrine()->getRepository('testBundle:test');
is returning entity class, not repository.
Your definition for the repositoryClass is wrong
#ORM\Entity(repositoryClass="testBundle\Entity\test")
doesn't provide the full path and class name.
#ORM\Entity(repositoryClass="testBundle\Entity\testRepository")
you need to provide the full path and class name, so that Symfony is able to get the correct route.

Doctrine 2 how to properly map multi-level inheritance

I have multi-level inheritance doctrine entity like this:
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"customer" = "CustomerUser",
* "admin" = "AdminUser", "stock" = "StockUser"})
*/
abstract class User { ... }
/** #ORM\Entity */
abstract class EmployeeUser extends User { ... }
/** #ORM\Entity */
class AdminUser extends EmployeeUser { ... }
/** #ORM\Entity */
class StockUser extends EmployeeUser { ... }
However it does not work this way, fields of EmployeeUser are neither read from database nor persisted.
I've found out that it works when I specify the discriminator map this way:
* #ORM\DiscriminatorMap({"customer" = "CustomerUser",
* "admin" = "AdminUser", "stock" = "StockUser", "EmployeeUser"})
it starts to work this way (there is no need to specify discriminator key for EmployeeUser - as it is abstract and will never be instantiated), but
I don't like when magic happen that I don't understand enough :) so my question is: is this a proper solution? To just let Doctrine know this way that this class is somehow included in inheritance hierarchy? Or should it be done anyhow else?
I haven't found any mention about how to do multiple level entity class inheritance in Doctrine docs.
I have same situation. I need more than one level of inheritance. That in your case is expected behavior, you need to list all of mapped classes in DiscriminatorMap.
My case don't have that map because I am using native transformation of ClassName to type key and it's working for classes on all inheritance level.
abstract ClassA
abstract ClassB extends ClassA
- protected someName
ClassC extends ClassB
When I save ClassC obj I have that property someName saved. You can try yourself without discriminatory map and see that all classes are mapped and save.
EDIT :
One more thing if you want to avoid multilevel inheritance you can always use trait for that. Just group the props to trait and add it to entity. There are good example of trait usage in DoctrineBehaviors bundle. There are using it to import additional capabilities to entities like blamable, loggable etc.

Doctrine2 Entity Manager cannot find Custom Repository Class in namespace

I have Silex setup with Doctrine2 ORM. I am trying to build a pagination class that I can use with my entities. I am well aware of the existing pagination classes that exist within Doctrine2 but because this project is for my school research I am trying to create this component myself.
Below is the fatal error I get when accessing this page:
Fatal error: Class 'PlayGround\Model\Helper\UserRepository' not found in D:\web\playground-solutions\vendor\doctrine\orm\lib\Doctrine\ORM\EntityManager.php on line 689
I have defined an interface called PaginateableInterface with two methods count and paginate. I went on to define a custom EntityRepository class that extends Doctrine\ORM\EntityRepository. Below is my custom EntityRepository.
<?php
namespace PlayGround\Service\Doctrine;
use Doctrine\ORM\EntityRepository as ParentEntityRepository;
class EntityRepository extends ParentEntityRepository{
public function count(){
$em = $this->getEntityManager();
$builder = $em->createQueryBuilder();
/**
* ToDo: #entity
*
* Still need to find a better way of getting entity class name.
*/
$entity = $em->getClassMetadata(get_class(__CLASS__))->getName();
//Dynamically get a count of records on any entity we happen to call this on.
$builder->select($builder->expr()->count('e'))
->from($entity, 'e');
$query = $builder->getQuery();
//Try-Catch block ommitted
return $query->getSingleScalarResult();
}
}
<?php
namespace PlayGround\Model\Helper;
use PlayGround\Service\Doctrine\EntityRepository as CustomRepository;
use PlayGround\Contract\PaginateableInterface as IPaginate;
class UserRepository extends CustomRepository implements IPaginate
{
}
In my understanding this should suffice as the count and paginate methods are sitting within the custom repository.
Inside my Paginator class I call the entity I want to paginate as shown below:
<?php
//Paginator class
$model = $this->getModel($model);
//Count should be inherited from CustomRepository aliased object.
$totalRecords = $model->count();
Below is another pierce of meet with regards to this where I add an annotation to my model to point it to the repository class it is suppose to use.
<?php
namespace Application\Model\Entity;
use Doctrine\ORM\Mapping as ORM;
use Application\Model\Entity\UserGroup;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
* #ORM\Entity(repositoryClass="PlayGround\Model\Helper\UserRepository")
*/
class User{ /* Rest of the code goes here... */ }
Given all this setup what could I have missed in getting this to work? I have even ran two commands on my doctrine console but that didn't help either.
Luyanda.Siko#ZACT-PC301 MINGW64 /d/web/playground-solutions
$ php app/Console/bin/doctrine.php orm:clear-cache:metadata
Clearing ALL Metadata cache entries
Successfully deleted cache entries.
Luyanda.Siko#ZACT-PC301 MINGW64 /d/web/playground-solutions
$ php app/Console/bin/doctrine.php orm:clear-cache:query
Clearing ALL Query cache entries
Successfully deleted cache entries.
EDIT:
Below is my file structure found in D:\web\playground-solutions.
You declare twice #ORM\Entity. Once with the repositoryClass and once without. Remove the one without:
#ORM\Entity
and leave this:
#ORM\Entity(repositoryClass="PlayGround\Model\Helper\UserRepository")
#ORM\HasLifecycleCallbacks should be declared without parentheses ()...
Also make sure that the EntityRepository is in the correct namespace and the corresponding folder:
your namespace is PlayGround\Model\Helper\UserRepository meaning the file should be in folder PlayGround\Model\Helper and the class file name should be UserRepository.php.
Fix and check that and if it still doesn't work leave a comment.
UPDATE:
Your UserRepository is in the wrong module. Is now in app should be in PlayGround
The file should be in:
src/PlayGround/Model/Helper/UserRepository.php
It's all about that problem.
Clearly this has really consumed my thought process. All I was doing was pointing to an incorrect namespace as pointed out by #Witt.
I changed my annotation entry in the User entity and the error went away.
<?php
/** #ORM\Entity(repositoryClass="Application\Model\Helper\UserRepository") */
Thanks you guys.

Doctrine MongoDB Referencing and Inheritance

I am having problems with Doctrine MongoDB ODM. Scenario is very simple (I think).
I have set of documents with COLLECTION_PER_CLASS inheritance model (Base, Product, etc). This all works well and I can persist objects as usual.
/**
* #ODM\Document(collection="content_base")
* #ODM\InheritanceType("COLLECTION_PER_CLASS")
*/
class Base {
/**
* #ODM\Document(collection="content_products")
*/
class Product extends Base {
Now, I have another Document (Item) and I want to create ReferenceOne to inherited Documents:
/**
* #ODM\ReferenceOne(targetDocument="Base")
*/
private $content;
And this is where I am having problems, because Doctrine ClassLoader complains about class Base being redeclared:
Fatal error: include(): Cannot redeclare class content\documents\types\base in /vendor/composer/ClassLoader.php on line 183
I am a bit confused why would this be a problem, or otherwise what is correct way of doing this?
UPDATE
I have just noticed, if I remove 'targetDocument' from ReferenceOne annotation I get results I wanted. Is this the correct way to do it?
Thanks,
Greg

Doctrine 2 LifecycleCallbacks with abstract base class are not called

I have this situation:
Abstract Class:
abstract class AbstractBase
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #var integer
*/
protected $id;
/**
* #ORM\Column(type="datetime", name="updated_at")
* #var \DateTime $updatedAt
*/
protected $updatedAt;
/**
* #ORM\PreUpdate
*/
public function setUpdatedAt()
{
die('THIS POINT IS NEVER REACHED');
$this->updatedAt = new \DateTime();
}
}
Concrete Class:
/**
* #ORM\Entity(repositoryClass="Entity\Repository\UserRepository")
* #ORM\Table(name="users")
* #ORM\HasLifecycleCallbacks
*/
class User extends AbstractBase
{
// some fields, relations and setters/getters defined here, these all work as expected.
}
Then i call it in my controller like this:
$user = $this->em->find('Entity\User', 1);
// i call some setters here like $user->setName('asd');
$this->em->flush();
die('end');
Everything works as expected, so the id field from the abstract class gets created for the User entity, i can access it etc.
The problem is, that the line "die('THIS POINT IS NEVER REACHED')" is never reached. (Note the #ORM\PreUpdate) This means that lifecycleCallbacks are not called on
inherited objects. Is this a bug, or is there a reason for this?
Your abstract base class has to be anotated as Mapped Superclasses and include the HasLifecycleCallbacks-Annotation.
Further Information: Inheritance Mapping in the Doctrine Documentation.
/**
* #ORM\MappedSuperclass
* #ORM\HasLifecycleCallbacks
*/
abstract class AbstractBase
{
[...]
/**
* #ORM\PreUpdate
*/
public function setUpdatedAt()
{
$this->updatedAt = new \DateTime();
}
}
/**
* #ORM\Entity(repositoryClass="Entity\Repository\UserRepository")
* #ORM\Table(name="users")
*/
class User extends AbstractBase
{
// some fields, relations and setters/getters defined here, these all work as expected.
}
You have to annotate the base class with #ORM\HasLifecycleCallbacks, and the function with #ORM\preUpdate
You have a typo (PreUpdate should be preUpdate), also preUpdate isn't called on creation (only on update). So if you want it also be triggered on creation, you should add #ORM\prePersist.
While the accepted reply is correct for the general case, in this particular case (timestamp) you actually want to use the doctrine extension Timestampable as explained for example here Lifecycle Callback Issue When Extending FOSUserBundle User Entity
It is important that the MappedSuperclass with HasLifecycleCallbacks is in the same namespace or directory as their child Entities.
I had problems with life cycle callbacks when the MappedSuperclass was in one directory (Model) while the Entities were in another (Entity). Putting the MappedSuperclass in the same directory as the Entities (Entity) solved the issue.
Maybe i'm wrong but I don't think preUpdate isn't triggered when you persist an entity. You should have a #prePersist.
http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html
But still then i'm not sure this is going to work but you could try that. Else a workaround would be to overwrite the setUpdatedAt function and just call his parent one but that's a bit ugly.
Hope the #prePersist helps for you.
Perhaps you could this issue report as a reference how to setup your annotations? The testcase seems to be valid and matches your use case.
I think you have to annotate the base class with #ORM\HasLifecycleCallbacks
docs

Categories