Symfony 2 many to one cannot null - symfony

I have :
An exception occurred while executing 'INSERT INTO image (image_name, artiste_id) VALUES (?, ?)' with params ["537bd9df69db9.png", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'artiste_id' cannot be null
I have a many-to-one relationship with the companies 'image' and 'artist'. I do not really see where the problem is.
My entity Image :
<?php
namespace Acme\ArtisteBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Acme\ArtisteBundle\Entity\Artiste;
/**
* Acme\ArtisteBundle\Entity\Image
*
* #ORM\Table(name="image")
* #ORM\Entity(repositoryClass="Acme\ArtisteBundle\Entity\ImageRepository")
* #ORM\HasLifecycleCallbacks
* #Vich\Uploadable
*/
class Image
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #Assert\File(
* maxSize="1M",
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
* )
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName")
*
* #var File $image
*/
public $image;
/**
* #var string $imageName
* #ORM\Column(type="string", length=255, name="image_name", type="integer", nullable=false)
*/
protected $imageName;
/**
* #ORM\ManyToOne(targetEntity="Acme\ArtisteBundle\Entity\Artiste", inversedBy="image", cascade={"remove"})
* #ORM\JoinColumn(name="artiste_id", referencedColumnName="id", nullable=false)
*/
private $artiste;
/**
* Set artiste
*
* #param \Acme\ArtisteBundle\Entity\Artiste $artiste
*/
public function setArtiste(\Acme\ArtisteBundle\Entity\Artiste $artiste)
{
$this->artiste = $artiste;
}
/**
* Get artiste
*
* #return \Acme\ArtisteBundle\Entity\Artiste
*/
public function getArtiste()
{
return $this->artiste;
}
/**
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*/
public function setImage(File $image)
{
$this->image = $image;
}
/**
* Get Image
* #return File
*/
public function getImage()
{
return $this->image;
}
/**
* #param string $imageName
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
}
/**
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
}
and my entity Artiste
<?php
namespace Acme\ArtisteBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Acme\ArtisteBundle\Entity\Image;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Artiste
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\ArtisteBundle\Entity\ArtisteRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Artiste extends BaseUser
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="valideAdmin", type="boolean", nullable=true)
*/
private $valideAdmin = '0';
/**
* #ORM\OneToMany(targetEntity="Acme\ArtisteBundle\Entity\Image", mappedBy="artiste", cascade={"persist", "remove"})
*/
protected $image;
public function __construct()
{
trigger_error(sprintf('%s is deprecated. Extend FOS\UserBundle\Model\User directly.', __CLASS__), E_USER_DEPRECATED);
parent::__construct();
$this->image = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get image
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getImage() {
return $this->image;
}
/**
* Set image
*
* #param \Doctrine\Common\Collections\Collection $image
*/
public function setImage(\Doctrine\Common\Collections\Collection $image)
{
$this->image = $image;
}
/**
* Add image
*
* #param \Acme\ArtisteBundle\Entity\Image $image
*/
public function addImage(\Acme\ArtisteBundle\Entity\Image $image)
{
$this->image[] = $image;
}
/**
* Remove image
*
* #param \Acme\ArtisteBundle\Entity\Artiste $image
*/
public function removeImage(\Acme\ArtisteBundle\Entity\Artiste $image)
{
$this->image->removeElement($image);
}
}
and my register action of FOS
namespace Unikness\ArtisteBundle\Controller;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use FOS\UserBundle\Model\UserInterface;
use Acme\ArtisteBundle\Entity\Image;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
class RegistrationController extends ContainerAware
{
public function registerAction(Request $request)
{
/** #var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->container->get('fos_user.registration.form.factory');
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->container->get('fos_user.user_manager');
/** #var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->container->get('event_dispatcher');
$user = $userManager->createUser();
$user->setEnabled(true);
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $formFactory->createForm();
$form->setData($user);
$image = new Image();
if ('POST' === $request->getMethod()) {
$form->bind($request);
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
$userManager->updateUser($user);
$image->setArtiste($user);
$em = $this->container->get('doctrine')->getEntityManager();
$em->persist($image);
$em->flush();
if (null === $response = $event->getResponse()) {
$url = $this->container->get('router')->generate('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
'form' => $form->createView(),
));
}
I have persisted but I always null. Any help would be appreciated :)

Try adding "persist" option in ManyToOne annotation
/**
* #ORM\ManyToOne(targetEntity="Acme\ArtisteBundle\Entity\Artiste", inversedBy="image", cascade={"remove","persist"})
* #ORM\JoinColumn(name="artiste_id", referencedColumnName="id", nullable=false)
*/
private $artiste;

To ensure bidirectional relation there is a trick :
in your class Artiste, modify your setter setImage like this :
public function setImage(\Doctrine\Common\Collections\Collection $image)
{
foreach ($image as $img) {
$img->setArtiste($this);
}
$this->image = $image;
}
Further more, just for a better read of your code, I recommend to rename "image" field in your class Artiste to "images" as this field is a collection of entities Image.
I also read in this post doctrine2: in a one-to-many bidirectional relationship, how to save from the inverse side? that you can do like this (choose on of these two solutions, this second solution is interesting if you create Images, and then attach Artiste to the Image created = "save from the inverse side") :
in your class Image modify the setter setArtiste like this :
public function setArtiste($artiste)
{
$this->artiste = $artiste;
$artiste->addImage($this);
}

This should work
public function addImage(\Acme\ArtisteBundle\Entity\Image $image)
{
if(!$this->image->contains($image)){
$this->image[] = $image;
$image->setArtiste($this);
}
}

Related

Symfony 3.4: Issues on saving an Object ArrayCollection OneToMany

I need your help on my problem for saving my data in table.
I use fosUserBundle and have different user types (Admin, Pro, Client) that are classes extending a base User entity.
I also have a Language entity linked to the User with a one-to-many association.
To subscribe, a userClient needs to check by checkbox the language(s) that he speaks.
The form page is ok, it displays the UserClient form (+ the parent User form) with the list of languages as checkboxes.
The problem is the data saved in table.
I have the same values in the language column:
O:43:"Doctrine\Common\Collections\ArrayCollection":1:{s:53:"Doctrine\Common\Collections\ArrayCollectionelements";a:2:{i:0;O:32:"LanguagesBundle\Entity\Languages":10:{s:36:"LanguagesBundle\Entity\Languagesid";i:2;s:38:"LanguagesBundle\Entity\Languagesname";s:7:"English";s:44:"LanguagesBundle\Entity\Languagesshort_slug";s:2:"en";s:43:"LanguagesBundle\Entity\Languageslong_slug";s:5:"en_EN";s:43:"LanguagesBundle\Entity\LanguagesisDefault";b:0;s:43:"LanguagesBundle\Entity\LanguagesupdatedAt";O:8:"DateTime":3:{s:4:"date";s:26:"2018-04-20 22:46:48.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";}s:43:"LanguagesBundle\Entity\LanguagesimageFile";N;s:39:"LanguagesBundle\Entity\Languagesimage";s:39:"Flag_of_United_Kingdom_-_Circle-512.png";s:43:"LanguagesBundle\Entity\LanguagesimageSize";i:37621;s:44:"LanguagesBundle\Entity\LanguagesuserClient";N;}i:1;O:32:"LanguagesBundle\Entity\Languages":10:{s:36:"LanguagesBundle\Entity\Languagesid";i:1;s:38:"LanguagesBundle\Entity\Languagesname";s:9:"Français";s:44:"LanguagesBundle\Entity\Languagesshort_slug";s:2:"fr";s:43:"LanguagesBundle\Entity\Languageslong_slug";s:5:"fr_FR";s:43:"LanguagesBundle\Entity\LanguagesisDefault";b:1;s:43:"LanguagesBundle\Entity\LanguagesupdatedAt";O:8:"DateTime":3:{s:4:"date";s:26:"2018-04-20 22:45:50.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:12:"Europe/Paris";}s:43:"LanguagesBundle\Entity\LanguagesimageFile";N;s:39:"LanguagesBundle\Entity\Languagesimage";s:31:"Flag_of_France_-_Circle-512.png";s:43:"LanguagesBundle\Entity\LanguagesimageSize";i:23352;s:44:"LanguagesBundle\Entity\LanguagesuserClient";N;}}}
Here's my code:
User.php
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use UserBundle\Entity\UserAdmin;
use UserBundle\Entity\UserProfessional;
use UserBundle\Entity\UserClient;
use UserBundle\Entity\Adress;
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"client" = "UserClient", "professional"="UserProfessional", "admin"="UserAdmin"})
*/
abstract class User extends BaseUser {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*/
protected $firstname;
//[...] getters and setters
Entity: UserClient.php
<?php
// src/UserBundle/Entity/UserGuest.php
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class UserClient extends User {
/**
* #ORM\Column(type="array")
* #ORM\OneToMany(targetEntity="LanguagesBundle\Entity\Languages", mappedBy="userClient")
*/
private $languages;
public function __construct() {
parent::__construct();
$this->languages = new ArrayCollection();
}
/**
* Set languages
*
* #param array $languages
*
* #return UserClient
*/
public function setLanguages($languages)
{
$this->languages = $languages;
}
/**
* Get languages
*
* #return array
*/
public function getLanguages()
{
return $this->languages;
}
/**
* Add language
*
* #param \LanguagesBundle\Entity\Languages $language
*
* #return UserClient
*/
public function addLanguage(LanguagesBundle\Entity\Languages $language)
{
$this->languages[] = $language;
return $this;
}
/**
* Remove language
*
* #param \LanguagesBundle\Entity\Languages $language
*/
public function removeLanguage(\LanguagesBundle\Entity\Languages $language)
{
$this->languages->removeElement($language);
}
}
Entity Languages.php
<?php
namespace LanguagesBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
*
* #Vich\Uploadable
*/
class Languages
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
* #Assert\NotBlank()
*/
private $name;
/**
* #ORM\Column(type="string", length=2, unique=true)
*/
private $short_slug;
/**
* #var string
*
* #ORM\Column(type="string", length=5, unique=true)
* #Assert\NotBlank()
*/
private $long_slug;
/**
* #var string
*
* #ORM\Column(type="boolean", nullable=true)
*/
private $isDefault;
/**
* #ORM\Column(type="datetime")
* #var \DateTime
*/
private $updatedAt;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Assert\File(
* maxSize="1M",
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
* )
* #Vich\UploadableField(mapping="language_images", fileNameProperty="image", size="imageSize")
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255, nullable = true)
* #var string
*/
private $image;
/**
* #ORM\Column(type="integer")
*
* #var integer
*/
private $imageSize;
/**
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\UserClient", inversedBy="languages")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $userClient;
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*/
public function setImageFile(?File $image = null): void
{
$this->imageFile = $image;
if (null !== $image) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
}
public function getImageFile()
{
return $this->imageFile;
}
/**
* Constructor
*/
public function __construct()
{
$this->updatedAt = new \DateTime();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Languages
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set shortSlug
*
* #param string $shortSlug
*
* #return Languages
*/
public function setShortSlug($shortSlug)
{
$this->short_slug = $shortSlug;
return $this;
}
/**
* Get shortSlug
*
* #return string
*/
public function getShortSlug()
{
return $this->short_slug;
}
/**
* Set longSlug
*
* #param string $longSlug
*
* #return Languages
*/
public function setLongSlug($longSlug)
{
$this->long_slug = $longSlug;
return $this;
}
/**
* Get longSlug
*
* #return string
*/
public function getLongSlug()
{
return $this->long_slug;
}
/**
* Set isDefault
*
* #param boolean $isDefault
*
* #return Languages
*/
public function setIsDefault($isDefault)
{
$this->isDefault = $isDefault;
return $this;
}
/**
* Get isDefault
*
* #return boolean
*/
public function getIsDefault()
{
return $this->isDefault;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return Languages
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set image
*
* #param string $image
*
* #return Languages
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Set imageSize
*
* #param integer $imageSize
*
* #return Languages
*/
public function setImageSize($imageSize)
{
$this->imageSize = $imageSize;
return $this;
}
/**
* Get imageSize
*
* #return integer
*/
public function getImageSize()
{
return $this->imageSize;
}
/**
* Set userClient
*
* #param \UserBundle\Entity\UserClient $userClient
*
* #return Languages
*/
public function setUserClient(\UserBundle\Entity\UserClient $userClient = null)
{
$this->userClient = $userClient;
return $this;
}
/**
* Get userClient
*
* #return \UserBundle\Entity\UserClient
*/
public function getUserClient()
{
return $this->userClient;
}
/**
* {#inheritdoc}
*/
public function __toString()
{
return $this->getName() ?: '-';
}
}
My FormType: RegistrationTypeClient.php
<?php
// src/UserBundle/Form/UserContactFormType.php
namespace UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use LanguagesBundle\Services\LanguagesService;
use LanguagesBundle\Entity\Languages ;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class RegistrationClientType extends AbstractType {
protected $service;
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
$builder
->add('languages', EntityType::class, [
'class' => 'LanguagesBundle:Languages',
'choice_label' => 'name',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.name', 'ASC');
},
'label' => 'Langues',
'expanded' => true,
'multiple' => true,
])
;
}
public function getParent() {
// on inclut le formulaire de base d'inscription utilisateur
return 'UserBundle\Form\RegistrationType';
}
public function getBlockPrefix() {
return 'app_user_registration_client';
}
// For Symfony 2.x
public function getName() {
return $this->getBlockPrefix();
}
public function configureOptions(OptionsResolver $resolver) {
$resolver
->setDefaults(array(
'data_class' => \UserBundle\Entity\UserClient::class,
))
//->setRequired('service_languages');
;
}
}
And my Controller:
public function registerClientAction(Request $request) {
/** #var $formFactory FactoryInterface */
//$formFactory = $this->get('fos_user.registration_pro.form.factory');
/** #var $userManager UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** #var $dispatcher EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = new UserClient();
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form = $this->createForm(RegistrationClientType::class, $user);
$form->setData($user);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
if (null !== $response = $event->getResponse()) {
return $response;
}
}
return $this->render('UserBundle\Registration\register_client.html.twig', array(
'form' => $form->createView(),
));
}
Here's a picture showing the data saved in the table
I need the languages to be stored in the database as an array for userClient.
Could you help me please.
Thank's for re-edit my question Philip-B-
Thank's for your reading also.
I have resolve my problem by adding a foreach to transform my object to array:
The code is in my controller:
if ($form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
foreach ($user->getLanguages() as $value) {
$langue[] = $value->getShortSlug();
}
$user->setLanguages($langue);
$userManager->updateUser($user);
if (null === $response = $event->getResponse()) {
$url = $this->generateUrl('fos_user_registration_confirmed');
$response = new RedirectResponse($url);
}
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));
return $response;
}

Update password with postPersist($object) method SonataAdminBundle

I need to update password with sonata admin int fos userbundle 'bcrypt' password.
This is my admin class,
<?php
namespace AdminBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
class UserAdmin extends Admin {
public function postPersist($object) {
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserBy(array('id'=>$object->id));
$user->setPlainPassword('test');
$userManager->updateUser($user);
}
This is my user entity,
<?php
// src/AppBundle/Entity/User.php
namespace AdminBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="telephone", type="text", length=30, nullable=false)
*/
private $telephone;
/**
* Set nonotification
*
* #param text $telephone
* #return User
*/
public function settelephone($telephone) {
$this->telephone = $telephone;
return $this;
}
/**
* Get telephone
*
* #return text
*/
public function gettelephone() {
return $this->telephone;
}
/**
* #var string
*
* #ORM\Column(name="name", type="text", length=60, nullable=false)
*/
private $name;
/**
* Set nonotification
*
* #param text $name
* #return User
*/
public function setname($name) {
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return text
*/
public function getname() {
return $this->name;
}
/**
* #var string
*
* #ORM\Column(name="surname", type="text", length=60, nullable=false)
*/
private $surname;
/**
* Set nonotification
*
* #param text $name
* #return User
*/
public function setsurname($surname) {
$this->surname = $surname;
return $this;
}
/**
* Get surname
*
* #return text
*/
public function getsurname() {
return $this->surname;
}
public function __construct() {
parent::__construct();
// your own logic
}
}
But I'm getting this error instead,
Attempted to call an undefined method named "get" of class
"AdminBundle\Admin\UserAdmin". Did you mean to call e.g.
"getActiveSubClass", "getActiveSubclassCode", "getBaseCodeRoute",
"getBaseControllerName", "getBaseRouteName", "getBaseRoutePattern",
"getBatchActions", "getBreadcrumbs", "getChild", "getChildren",
"getClass", "getClassnameLabel", "getCode", "getConfigurationPool",
"getCurrentChild", "getCurrentChildAdmin", "getDataSourceIterator",
"getDatagrid", "getDatagridBuilder", "getExportFields",
"getExportFormats", "getExtensions", "getFilterFieldDescription",
"getFilterFieldDescriptions", "getFilterParameters", "getFilterTheme",
"getForm", "getFormBuilder", "getFormContractor",
"getFormFieldDescription", "getFormFieldDescriptions",
"getFormGroups", "getFormTabs", "getFormTheme", "getIdParameter",
"getLabel", "getLabelTranslatorStrategy", "getList", "getListBuilder",
"getListFieldDescription", "getListFieldDescriptions",
"getManagerType", "getMaxPageLinks", "getMaxPerPage",
"getMenuFactory", "getModelManager", "getNewInstance",
"getNormalizedIdentifier", "getObject", "getObjectIdentifier",
"getObjectMetadata", "getParent", "getParentAssociationMapping",
"getParentFieldDescription", "getPerPageOptions",
"getPermissionsShow", "getPersistentParameter",
"getPersistentParameters", "getRequest", "getRoot", "getRootCode",
"getRouteBuilder", "getRouteGenerator", "getRouterIdParameter",
"getRoutes", "getSecurityHandler", "getSecurityInformation",
"getShow", "getShowBuilder", "getShowFieldDescription",
"getShowFieldDescriptions", "getShowGroups", "getShowTabs",
"getSideMenu", "getSubClasses", "getSubject", "getTemplate",
"getTemplates", "getTranslationDomain", "getTranslationLabel",
"getTranslator", "getUniqid", "getUrlsafeIdentifier" or
"getValidator"?
It would be great help someone can look into it.
You cannot access the container with $this->get('service.name') from a sonata admin class. You should use:
$container = $this->getConfigurationPool()->getContainer();
$userManager = $container->get('fos_user.user_manager');
Also, I don't know if your solution would work anyway. I would use something like this:
public function postPersist($object) {
$container = $this->getConfigurationPool()->getContainer();
$entityManager = $container->get('doctrine.orm.entity_manager');
$object->setPlainPassword('test');
$entityManager->persist($user);
$entityManager->flush();
}
And do yourself a favor and respect the naming conventions (getName instead of getname, etc)

How to search ManyToOne side by OneToMany

I have Four Entities:
Batch
BachGroup
BachGroupApplication
Application
Entity 1(Batch) has OneToMany Bidirectional relationship with Entity 2(BatchGroup).
Entity 2(BatchGroup) has OneToMany Bidirectional relationship with Entity 3(BachGroupApplication).
Entity 3(BachGroupApplication) has ManyToOne Bidirectional relationship with Entity 4(Application).
DETAIL ON ABOVE ENTITIES:
Each batch has it's groups which i'm storing in bachGroup entity with batch reference column in it, now each batchGroup can have multiple applications so i have created BatchGroupApplication entity which holds reference to batchGroup and Application.
TODO:
I want to be able to search applications by individual batch group which i'm not able to do i searched the web and stackoverflow but failed to get it working! i don't know if my mind has stopped somewhere! my entities are listed below please help:
Batch Entity
<?php
namespace ModelBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Batch
*
* #ORM\Table(name="batch")
* #ORM\Entity(repositoryClass="ModelBundle\Repository\BatchRepository")
*/
class Batch
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ..............
/**
* If a Batch is removed all it's associated Groups will be deleted as well..
*
* #ORM\OneToMany(targetEntity="BatchGroup", mappedBy="batch", cascade={"remove"})
**/
private $batchGroups;
public function __construct() {
$this->batchGroups = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
// ...............
/**
* Add batchGroups
*
* #param \ModelBundle\Entity\BatchGroup $batchGroups
* #return Batch
*/
public function addBatchGroup(\ModelBundle\Entity\BatchGroup $batchGroups)
{
$this->batchGroups[] = $batchGroups;
return $this;
}
/**
* Remove batchGroups
*
* #param \ModelBundle\Entity\BatchGroup $batchGroups
*/
public function removeBatchGroup(\ModelBundle\Entity\BatchGroup $batchGroups)
{
$this->batchGroups->removeElement($batchGroups);
}
/**
* Get batchGroups
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getBatchGroups()
{
return $this->batchGroups;
}
}
BatchGroup Entity
<?php
namespace ModelBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* BatchGroup
*
* #ORM\Table(name="batch_group")
* #ORM\Entity()
*/
class BatchGroup
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=128)
*/
private $title;
/**
* #ORM\ManyToOne(targetEntity="Batch", inversedBy="batchGroups")
* #ORM\JoinColumn(name="batch_id", referencedColumnName="id")
**/
private $batch;
/**
* #ORM\OneToMany(targetEntity="BatchGroupApplication", mappedBy="batchGroup", cascade={"remove"})
**/
private $batchGroupApplications;
public function __construct() {
$this->batchGroupApplications = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
// ............
/**
* Set batch
*
* #param \ModelBundle\Entity\Batch $batch
* #return BatchGroup
*/
public function setBatch(\ModelBundle\Entity\Batch $batch = null)
{
$this->batch = $batch;
return $this;
}
/**
* Get batch
*
* #return \ModelBundle\Entity\Batch
*/
public function getBatch()
{
return $this->batch;
}
/**
* Add batchGroupApplications
*
* #param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
* #return BatchGroup
*/
public function addBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
{
$this->batchGroupApplications[] = $batchGroupApplications;
return $this;
}
/**
* Remove batchGroupApplications
*
* #param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
*/
public function removeBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
{
$this->batchGroupApplications->removeElement($batchGroupApplications);
}
/**
* Get batchGroupApplications
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getBatchGroupApplications()
{
return $this->batchGroupApplications;
}
}
BatchGroupApplication Entity
<?php
namespace ModelBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* BatchGroupApplication
*
* Table generated through this entity class will hold all application and can be filtered through BatchGroup
*
* #ORM\Table(name="batch_group_application")
* #ORM\Entity()
*/
class BatchGroupApplication
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="BatchGroup", inversedBy="batchGroupApplications")
* #ORM\JoinColumn(name="batch_group_id", referencedColumnName="id")
**/
private $batchGroup;
/**
* #ORM\ManyToOne(targetEntity="Application", inversedBy="batchGroupApplications")
* #ORM\JoinColumn(name="application_id", referencedColumnName="id")
**/
private $application;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set batchGroup
*
* #param \ModelBundle\Entity\BatchGroup $batchGroup
* #return BatchGroupApplication
*/
public function setBatchGroup(\ModelBundle\Entity\BatchGroup $batchGroup = null)
{
$this->batchGroup = $batchGroup;
return $this;
}
/**
* Get batchGroup
*
* #return \ModelBundle\Entity\BatchGroup
*/
public function getBatchGroup()
{
return $this->batchGroup;
}
/**
* Set application
*
* #param \ModelBundle\Entity\Application $application
* #return BatchGroupApplication
*/
public function setApplication(\ModelBundle\Entity\Application $application = null)
{
$this->application = $application;
return $this;
}
/**
* Get application
*
* #return \ModelBundle\Entity\Application
*/
public function getApplication()
{
return $this->application;
}
}
Application Entity
<?php
namespace ModelBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Application
*
* #ORM\Table(name="application")
* #ORM\Entity(repositoryClass="ModelBundle\Repository\ApplicationRepository")
*/
class Application
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ............
/**
* #ORM\OneToMany(targetEntity="BatchGroupApplication", mappedBy="application", cascade={"remove"})
**/
private $batchGroupApplications;
public function __construct()
{
$this->batchGroupApplications = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
// ............
/**
* Add batchGroupApplications
*
* #param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
* #return Application
*/
public function addBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
{
$this->batchGroupApplications[] = $batchGroupApplications;
return $this;
}
/**
* Remove batchGroupApplications
*
* #param \ModelBundle\Entity\BatchGroupApplication $batchGroupApplications
*/
public function removeBatchGroupApplication(\ModelBundle\Entity\BatchGroupApplication $batchGroupApplications)
{
$this->batchGroupApplications->removeElement($batchGroupApplications);
}
/**
* Get batchGroupApplications
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getBatchGroupApplications()
{
return $this->batchGroupApplications;
}
}
ApplicationRepository
Search function in this repository is being called from controller and from data is being sent to it via parameter that is in key value pair format, because form may have more properties so i'm checking if user is searching through batchGroup as well if yes it should combine the result from there as well.
namespace ModelBundle\Repository;
use Doctrine\ORM\EntityRepository;
/**
* ApplicationRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class ApplicationRepository extends EntityRepository
{
/**
* Search Applications
*
* data: search form data in key => value fashion
*
*
*/
public function search($data)
{
$em = $this->getEntityManager();
$applicationRepository = $em->getRepository('ModelBundle:Application');
$qb = $applicationRepository->createQueryBuilder('a');
foreach ($data as $field => $value) {
if($field=="batchGroupApplications"){
$qb->andWhere(":value_$field MEMBER OF a.batchGroupApplications")->setParameter("value_$field", $value);
}else{
$qb->andWhere("a.$field = :value_$field")->setParameter("value_$field", $value);
}
}
$query = $qb->getQuery();
$result = $query->getResult();
return $result;
}
}
Controller
Here i'm creating a search form with batchGroupApplications dropdown, where user will choose any batch group and submit the form, once submitted user should be able to see all applications which are in that group but i'm getting nothing!
namespace SISBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use ModelBundle\Entity\Batch;
use SISBundle\Form\BatchType;
use ModelBundle\Entity\Application;
use DefaultBundle\Form\ApplicationType;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use SISBundle\Form\SearchApplicationType;
use ModelBundle\Entity\Group;
use ModelBundle\Entity\BatchGroup;
/**
* Admission controller.
*
* #Route("/admission")
*/
class AdmissionController extends Controller
{
// ..............
/**
* List Applications for selected Batch
*
* #Route("/{batch}/applications")
*
* #Method({"GET", "POST"})
* #Template()
*/
public function applicationsAction(Request $request, Batch $batch)
{
$em = $this->getDoctrine()->getManager();
if( $batch != null ){
$applications = $batch->getApplications();
/*
* Search Applications
*
*/
$searchForm = $this->createForm(SearchApplicationType::class, null, array(
'action' => $this->generateUrl('sis_admission_applications', array('batch'=>$batch->getId())),
'method' => 'POST',
'attr' => array(
'novalidate' => 'novalidate',
'id' => 'sis_application_search_form',
),
));
// Manually Populating groups dropdown based on their availability for current loaded batch
$searchForm->add('batchGroupApplications', ChoiceType::class, array(
'choices' => $batch->getBatchGroups(),
'choices_as_values' => true,
'multiple'=>false,
'choice_label'=>'title',
'placeholder'=>' - Select Group..',
)
);
$searchForm->handleRequest($request);
if ($searchForm->isSubmitted()) {
// data is an array with "firstname", "middlename", and "lastname" keys etc
$data = $searchForm->getData();
$applications = $em->getRepository('ModelBundle:Application')->search($data);
}
/*********************************** end: Search Applications ***************************************/
return array(
'batch' => $batch,
'applications' => $applications,
'searchForm' => $searchForm->createView(),
);
}
}
}
Again, please suggest how can i search applications through batchGroup in andWhere fashion as search form may have some more fields which are available in application entity, for other fields it's working fine but this search by BatchGroup is somewhat tricky may be because of complicated associations etc.
Looking forward to solution..

Erreur in Installation PUGXMultiUserBundle

I want to install PUGXMultiUserBundle. I followed the documentation of PUGXMultiUserBundle:https://github.com/PUGX/PUGXMultiUserBundle/blob/master/Resources/doc/index.md
I have downloaded the PUGXMultiUserBundle with success and I continued Creating my Entities. I created an entity User:
<?php
namespace Register\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="user")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="type", type="string")
* #ORM\DiscriminatorMap({"societe" = "Societe", "chercheur" = "Chercheur"})
*
*/
abstract class User extends BaseUser
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string $image
* #ORM\Column(name="image", type="string", length=255)
*/
protected $image;
public $file;
protected function getUploadDir()
{
return 'image';
}
protected function getUploadRootDir()
{
return __DIR__.'/../../../../web/'.$this->getUploadDir()."/".$this->getId()."/";
}
public function getWebPath()
{
return null === $this->image ? null : $this->getUploadDir().$this->getId()."/".'/'.$this->image;
}
public function getAbsolutePath()
{
return null === $this->image ? null : $this->getUploadRootDir().$this->getId()."/".'/'.$this->image;
}
public function getAbsolutePath1()
{
return null === $this->image ? null : $this->getUploadRootDir().$this->image;
}
/**
* #ORM\PrePersist
* #ORM\PreUpdate
*/
public function preUpload()
{
if (null !== $this->file) {
// do whatever you want to generate a unique name
$this->image = uniqid().'.'.$this->file->guessExtension();
}
}
/**
* #ORM\PostPersist
* #ORM\PostUpdate
*/
public function upload()
{
if (null === $this->file) {
return;
}
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->file->move($this->getUploadRootDir(), $this->image);
unset($this->file);
}
/**
* #ORM\PreRemove()
*/
public function storeFilenameForRemove()
{
$this->filenameForRemove = $this->getAbsolutePath1();
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
if ($this->filenameForRemove) {
unlink($this->filenameForRemove);
}
}
}
and the other Entity: societe:
<?php
namespace Register\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use PUGX\MultiUserBundle\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity
* #ORM\Table(name="societe")
* #UniqueEntity(fields = "username", targetClass = "Register\UserBundle\Entity\User", message="fos_user.username.already_used")
* #UniqueEntity(fields = "email", targetClass = "Register\UserBundle\Entity\User", message="fos_user.email.already_used")
*/
class Societe extends User
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string $adressemail
*/
protected $adressemail;
/**
* #var string $namesociete
*/
protected $namesociete;
}
an finally the last Entity chercheur:
<?php
namespace Register\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use PUGX\MultiUserBundle\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
* #ORM\Table(name="chercheur")
* #UniqueEntity(fields = "username", targetClass = "Register\UserBundle\Entity\User", message="fos_user.username.already_used")
* #UniqueEntity(fields = "email", targetClass = "Register\UserBundle\Entity\User", message="fos_user.email.already_used")
*/
class Chercheur extends User
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Assert\NotBlank
* #var string
*/
protected $region;
/**
* #Assert\NotBlank
* #var string
*/
protected $firstname;
}
The problem is when I want to generate my entities after : php app/console doctrine:generate:entities Register, a error message appeared in console:
[Doctrine\ORM\Mapping\MappingException]
Class "Register" is not a valid entity or mapped super class.
doctrine:generate:entities [--path="..."] [--no-backup] name
.
Can someone help me to fix this problem and Thank you.

