Class inheritance is not found - php

I am building an application using Zend Framework and Doctrine 2.
My code looks like this:
namespace Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity (repositoryClass="Repositories\Person")
* #Table(name="persons")
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="type", type="string")
* #DiscriminatorMap({"2"="User"})
*/
class Person
{
/**
* #Id #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
}
And my class User
namespace Entities;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity (repositoryClass="Repositories\User")
*/
class User extends Person
{
}
Now, I get this error:
Fatal error: Class 'Entities\Person' not found in C:\xamp\htdocs\Persons\application\m
odels\Entities\User.php on line 13
I have no idea why I get that error. I have tried calling the "Person" class in many different ways but the its not working. Any idea? Thanks!

When running in Zend Framework, you have an autoloader setup that handles the loading of classes for you dynamically.
When you run just the Doctrine tool from the command line, you don't have an autoloader at your disposal. Doctrine is trying to load the User class, which requires Person, and yet it doesn't (apparently) know how to load Person.
I think the simple solution would be to have require_once('Person.php'); at the top of your User entity. This is probably unnecessary for ZF, but will be helpful for Doctrine command line tools.

Related

Symfony - Optional inheritance with Doctrine

We encounter an issue with inheritance on Symfony 5.
We created a UserBundle bundle which includes a simple User entity (id, email, password): the purpose of this bundle is to be able to easily reimport it into our various projects.
In some projets, we want to extend this entity to add some specific fields (phone, address, ...), but that's not always the case.
Here is the code we had set up:
UserBundle > User class:
<?php
namespace MyCompany\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\MappedSuperclass()
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
...
User entity inherited:
<?php
namespace App\Entity;
use MyCompany\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity
* #UniqueEntity(fields={"email"})
*/
class User extends BaseUser
{
/**
* #ORM\Column(type="string", length=50)
*/
private $phone;
...
The inheritance works fine: the problem comes from projects for which the User entity of the bundle is sufficient for us.
=> The User class of the bundle is defined as Mapped superclass in order to be able to extend it but Doctrine can't create an associated table if there is no class which inherits from it...
We could systematically create an empty User class in src/ which inherits from the User class of the bundle, but that doesn't seem super clean to me...
I went on this post but that doesn't seem to work: Doctrine Inheritance replacement
Could anyone help us on this problem? I imagine that a solution must exist...
Thank you in advance!
The idea below does not work.
As #Cerad already pointed out, the best approach probably really is to define the concrete User in each app. Thats also what FOSUserBundle does.
I'd go with the following approach: Declare the mapped superclass abstract.
/**
* #ORM\MappedSuperclass()
*/
abstract class AbstractBaseUser implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
...
And implement a concrete empty child class User inside your bundle.
/**
* #ORM\Entity
*/
class User extends AbstractBaseUser
{
}
That way each app can either use the User of your library or inherit from it.

Symfony doctrine lazy load properties

I have an entity that stores large files as blobs to the DB.
I would now like to get Symfony to never ever load these blobs unless I specifically request them via the appropriate getter.
In essence I want the same idea as lazy-loading relationships but for a string property.
What I have tried so far is to put all my other properties that hold the file meta data into a trait and then apply that trait to two entities.
namespace App\Entity\Traits;
use Doctrine\ORM\Mapping as ORM;
trait DocumentMetaData
{
/**
* #var int|null
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime|null
*
* #ORM\Column(type="datetime")
*/
private $date_uploaded;
}
One entity has nothing to it but the trait...
namespace App\Entity;
use App\Entity\Traits\DocumentMetaData;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="documents")
* #ORM\Entity()
*/
class Document
{
use DocumentMetaData;
}
...the other has the added blob property:
namespace App\Entity;
use App\Entity\Traits\DocumentMetaData;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="documents")
* #ORM\Entity()
*/
class DocumentFile
{
use DocumentMetaData;
/**
* #var string|null
*
* #ORM\Column(type="blob")
*/
private $blob;
}
Now, if I don't want the blob to be loaded, for example for a listing of files, I simply use the entity that doesn't have the blob.
This approach sort of works but causes issues as I need to point both entities at the same table (see the class level ORM annotations).
Specifically, it makes doctrine freak out when running migrations:
The table with name 'myapp.documents' already exists.
That makes perfect sense and really I'm hoping that someone can point me to a nicer solution.
How can I tell doctrine not to load the blob unless its explicitly asked for?
So as per the comments on my question - the way to do this so that migrations do not break is to leverage doctrine's ability to lazy load relationships between tables.
Basically I had to go and create a new entity that only holds my giant blobs and then establish a one to one relationship between the original entity and the blob entity.
I then set that relationship to load EXTRA_LAZY and as a result I can now control when precisely the blobs of giant data should be loaded.
I don't think this is ideal in terms of normalising the DB design but it works a lot better than anything else so happy with that.

Symfony Doctrine ORM not a valid entity or mapped super class

