I've a custom User Class which extends from the FOSUser Model:
use FOS\UserBundle\Model\User as BaseUser;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
/**
* #ExclusionPolicy("all")
*/
class User extends BaseUser
My problem is: The Abstract properties from the FOSUser Model are exposed, but the properties in the custom extended class not.
To expose the properties I've two yaml files:
1) MyBundle/../Resources/config/serializer/fos/Model.User.yml
2) SecurityBundle/../Resource/config/serializer/Entity.User.yml
My custom User class has a property $name. Which should be exposed by my .yaml file:
ErwineEberhard\SecurityBundle\Entity\User:
exclusion_policy: none
properties:
name:
expose: true
groups: [list, details]
Doctrine compels me to add a $id in the exteded class. The $id is only exposed when I add * #ExclusionPolicy("all") in my custom User class.
When I add #Expose to name, no differences.
How to accomplish this?
Related
I got a Cours (it's french for lesson) entity, and this entity have a "prof" attribute that is a manytoone relation with a Prof (teacher in french) entity. This Prof entity in itself extend an Eleve (student) entity (a prof is an eleve with more attributes and methods).
I created a prof and a cours with fixtures, just to test my app. Then, in a CourseController, I tried to send my cours and prof informations to a view. To do so, I load my cours, then I try to access my prof through my cours.
When I try to show the cours informations, everything is fine. But when I try to access the prof, nothing works anymore. I got an error that tells me that id column doesn't exists, and when I try to dump the prof, it tells me isInitialized is false, and every attributes is null.
I found other stackoverflow (or other forums) topics with similar problems where people explain that symfony do lazy loading, and doesn't load the related entity this way it gets faster. But all solutions proposed doesn't work or aren't good choices in my case.
One of the solution seems to be to set fetching to eager in my manytoone relation. But the problem is that prof itself has many manytoone or manytomany or other relations, and each of this entities has to allow access to entities related (so fetching eager too), and so, each time I'll want to get an entity, I'll load the entire database. And I just want to load what I need, which will change in each controller and each methods.
Another solution proposed is to call some methods of my related object (prof in this situation), to tell doctrine we need to access it, this way doctrine load it. But this result with the exception again (telling id column is not found).
in CoursController :
/**
* #Route("/cours/{slug}", name="presentationCours")
*/
public function presentationCours(Cours $cours)
{
$prof = $cours->getProf();
// $prof->getLogin(); THIS result with exception
dump($prof); // THIS shows all null values
die();
return $this->render('cours/presentation.html.twig', [
"cours" => $cours,
"prof" => $prof
]);
}
note : if you wonder how I get the $cours var without telling symfony where to find it, it can find it just with the slug in the route. It's new in symfony 4 (not sure it's new but I think). I'm sure it works, I did it many times and a dump($cours) perfectly works.
the twig file :
{% extends 'base.html.twig' %}
{% block title %}{{ cours.nom }}{% endblock %}
{% block body %}
<p>
{{ cours.nom }}
</p>
<p>
{{ cours.description }}
</p>
<p>
{{ prof.login }} {# THIS result with exception #}
</p>
{% endblock %}
part of the Eleve entity (the entity which is parent of prof : prof extends eleve)
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\EleveRepository")
*/
class Eleve
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $login;
...
}
part of the prof entity :
<?php
namespace App\Entity;
use App\Entity\Eleve;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\ProfRepository")
*/
class Prof extends Eleve
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="text")
*/
private $introduction;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Cours", mappedBy="prof")
*/
private $cours;
part of the cours entity :
<?php
namespace App\Entity;
use Cocur\Slugify\Slugify;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="App\Repository\CoursRepository")
* #ORM\HasLifecycleCallbacks
*/
class Cours
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Prof", inversedBy="cours")
* #ORM\JoinColumn(nullable=false)
*/
private $prof;
in the database with phpmyadmin :
part of the cours table :
part of the prof table :
the exception (without the dump) :
the dump(prof) result :
Thank you for your time.
EDIT
Problem solved ! As jeroen told, the problem was about inheritance.
Here is what I did to manage to solve it :
<?php
namespace App\Entity;
use App\Entity\Prof;
use App\Entity\Eleve;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\InheritanceType;
use Doctrine\ORM\Mapping\DiscriminatorMap;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\DiscriminatorColumn;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="App\Repository\EleveRepository")
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"eleve" = "Eleve", "prof" = "Prof"})
*/
class Eleve
{
I added the lines inheritancetype, discriminatorcolumn, and discriminatormap. This, because I chosed the class table inheritance, but you could chose the mapped superclass solution, or the single table inheritance solution.
For those who, like me, would have made a migration before changing the classes, I had a problem when I added the class table inheritance. Doctrine refused to migrate after that, an exception told me there was a foreign key problem. I'm not sure this is the good way, but I deleted my migration files in symfony (src > migrations), I droped my whole database in phpmyadmin, then in symfony, using CLI (command line interface, ctrl + รน on windows and ctrl + ` on mac (on the left of enter on the keyboard), I did :
bin/console doctrine:database:create
bin/console make:migration
bin/console doctrine:migrations:migrate
and the problem is now solved. But again, I'm really not sure this is the good way, just saying it worked for me.
i have a bundle CompanyBundle with:
a class Product with this inside
/**
* #ORM\ManyToMany(targetEntity="CompanyBundle\Entity\ProductImage", inversedBy="listProduct")
**/
private $listProductImage;
and a class ProductImage having this:
/**
* #ORM\ManyToMany(targetEntity="CompanyBundle\Entity\Product", mappedBy="listProductImage")
*/
private $listProduct;
but i also extend my class Product from another ClinetBundle like that:
/**
* #ORM\Entity(repositoryClass="ClientBundle\Entity\Repository\ClientProductRepository")
*/
class ClientProduct extends Product
{
/**
* #ORM\ManyToMany(targetEntity="ClientBundle\Entity\ClientProductImage", inversedBy="listProduct")
**/
private $listProductImage;
}
but when in my controller i build a ClientProduct object class and that i try to access to the ClientProductImage from it, it is giving the class from the CompanyBundle, not the ClientBundle. so, how can i do to get the ProductImage from the ClientBundle?
it is like if my /** #ORM\ManyToMany(targetEntity="ClientBundle\Entity\ClientProductImage", inversedBy="listProduct") **/ was doing nothing :(
thanks for your help!
I finally found the solution.
I don't keep the useless relation defined in ClientProduct.
so i deleted the ManyToMany(targetEntity="ClientBundle\Entity\ClientProductImage"
and after that, i opened my app/config.yml and add the resolve_target_entities:
doctrine:
...
orm:
...
resolve_target_entities:
CompanyBundle\Entity\ProductImage: ClientBundle\Entity\ClientProductImage
all work fine, and i don't need to change the CompanyBundle :)
Suppose I have two bundles: a FormBundle and an AccommodationBundle. These bundles I would like to Open Source independently from each other.
FormBundle i.e. has a class FormEvent
class FormEvent {
/**
* #ORM\ManyToMany(
* targetEntity="Visit",
* mappedBy="formEvents",
* cascade={"persist","remove"})
**/
protected $visits;
}
Now as you may understand, the Visit-entity is part of the AccommodationBundle.
How do I make the property visits part of the FormEvent class, only if the AccommodationBundle is registered? Do I need to extend the class FormEvent in the AccommodationBundle?
I've generated a bundle (#ShopfishApiBundle) using generate:bundle like I have many times. It has automatically registered the bundle in theAppKernel and it added the loading of the bundle's routing.yml to the app/Resource/config/routing.yml as well. This is within a Sylius installation running Symfony 2.3
The #ShopfishApiBundle/Resource/config/routing.yml looks like this:
shopfish_api:
resource: "#ShopfishApiBundle/Controller/ProductController.php"
type: annotation
The product controller looks like this:
namespace Shopfish\Bundle\ApiBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
/**
* #Route("/api")
*/
class ProductController extends Controller
{
/**
* #Route("/products")
* #Method({"GET"})
*
* #Rest\View
*/
public function allAction()
{
$products = array();
return array('products' => $products);
}
}
Loading any page instantly yields the below exception:
FileLoaderLoadException: Cannot load resource "#ShopfishApiBundle/Controller/". Make sure the "ShopfishApiBundle" bundle is correctly registered and loaded in the application kernel class.
In another Symfony2 (version 2.4) application I've made a similar bundle and this worked without error, I'm thinking something in Sylius messes this up. Do you know where I might solve this issue?
NOTE: I did a little test to see if a direct-no-annotations code snippet worked, and that seems to work. Though I want to use the FOS Rest bundle, using Annotations for Routing.
sf_api_controller:
pattern: /no-annotation-test
defaults:
_controller: ShopfishApiBundle:Product:all
I hadn't registered the essential SensionFrameworkExtraBundle in my AppKernel.php:
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle()
Thanks, #pazi!
I have a custom password validator that someone gave me in an answer to another question. The validator looks like this:
<?php
namespace Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\ConstraintValidator,
Symfony\Component\Validator\Constraint,
Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface,
Symfony\Component\Security\Core\SecurityContextInterface,
JMS\DiExtraBundle\Annotation\Validator,
JMS\DiExtraBundle\Annotation\InjectParams,
JMS\DiExtraBundle\Annotation\Inject;
/**
* #Validator("user.validator.current_password")
*/
class CurrentPasswordValidator extends ConstraintValidator
{
// ...
}
The place where I'm trying to use this validator is in my User entity, which looks like this:
<?php
namespace VNN\PressboxBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\JoinTable as JoinTable;
use Doctrine\ORM\Mapping\JoinColumn as JoinColumn;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\MaxLength;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\CurrentPassword;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* VNN\PressboxBundle\Entity\User
*
* #ORM\Table(name="user")
* #ORM\Entity
*/
class User implements UserInterface, \Serializable
{
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('current_password', new CurrentPassword());
}
}
(I've omitted some code, of course, for clarity.)
The problem I'm having is that my validator class is not being recognized:
Fatal error: Class 'Symfony\Component\Validator\Constraints\CurrentPassword' not found in /home/jason/pressbox/src/VNN/PressboxBundle/Entity/User.php on line 438
Why could this be happening?
You have to write the constraint yourself. It doesn't come with Symfony2.