FosUserBundle and doctrine request

When I execute this query
public function SearchByfournisseur($keyWord)
{
$qb = $this->createQueryBuilder('p')->distinct()->select('p');
$qb ->leftJoin('p.Fournisseur', 'f');
$qb ->where($qb->expr()->eq('f.username', $keyWord));
$query = $qb->getQuery();
$products = $query->getResult();
return $products;
}
I got this error:
[Semantical Error] line 0, col 110 near 'test': Error: 'test' is not defined.
But this one works perfectly:
public function SearchByfournisseur($keyWord)
{
$qb = $this->createQueryBuilder('p')->distinct()->select('p');
$qb ->leftJoin('p.Fournisseur', 'f');
$qb ->where($qb->expr()->eq('f.id', $keyWord));
$query = $qb->getQuery();
$products = $query->getResult();
return $products;
}
That means that I can't access to the user's attributes except his id.
Is there any away to solve this problem?
EDIT:
This is the concerned entities :
<?php
namespace Ecommerce\boutiqueBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use FS\SolrBundle\Doctrine\Annotation as Solr;
/**
* Ecommerce\boutiqueBundle\Entity\Produit
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Ecommerce\boutiqueBundle\Entity\ProduitRepository")
*/
class Produit
{
/**
* #var integer $id
*#Solr\Id
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Ecommerce\UserBundle\Entity\User",inversedBy="Produits")
*
* #ORM\JoinColumn(name="Fournisseur_id", referencedColumnName="id")
*/
private $Fournisseur;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set Fournisseur
*
* #param string $Fournisseur
*/
public function setFournisseur( $Fournisseur)
{
$this->Fournisseur = $Fournisseur;
}
/**
* Get Fournisseur
*
* #return string
*/
public function getFournisseur()
{
return $this->Fournisseur;
}
}
Fournisseur entity:
<?php
namespace Ecommerce\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="Ecommerce_user")
*/
class User extends BaseUser
{
public function __construct()
{
parent::__construct();
$this->Produits = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="Ecommerce\boutiqueBundle\Entity\Produit",
* mappedBy="Fournisseur")
*/
protected $Produits;
public function addProduit(\Ecommerce\boutiqueBundle\Entity\Produit $Produit)
{
$this->Produits[] = $Produit;
$Produit->setCategorie($this);
}
public function getProduits()
{
return $this->Produits;
}
}
You have to specify the join condition within the leftJoin() call.
public function SearchByfournisseur($keyWord)
{
$qb = $this->createQueryBuilder('p')->distinct()->select('p');
$qb ->leftJoin('p.Fournisseur', 'f', 'WITH', $qb->expr()->eq('f.username = ?', $keyWord));
$products = $query->getResult();
return $products;
}
I suggest you to read the Doctrine documentation chapter dealing about the QueryBuilder.

Resources