I'm just making a new Entity as usual, but something goes wrong and console report this error and I couldn't generate the entity setter/getter:
[Doctrine\ORM\Mapping\MappingException]
Class "AppBundle\Entity\Admin_Actions" is not a valid entity or mapped super class.
Here is my Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="admin_actions")
*/
class Admin_Actions
{
/**
* #ORM\Column(name="id",type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="uid",type="string",length=100)
*/
private $uid;
/**
* #ORM\Column(name="type",type="integer")
*/
private $type;
/**
* #ORM\Column(name="linedate",type="datetime")
*/
private $linedate;
}
If I do doctrine:mapping:info:
[Exception]
You do not have any mapped Doctrine ORM entities according to the current configuration. If you have
entities or mapping files you should check your mapping configuration for errors.
I've just waste an hour trying to investigate the problem and I've already tried to rewrite it from new but I'm missing something. What's wrong with this?
May be datetime field has same name as function/implementation in doctrine, I have got same mistake by naming a table "condition" which may be condition function in MySql query

Doctrine ORM in ZF2 giving "The target-entity Application\\Entity\\UserCmsPermission cannot be found in 'Application\\Entity\\User#cmsPermissions'."

I have an existing ZF2 project to which I have added entities before, and I have just added a new entity by copying an existing one and changing the details as necessary. This UserCmsPermission entity links to the User entity via the User entity's cmsPermissions property.
I have redeployed the database using the following commands:
doctrine-module orm:schema-tool:drop --force
doctrine-module orm:schema-tool:create
doctrine-module data-fixture:import
This executes successfully with no errors at all. However, when I access my application I receive the following error:
The target-entity Application\\Entity\\UserCmsPermission cannot be found in
'Application\\Entity\\User#cmsPermissions'.
The relevant code from each entity is as follows:
module/Application/src/Application/Entity/User.php
<?php
/**
* User model
*
*
*/
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Tilt\Entity\Base\User as TiltUser;
/**
* #ORM\Entity
*/
class User extends TiltUser
{
// … etc …
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="UserChallenge", mappedBy="user", cascade={"all"})
*/
protected $challenges;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="UserCmsPermission", mappedBy="user", cascade={"all"})
*/
protected $cmsPermissions;
// … etc …
}
module/Application/src/Application/Entity/UserCmsPermission.php
<?php
/**
* User CMS Permission model
*
*
*/
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Tilt\Exception\InvalidArgumentException;
use Tilt\Entity\Base\Entity as BaseEntity;
/**
* #ORM\Entity
*/
class UserCmsPermission extends BaseEntity
{
// … etc …
/**
* #var User
*
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* #ORM\ManyToOne(targetEntity="User", inversedBy="cmsPermissions", cascade={"all"})
*/
protected $user;
// … etc …
}
As far as I can tell, the code is correct, and I have also removed data/DoctrineORMModule/ in case the entity metadata was being cached, but this hasn't fixed the problem, and neither has restarting PHP5-FPM in case something was being cached there, so I've now run out of ideas.
Anyone got a clue as to what could be causing this to happen?
Finally figured out what is causing this. Doctrine throws this error if you are using a class map to load classes rather than the standard ZF2 autoloader and you've forgotten to update your class map, which was what I'd not done.
Simply running this in the project folder fixed it:
php vendor/zendframework/zendframework/bin/classmap_generator.php
Et voila.

Symfony 2 + Doctrine 2 + inheritance

I'm searching for a solution for the following problem with a database inheritance using Doctrine 2 built in Symfony 2 framework. This is what I want to do...
I want to create two tables (UredniHodiny, KonzultacniHodiny) with the same interface as the abstract class Hodiny. This is how I'm trying to do it
<?php
// src/CvutPWT/ImportBundle/Entity/Hodiny.php
namespace CvutPWT\ImportBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\MappedSuperclass
*/
abstract class Hodiny
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Osoba")
*/
protected $osoba;
/**
* #ORM\ManyToOne(targetEntity="Mistnost")
*/
protected $mistnost;
/**
* #ORM\Column(type="datetime")
*/
protected $zacatek;
/**
* #ORM\Column(type="datetime")
*/
protected $konec;
}
<?php
// src/CvutPWT/ImportBundle/Entity/KonzultacniHodiny.php
namespace CvutPWT\ImportBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="konzultacnihodiny")
*/
class KonzultacniHodiny extends Hodiny
{
}
<?php
// src/CvutPWT/ImportBundle/Entity/UredniHodiny.php
namespace CvutPWT\ImportBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="urednihodiny")
*/
class UredniHodiny extends Hodiny
{
}
Now when I run php app/console doctrine:generate:entities CvutPWTImportBundle Symfony generates all variables (more precisely columns) from class Hodiny as private variables to both child classes. Now when I'm trying to create those tables with app/console doctrine:schema:update --force I'm getting errors that $id must be protected or weaker. When I change this protection manually I am able to create tables but there is only one column (id). But this is not what I was hoping for. Can somebody give me any advice what I'm doing wrong?
This is not table inheritance. Mapped super classes are just mapping inheritance.
The tables corresponding to your final entities will not be relied together in any way.
If you want real table inheritance (single table or joined table), use this: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/inheritance-mapping.html#single-table-inheritance
If you still want to use mapped super classes, then you will have to put the #ORM\Id definition in both final classes. You can not put ids in mapped super classes.

Categories