Controller does not read the method from the Repository - symfony

Good afternoon,
I have this issue where the Admin Controller is not reading the method findBynom from the UserRepository even everything is included here is my code:
here is the UserRepository:
<?php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Persistence\ManagerRegistry;
/**
* #method User|null find($id, $lockMode = null, $lockVersion = null)
* #method User|null findOneBy(array $criteria, array $orderBy = null)
* #method User[] findAll()
* #method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
/**
* #param $type
* #return int|mixed|string
*/
public function findBynom($type)
{
return $this->createQueryBuilder('p')
->Where('p.fullname LIKE :type')
->setParameter('type','%'.$type.'%')
->getQuery()
->getResult()
;
}
public function findByMail($type)
{
return $this->createQueryBuilder('p')
->Where('p.email LIKE :type')
->setParameter('type','%'.$type.'%')
->getQuery()
->getResult()
;
}
// /**
// * #return User[] Returns an array of User objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('u')
->andWhere('u.exampleField = :val')
->setParameter('val', $value)
->orderBy('u.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
public function findOneBySomeField($value): ?User
{
return $this->createQueryBuilder('u')
->andWhere('u.activation_token = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
}
and here is the AdminController:
<?php
namespace App\Controller;
use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use GuzzleHttp\Psr7\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
/**
* #Route("/admin", name="admin_")
*/
class AdminController extends AbstractController
{
/**
* Liste les utilisateur du side
* #Route("/", name="users", methods={"GET"})
*/
public function index(UserRepository $users){
return $this->render("admin/index.html.twig",[
'users'=> $users->findAll()
]);
}
/**
* #Route("/new", name="app_admin_new", methods={"GET", "POST"})
*/
public function new(Request $request, UserRepository $userRepository): Response
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$file = $form->get('Photo')->getData();
$Filename = md5(uniqid()).'.'.$file->guessExtension();
$file->move(
$this->getParameter('images'),
$Filename
);
$user->setPhoto($Filename);
$userRepository->add($user);
return $this->redirectToRoute('app_admin_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('admin/new.html.twig', [
'user' => $user,
'form' => $form->createView(),
]);
}
/**
* #Route("/{id}", name="app_admin_show", methods={"GET"})
*/
public function show(User $user): Response
{
return $this->render('admin/show.html.twig', [
'user' => $user,
]);
}
/**
* #Route("/{id}/edit", name="app_admin_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, User $user, UserRepository $userRepository): Response
{
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$userRepository->add($user);
return $this->redirectToRoute('app_admin_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('admin/edit.html.twig', [
'user' => $user,
'form' => $form->createView(),
]);
}
/**
* #Route("/{id}", name="app_admin_delete", methods={"POST"})
*/
public function delete(Request $request, User $user, UserRepository $userRepository): Response
{
if ($this->isCsrfTokenValid('delete'.$user->getId(), $request->request->get('_token'))) {
$userRepository->remove($user);
}
return $this->redirectToRoute('app_admin_index', [], Response::HTTP_SEE_OTHER);
}
/**
* #Route("/{id}/ban", name="admin_ban", methods={"GET", "POST"})
*/
public function ban(Request $request, User $user, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('ban'.$user->getId(), $request->request->get('_token'))) {
$user->setIsBanned(true);
$entityManager->flush();
}
return $this->redirectToRoute('admin_index', [], Response::HTTP_SEE_OTHER);
}
/**
* #Route("/{id}/unban", name="admin_unban", methods={"GET", "POST"})
*/
public function unban(Request $request, User $user, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('unban'.$user->getId(), $request->request->get('_token'))) {
$user->setIsBanned(false);
$entityManager->flush();
}
return $this->redirectToRoute('admin_index', [], Response::HTTP_SEE_OTHER);
}
/**
* #Route("/searchuser", name="utilsearchuser")
*/
public function searchPlan($searchString): JsonResponse
{
$serializer = new Serializer([new ObjectNormalizer()]);
$repository = $this->getDoctrine()->getRepository(User::class);
$users = $repository->findBynom($searchString);
$data=$serializer->normalize($users);
return new JsonResponse($data);
}
}
thanks for your help!
adzdafzferfzfaefzrfzrgd a aefzk ff ae ae ak,er ear ae rea rak aer !

Most likely you didn't specify UserRepository in annotations to your entity. Just declare the repositoryClass parameter in your entity
/**
* #ORM\Entity(repositoryClass=UserRepository::class)
*/
class User
Then you can get an instance of your repository:
$users = $this->getDoctrine()->getRepository(User::class)->findBynom($searchString);
Or you can specify the UserRepository in an attribute of your method, after which the Dependency Injection Component will include it
/**
* #Route("/searchuser", name="utilsearchuser")
*/
public function searchPlan($searchString, UserRepository $userRepository): JsonResponse
{
$serializer = new Serializer([new ObjectNormalizer()]);
$users = $userRepository->findBynom($searchString);
$data=$serializer->normalize($users);
return new JsonResponse($data);
}

Related

Symfony 4.2 App\Entity\Shopcart object not found by the #ParamConverter annotation

Im working on Symfony 4.2. I get this error
App\Entity\Shopcart object not found by the #ParamConverter annotation.
when I try to delete or edit an item on shopcard.I tried many solution but failed.I need your suggestions.
Here is my ShopcartController
<?php
namespace App\Controller;
use App\Entity\Shopcart;
use App\Form\ShopcartType;
use App\Repository\ProductRepository;
use App\Repository\ShopcartRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/shopcart")
*/
class ShopcartController extends AbstractController
{
/**
* #Route("/", name="shopcart_index", methods={"GET"})
*/
public function index(ShopcartRepository $shopcartRepository, ProductRepository $productRepository): Response
{
$slider=$productRepository->findBy([], ['name'=>'ASC'], 3); //slider doesn't exist hatası için ekledim
return $this->render('shopcart/index.html.twig', [
'shopcarts' => $shopcartRepository->getAllShops(),
'slider' => $slider, //slider doesn't exist hatası için ekledim
]);
}
/**
* #Route("/new", name="shopcart_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$shopcart = new Shopcart();
$form = $this->createForm(ShopcartType::class, $shopcart);
$form->handleRequest($request);
echo $submittedToken=$request->request->get('token');
if($this->isCsrfTokenValid('add-item', $submittedToken)) { //alınan tokenla uyuşuyorsa göre sepete ekliyor
if ($form->isSubmitted()) {
$entityManager = $this->getDoctrine()->getManager();
$user=$this->getUser();
$shopcart->setQuantity($request->request->get('quantity'));
$shopcart->setUserid($user->getid());
$entityManager->persist($shopcart);
$entityManager->flush();
return $this->redirectToRoute('shopcart_index');
}
}
return $this->render('shopcart/new.html.twig', [
'shopcart' => $shopcart,
'form' => $form->createView(),
]);
}
/**
* #Route("/{id}", name="shopcart_show", methods={"GET"})
*/
public function show(Shopcart $shopcart): Response
{
return $this->render('shopcart/show.html.twig', [
'shopcart' => $shopcart,
]);
}
/**
* #Route("/{id}/edit", name="shopcart_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Shopcart $shopcart): Response
{
$form = $this->createForm(ShopcartType::class, $shopcart);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('shopcart_edit',['id'=>$shopcart->getId()]);
}
return $this->render('shopcart/edit.html.twig', [
'shopcart' => $shopcart,
'form' => $form->createView(),
]);
}
/**
* #Route("/{id}", name="shopcart_delete", methods={"DELETE"})
*/
public function delete(Request $request, Shopcart $shopcart): Response
{
//methodu post ile değiştirip dene
if ($this->isCsrfTokenValid('delete'.$shopcart->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($shopcart);
$entityManager->flush();
}
return $this->redirectToRoute('shopcart_index');
}
/**
* #Route("/{id}/del", name="shopcart_del", methods={"DELETE"})
*/
public function del(Request $request, Shopcart $shopcart): Response
{
$em=$this->getDoctrine()->getManager();
$em->remove($shopcart);
$em->flush();
return $this->redirectToRoute('shopcart_index');
}
}
And here is ShopcartRepository.I use only getAllShops method.
<?php
namespace App\Repository;
use App\Entity\Shopcart;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use phpDocumentor\Reflection\Types\Integer;
/**
* #method Shopcart|null find($id, $lockMode = null, $lockVersion = null)
* #method Shopcart|null findOneBy(array $criteria, array $orderBy = null)
* #method Shopcart[] findAll()
* #method Shopcart[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ShopcartRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Shopcart::class);
}
// /**
// * #return Shopcart[] Returns an array of Shopcart objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('s')
->andWhere('s.exampleField = :val')
->setParameter('val', $value)
->orderBy('s.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?Shopcart
{
return $this->createQueryBuilder('s')
->andWhere('s.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
//LET JOIN WITH SQL
public function getAllShops():array
{
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT p.name, p.price, s.*, u.id FROM shopcart s, product p, user u
WHERE s.productid = p.id and s.userid=u.id
';
$stmt=$conn->prepare($sql);
$stmt->execute();
return $stmt->fetchAll();
}
public function getUserShopCartTotal($userid): float
{
$em=$this->getEntityManager();
$query= $em->createQuery('
SELECT sum(p.price *s .quantity) as total
FROM App\Entity\Shopcart s, App\Entity\Product p
WHERE s.productid = p.id and s.userid=:userid
')
->setParameter('userid',$userid);
$result=$query->getResult();
if($result[0]['total']!=null){
return $result[0]["total"];
} else {
return 0;
}
}
public function getUserShopCartCount($userid): Integer
{
$em=$this->getEntityManager();
$query= $em->createQuery('
SELECT count(s.id) as shopcount
FROM App\Entity\Shopcart s
WHERE s.userid=:userid
')
->setParameter('userid',$userid);
$result=$query->getResult();
if($result[0]['shopcount']!=null){
return $result[0]["shopcount"];
} else {
return 0;
}
}
public function getUserShopCart($userid): array
{
$em=$this->getEntityManager();
$query= $em->createQuery('
SELECT p.name, p.price, s.quantity,s.productid, s.userid, (p.price * s.quantity) as total
FROM App\Entity\Shopcart s, App\Entity\Product p
WHERE s.productid = p.id and s.userid=:userid
')
->setParameter('userid',$userid);
return $query->getResult();
}
}
I think the problem is that you have two delete functions. The del function is a copy of the delete function. If you remove 'del' function your problem will be solved. The 'del' function override the route oh other functions.

How can I filter on entities owned by current User

I'm very new to Symfony.
As a User I only want to see the entities I've created.
A User may login and create games but I only want to see the game entities I've created.
It's a ManyToMany relation for User and Games, where User is the owning side.
Example: the game "Game for user Joop1" can only be viewed by user
Joop1. The game with title "Game for Joop2" may only be viewed by
Joop2.
If Joop1 is logged as the current user, how can I only show the games he has created with DQL/querybuilder?
I use FOSUserBundle.
Update: I've changed the relation to:
User->Game: many-to-many.
Question: what is the dql/querybuilder script for this sql statement:
SELECT * FROM game,users_games WHERE users_games.user_id = 1
This is my current querybuilder script based on Manuel DUVERNON answer:
$em = $this->getDoctrine()->getManager();
$qb = $em->getRepository( Game::class )->createQueryBuilder( 'game_t' );
$qb->join( 'users_games.user_id', 'ug' )
->where( 'ug.user_id = :userId' )
->setParameter( 'userId', 1);
return $qb->getQuery()->getResult();
But this is not working because I get the following error:
[Semantical Error] line 0, col 70 near '.user_id ug WHERE': Error:
Identification Variable users_games used in join path expression but
was not defined before.
GameController
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Game;
use AppBundle\Entity\PlayLog;
use AppBundle\Entity\User;
use AppBundle\Form\GameType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\HttpFoundation\Request;
/**
* Game controller.
*
* #Route("game")
*/
class GameController extends Controller
{
/**
* Lists all game entities.
*
* #Route("/", name="game_index")
* #Method("GET")
*/
public function indexAction(Request $request)
{
//get user_id
//
$usr = $this->getUser();
$id = $usr->getId();
//
// $em = $this->getDoctrine()->getManager();
//// $dql="SELECT g FROM AppBundle\Entity\Game g Join g.users u WHERE u.id := user_id";
// $dql = "SELECT game FROM AppBundle:Game game ";
// $query = $em->createQuery($dql);
// $query->setParameter('user_id', $id);
// $current_games = $query->getResult();
// $paginator = $this->get('knp_paginator');
// $result = $paginator->paginate(
//
// $request->query->getInt('page', 1),
// $request->query->getInt('limit', 25)
// );
// dump(get_class($paginator));
// $em = $this->getDoctrine()->getManager();
//
// $current_games = $em->getRepository('AppBundle:Game')->findAll();
// $em = $this->getDoctrine()->getManager();
//
// $current_games = $em->getRepository('AppBundle:Game')->findAllOrdered($id);
//
$em = $this->getDoctrine()->getManager();
$qb = $em->getRepository( Game::class )->createQueryBuilder( 'game_t' );
$qb->join( 'users_games.user_id', 'ug' )
->where( 'ug.user_id = :userId' )
->setParameter( 'userId', $id);
return $qb->getQuery()->getResult();
return $this->render('game/index.html.twig', array(
'games' => $current_games,
'max_limit_error' => 25
));
}
/**
* Creates a new game entity.
*
* #Route("/new", name="game_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$game = new Game();
$form = $this->createForm('AppBundle\Form\GameType', $game);
$form->handleRequest($request);
$game->setUser($this->getUser());
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($game);
$em->flush($game);
return $this->redirectToRoute('game_show', array('id' => $game->getId()));
}
return $this->render('game/new.html.twig', array(
'game' => $game,
'form' => $form->createView(),
));
}
/**
* Finds and displays a game entity.
*
* #Route("/{id}", name="game_show")
* #Method("GET")
*/
public function showAction(Game $game)
{
$deleteForm = $this->createDeleteForm($game);
return $this->render('game/show.html.twig', array(
'game' => $game,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing game entity.
*
* #Route("/{id}/edit", name="game_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Game $game)
{
$deleteForm = $this->createDeleteForm($game);
$editForm = $this->createForm('AppBundle\Form\GameType', $game);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('game_show', array('id' => $game->getId()));
}
return $this->render('game/edit.html.twig', array(
'game' => $game,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing game entity.
*
* #Route("/{id}/log", name="game_log")
* #Method({"GET", "POST"})
*/
public function addLogAction(Request $request, Game $game)
{
$playlog = new PlayLog();
$form = $this->createForm(GameType::class, $game);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
//Save playLog
$em = $this->getDoctrine()->getManager();
$em->persist($playlog);
$em->flush();
}
// Render / return view incl. formulier.
return $this->render('game/log.html.twig', array(
'game' => $game,
'form' => $form->createView(),
));
}
/**
* Deletes a game entity.
*
* #Route("/{id}", name="game_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, Game $game)
{
$form = $this->createDeleteForm($game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($game);
$em->flush($game);
}
return $this->redirectToRoute('game_index');
}
/**
* Creates a form to delete a game entity.
*
* #param Game $game The game entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(Game $game)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('game_delete', array('id' => $game->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
Game Entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Game
*
* #ORM\Table(name="game")
* #ORM\Entity(repositoryClass="AppBundle\Repository\GameRepository")
*/
class Game
{
/**
* #ORM\OneToMany(targetEntity="PlayLog", mappedBy="game")
* #ORM\OrderBy({"date" = "DESC"})
*
*/
private $playlogs;
public function __construct()
{
$this->playlogs = new ArrayCollection();
}
/**
* #ORM\ManyToOne(targetEntity="Type", inversedBy="games")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id")
*/
private $type;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="games")
*/
private $user;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #Assert\NotBlank()
* #Assert\Length(
* min = "3",
* max = "100"
* )
* #ORM\Column(name="name", type="string", length=255, unique=true)
*/
private $name;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getUser()
{
return $this->user;
}
/**
* #param mixed $user
*/
public function setUser($user)
{
$this->user = $user;
}
/**
* Set name
*
* #param string $name
*
* #return Game
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #return mixed
*/
public function getType()
{
return $this->type;
}
/**
* #param mixed $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* #return mixed
*/
public function getPlaylogs()
{
return $this->playlogs;
}
/**
* #param mixed $playlogs
*/
public function setPlaylogs($playlogs)
{
$this->playlogs = $playlogs;
}
public function addPlayLog(PlayLog $playlog)
{
$this->playlog->add($playlog);
$playlog->setPlayLogs($this);
}
}
You can just get the current logged user, then request your dql query using that user id .
Take a look :
$usr= $this->getUser();
$id=$usr->getId();
$em=$this->getDoctrine()->getManager();
$dql="SELECT * games FROM Game WHERE Game.user_id := user_id";
$query = $em->createQuery($dql);
$query->setParameter('user_id',$id);
$current_games = $query->getResult();

Symfony Howto create a entity and add it to another?

Hi and thank you for taking the time reading this.
English is not my first language so I hope you'll excuse me for any errors.
Currently I'm doing a project to get familiar with Symfony 3.
This is what I'm trying to do:
I have a oneToMany relation, Game to PlayLog.
The relation is established and I can view a list of dates in my games.
I want to create a new PlayLog and be associated with the Game so I can access all my related PlayLogs via Game.
A view is shown with the id of the game (log.html.twig)
My question:
How do I create a new PlayLog with a form and date formField(dateType), and add it to an existing game?
Update: with the current code I now get this error:
An exception occurred while executing 'INSERT INTO play_log (date,
game_id) VALUES (?, ?)' with params ["2017-03-04", null]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'game_id'
cannot be null
This is my code:
--- entity/Game.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Game
*
* #ORM\Table(name="game")
* #ORM\Entity(repositoryClass="AppBundle\Repository\GameRepository")
*/
class Game
{
/**
* #ORM\OneToMany(targetEntity="PlayLog", mappedBy="game")
*/
private $playlogs;
public function __construct()
{
$this->playlogs = new ArrayCollection();
}
/**
* #ORM\ManyToOne(targetEntity="Type", inversedBy="games")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id")
*/
private $type;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #Assert\NotBlank()
* #Assert\Length(
* min = "3",
* max = "100"
* )
* #ORM\Column(name="name", type="string", length=255, unique=true)
*/
private $name;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Game
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #return mixed
*/
public function getType()
{
return $this->type;
}
/**
* #ORM\Column (options={"default" = none})
* #param mixed $type
*/
public function setType($type)
{
$this->type = $type;
}
/**
* #return mixed
*/
public function getPlaylogs()
{
return $this->playlogs;
}
/**
* #param mixed $playlogs
*/
public function setPlaylogs($playlogs)
{
$this->playlogs = $playlogs;
}
public function addPlayLog(PlayLog $playlog)
{
$this->playlog->add($playlog);
$playlog->setPlayLogs($this);
}
}
--- entity/PlayLog.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* PlayLog
*
* #ORM\Table(name="play_log")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PlayLogRepository")
*/
class PlayLog
{
/**
* #ORM\ManyToOne(targetEntity="Game", inversedBy="playlogs")
* #ORM\JoinColumn(name="game_id", referencedColumnName="id")
*/
private $game;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="date")
*/
private $date;
/**
* #var int
*
* #ORM\Column(name="game_id", type="integer")
*/
private $gameId;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set date
*
* #param \DateTime $date
*
* #return PlayLog
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set gameId
*
* #param integer $gameId
*
* #return PlayLog
*/
public function setGameId($gameId)
{
$this->gameId = $gameId;
return $this;
}
/**
* Get gameId
*
* #return int
*/
public function getGameId()
{
return $this->gameId;
}
public function addGame(Game $game)
{
$this->games->add($game);
$game->setType($this);
}
public function removeGame(Game $game)
{
$this->games->removeElement($game);
}
}
--- GameController.php
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Game;
use AppBundle\Entity\PlayLog;
use AppBundle\Entity\Type;
use AppBundle\Form\GameType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\HttpFoundation\Request;
/**
* Game controller.
*
* #Route("game")
*/
class GameController extends Controller
{
/**
* Lists all game entities.
*
* #Route("/", name="game_index")
* #Method("GET")
*/
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
// $games = $em->getRepository('AppBundle:Game')->findAll();
$dql = "SELECT game FROM AppBundle:Game game JOIN game.type type ORDER BY game.name";
$query = $em->createQuery($dql);
/*
* #var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$result = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
$request->query->getInt('limit', 25)
);
// dump(get_class($paginator));
return $this->render('game/index.html.twig', array(
'games' => $result,
'max_limit_error' => 25
));
}
/**
* Creates a new game entity.
*
* #Route("/new", name="game_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$game = new Game();
$form = $this->createForm('AppBundle\Form\GameType', $game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($game);
$em->flush($game);
return $this->redirectToRoute('game_show', array('id' => $game->getId()));
}
return $this->render('game/new.html.twig', array(
'game' => $game,
'form' => $form->createView(),
));
}
/**
* Finds and displays a game entity.
*
* #Route("/{id}", name="game_show")
* #Method("GET")
*/
public function showAction(Game $game)
{
$deleteForm = $this->createDeleteForm($game);
return $this->render('game/show.html.twig', array(
'game' => $game,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing game entity.
*
* #Route("/{id}/edit", name="game_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Game $game)
{
$deleteForm = $this->createDeleteForm($game);
$editForm = $this->createForm('AppBundle\Form\GameType', $game);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('game_show', array('id' => $game->getId()));
}
return $this->render('game/edit.html.twig', array(
'game' => $game,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing game entity.
*
* #Route("/{id}/log", name="game_log")
* #Method({"GET", "POST"})
*/
public function addLogAction(Request $request, Game $game)
{
$playlog = new PlayLog();
$form = $this->createForm(GameType::class, $game);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
//Save playLog
$em = $this->getDoctrine()->getManager();
$em->persist($playlog);
$em->flush();
}
// Render / return view incl. formulier.
return $this->render('game/log.html.twig', array(
'game' => $game,
'form' => $form->createView(),
));
}
/**
* Deletes a game entity.
*
* #Route("/{id}", name="game_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, Game $game)
{
$form = $this->createDeleteForm($game);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($game);
$em->flush($game);
}
return $this->redirectToRoute('game_index');
}
/**
* Creates a form to delete a game entity.
*
* #param Game $game The game entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(Game $game)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('game_delete', array('id' => $game->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
--- PlayLogController.php
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\PlayLog;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Component\HttpFoundation\Request;
/**
* Playlog controller.
*
* #Route("playlog")
*/
class PlayLogController extends Controller
{
/**
* Lists all playLog entities.
*
* #Route("/", name="playlog_index")
* #Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$playLogs = $em->getRepository('AppBundle:PlayLog')->findAll();
return $this->render('playlog/index.html.twig', array(
'playLogs' => $playLogs,
));
}
/**
* Creates a new playLog entity.
*
* #Route("/{gameId}/new", name="playlog_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request, $gameId)
{
$playlog = new PlayLog();
$form = $this->createForm('AppBundle\Form\PlayLogType', $playlog);
$form->handleRequest($request);
$playlog->setGameId($gameId);
echo $playlog->getGameId()."!";
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($playlog);
$em->flush();
// return $this->redirectToRoute('game_show', array('id' => $gameId));
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playlog,
'form' => $form->createView(),
));
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playLog,
'form' => $form->createView(),
));
}
/**
* Finds and displays a playLog entity.
*
* #Route("/{id}", name="playlog_show")
* #Method("GET")
*/
public function showAction(PlayLog $playLog)
{
$deleteForm = $this->createDeleteForm($playLog);
return $this->render('playlog/show.html.twig', array(
'playLog' => $playLog,
'delete_form' => $deleteForm->createView(),
));
}
/**
* Displays a form to edit an existing playLog entity.
*
* #Route("/{id}/edit", name="playlog_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, PlayLog $playLog)
{
$deleteForm = $this->createDeleteForm($playLog);
$editForm = $this->createForm('AppBundle\Form\PlayLogType', $playLog);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('playlog_edit', array('id' => $playLog->getId()));
}
return $this->render('playlog/edit.html.twig', array(
'playLog' => $playLog,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Deletes a playLog entity.
*
* #Route("/{id}", name="playlog_delete")
* #Method("DELETE")
*/
public function deleteAction(Request $request, PlayLog $playLog)
{
$form = $this->createDeleteForm($playLog);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($playLog);
$em->flush();
}
return $this->redirectToRoute('playlog_index');
}
/**
* Creates a form to delete a playLog entity.
*
* #param PlayLog $playLog The playLog entity
*
* #return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(PlayLog $playLog)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('playlog_delete', array('id' => $playLog->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
--- game/log.html.twig
{% extends 'base.html.twig' %}
{% block content %}
Adding log for {{ game.name }}
{{ form_widget(form.playlogs) }}
<input type="submit" value="Create" class="btn btn-default pull-left" />
{% endblock content %}
--- PlayLogType.php
<?php
namespace AppBundle\Form;
use AppBundle\Entity\PlayLog;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PlayLogType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('date');
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => PlayLog::class
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_playlog';
}
}
--- GameType.php
<?php
namespace AppBundle\Form;
use AppBundle\Entity\PlayLog;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class GameType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, [
'attr' => [
'class' => 'form-control',
],
]);
$builder
->add('type', EntityType::class, [
'class' => 'AppBundle:Type',
'choice_label' => function ($type) {
return $type->getName();
},
'multiple' => false,
'expanded' => false,
'attr' => [
'class' => 'form-control',
],
]);
$builder->add('playlogs', CollectionType::class, array(
'entry_type' => PlayLogType::class,
'label' => false
));
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Game'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_game';
}
}
Not sure if this is the answer you looking for..
You can tweek your newAction and his Route annotation in the Playlog controller a bit so that you add the gameId in the route
/**
* Creates a new playLog entity.
*
* #Route("/{gameId}/new", name="playlog_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request, $gameId)
{
$em = $this->getDoctrine()->getManager();
$game = $em->getRepository('AppBundle:Game')->find($gameId);
if(null === $game) {
throw $this->createNotFoundException('The game with id ' . $gameId . ' does not exist.');
}
$playLog = new Playlog();
$playLog->SetGame($game);
$form = $this->createForm('AppBundle\Form\PlayLogType', $playLog);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($playLog);
$em->flush($playLog);
return $this->redirectToRoute('playlog_show', array('id' => $playLog->getId()));
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playLog,
'form' => $form->createView(),
));
}
I've figured it out, I tried to persist with just an ID ($gameId) but it expected the entire Game object. (1) So I first had to get the actual repository object with the ID and after that I can persist this object:
public function newAction(Request $request, $gameId)
{
$playlog = new PlayLog();
$em = $this->getDoctrine()->getManager();
// (1) Get Game object with given gameId:
$game = $em ->getRepository(Game::class)->find($gameId);
//Set the Game object
$playlog->setGame($game);
$form = $this->createForm('AppBundle\Form\PlayLogType', $playlog);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/* #var $playLog PlayLog */
$playlog = $form->getData();
$em->persist($playlog);
$em->flush();
}
return $this->render('playlog/new.html.twig', array(
'playLog' => $playlog,
'form' => $form->createView(),
));
}

Symfony 2.3 / Doctrine2 personal translations not working in Sonata Admin with TranslatedFieldType.php

I am currently working on a symfony2.3 project with doctrine2 trying to implement personal translations management in the Sonata backend.
Translations are based on the doctrine2 translatable behaviour model: https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/translatable.md
and more precisely Personal Translations.
The admin form is using the symfony2.3 version of TranslatedFieldType.php.
My entity class is as follows:
<?php
namespace Hr\OnlineBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #Gedmo\TranslationEntity(class="Hr\OnlineBundle\Entity\CategoryTranslation")
*/
class Category
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue
*/
private $id;
/**
* #Gedmo\Translatable
* #ORM\Column(length=64)
*/
private $title;
/**
* #Gedmo\Translatable
* #ORM\Column(type="text", nullable=true)
*/
private $description;
/**
* #ORM\OneToMany(
* targetEntity="CategoryTranslation",
* mappedBy="object",
* cascade={"persist", "remove"}
* )
*/
private $translations;
public function __construct()
{
$this->translations = new ArrayCollection();
}
public function getTranslations()
{
return $this->translations;
}
public function addTranslation(CategoryTranslation $t)
{
if (!$this->translations->contains($t)) {
$this->translations[] = $t;
$t->setObject($this);
}
}
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function setDescription($description)
{
$this->description = $description;
}
public function getDescription()
{
return $this->description;
}
public function __toString()
{
return $this->getTitle();
}
}
The related Personal Translation class is this:
<?php
namespace Hr\OnlineBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation;
/**
* #ORM\Entity
* #ORM\Table(name="category_translations",
* uniqueConstraints={#ORM\UniqueConstraint(name="lookup_unique_idx", columns={
* "locale", "object_id", "field"
* })}
* )
*/
class CategoryTranslation extends AbstractPersonalTranslation
{
/**
* Convinient constructor
*
* #param string $locale
* #param string $field
* #param string $value
*/
public function __construct($locale, $field, $value)
{
$this->setLocale($locale);
$this->setField($field);
$this->setContent($value);
}
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="translations")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $object;
}
The admin form class is this:
<?php
namespace Hr\OnlineBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Hr\OnlineBundle\Form\Type\TranslatedFieldType;
class CategoryAdmin extends Admin
{
// Fields to be shown on create/edit forms
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('General')
->add('title', 'translatable_field', array(
'field' => 'title',
'personal_translation' => 'Hr\OnlineBundle\Entity\CategoryTranslation',
'property_path' => 'translations',
))
->end();
}
// Fields to be shown on filter forms
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title')
;
}
// Fields to be shown on lists
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('title')
;
}
}
The admin form is using the following form type class:
<?php
namespace Hr\OnlineBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Hr\OnlineBundle\Form\EventListener\addTranslatedFieldSubscriber;
class TranslatedFieldType extends AbstractType
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
if(! class_exists($options['personal_translation']))
{
Throw new \InvalidArgumentException(sprintf("Unable to find personal translation class: '%s'", $options['personal_translation']));
}
if(! $options['field'])
{
Throw new \InvalidArgumentException("You should provide a field to translate");
}
$subscriber = new addTranslatedFieldSubscriber($builder->getFormFactory(), $this->container, $options);
$builder->addEventSubscriber($subscriber);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'remove_empty' => true,
'csrf_protection'=> false,
'field' => false,
'personal_translation' => false,
'locales'=>array('en', 'fr', 'de'),
'required_locale'=>array('en'),
'widget'=>'text',
'entity_manager_removal'=>true,
));
}
public function getName()
{
return 'translatable_field';
}
}
and the corresponding Event Listener:
<?php
namespace Hr\OnlineBundle\Form\EventListener;
use Symfony\Component\Form\Event\DataEvent;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\FormError;
class AddTranslatedFieldSubscriber implements EventSubscriberInterface
{
private $factory;
private $options;
private $container;
public function __construct(FormFactoryInterface $factory, ContainerInterface $container, Array $options)
{
$this->factory = $factory;
$this->options = $options;
$this->container = $container;
}
public static function getSubscribedEvents()
{
// Tells the dispatcher that we want to listen on the form.pre_set_data
// , form.post_data and form.bind_norm_data event
return array(
FormEvents::PRE_SET_DATA => 'preSetData',
FormEvents::POST_BIND => 'postBind',
FormEvents::BIND => 'bindNormData'
);
}
private function bindTranslations($data)
{
//Small helper function to extract all Personal Translation
//from the Entity for the field we are interested in
//and combines it with the fields
$collection = array();
$availableTranslations = array();
foreach($data as $Translation)
{
if(strtolower($Translation->getField()) == strtolower($this->options['field']))
{
$availableTranslations[ strtolower($Translation->getLocale()) ] = $Translation;
}
}
foreach($this->getFieldNames() as $locale => $fieldName)
{
if(isset($availableTranslations[ strtolower($locale) ]))
{
$Translation = $availableTranslations[ strtolower($locale) ];
}
else
{
$Translation = $this->createPersonalTranslation($locale, $this->options['field'], NULL);
}
$collection[] = array(
'locale' => $locale,
'fieldName' => $fieldName,
'translation' => $Translation,
);
}
return $collection;
}
private function getFieldNames()
{
//helper function to generate all field names in format:
// '<locale>' => '<field>|<locale>'
$collection = array();
foreach($this->options['locales'] as $locale)
{
$collection[ $locale ] = $this->options['field'] .":". $locale;
}
return $collection;
}
private function createPersonalTranslation($locale, $field, $content)
{
//creates a new Personal Translation
$className = $this->options['personal_translation'];
return new $className($locale, $field, $content);
}
public function bindNormData(FormEvent $event)
{
//Validates the submitted form
$data = $event->getData();
$form = $event->getForm();
$validator = $this->container->get('validator');
foreach($this->getFieldNames() as $locale => $fieldName)
{
$content = $form->get($fieldName)->getData();
if(
NULL === $content &&
in_array($locale, $this->options['required_locale']))
{
$form->addError(new FormError(sprintf("Field '%s' for locale '%s' cannot be blank", $this->options['field'], $locale)));
}
else
{
$Translation = $this->createPersonalTranslation($locale, $fieldName, $content);
$errors = $validator->validate($Translation, array(sprintf("%s:%s", $this->options['field'], $locale)));
if(count($errors) > 0)
{
foreach($errors as $error)
{
$form->addError(new FormError($error->getMessage()));
}
}
}
}
}
public function postBind(FormEvent $event)
{
//if the form passed the validattion then set the corresponding Personal Translations
$form = $event->getForm();
$data = $form->getData();
$entity = $form->getParent()->getData();
foreach($this->bindTranslations($data) as $binded)
{
$content = $form->get($binded['fieldName'])->getData();
$Translation = $binded['translation'];
// set the submitted content
$Translation->setContent($content);
//test if its new
if($Translation->getId())
{
//Delete the Personal Translation if its empty
if(
NULL === $content &&
$this->options['remove_empty']
)
{
$data->removeElement($Translation);
if($this->options['entity_manager_removal'])
{
$this->container->get('doctrine.orm.entity_manager')->remove($Translation);
}
}
}
elseif(NULL !== $content)
{
//add it to entity
$entity->addTranslation($Translation);
if(! $data->contains($Translation))
{
$data->add($Translation);
}
}
}
}
public function preSetData(FormEvent $event)
{
//Builds the custom 'form' based on the provided locales
$data = $event->getData();
$form = $event->getForm();
// During form creation setData() is called with null as an argument
// by the FormBuilder constructor. We're only concerned with when
// setData is called with an actual Entity object in it (whether new,
// or fetched with Doctrine). This if statement let's us skip right
// over the null condition.
if (null === $data)
{
return;
}
foreach($this->bindTranslations($data) as $binded)
{
$form->add($this->factory->createNamed(
$binded['fieldName'],
$this->options['widget'],
$binded['translation']->getContent(),
array(
'label' => $binded['locale'],
'required' => in_array($binded['locale'], $this->options['required_locale']),
'auto_initialize' => false,
)
));
}
}
}
So, the form shows the three fields for the three specified locales, which is fine, but when submitting the form the following error occurs:
FatalErrorException: Error: Call to a member function getField() on a non-object in C:\wamp\www\hronline\src\Hr\OnlineBundle\Form\EventListener\addTranslatedFieldSubscriber.php line 47
in C:\wamp\www\hronline\src\Hr\OnlineBundle\Form\EventListener\addTranslatedFieldSubscriber.php line 47
at ErrorHandler->handleFatal() in C:\wamp\www\hronline\vendor\symfony\symfony\src\Symfony\Component\Debug\ErrorHandler.php line 0
at AddTranslatedFieldSubscriber->bindTranslations() in C:\wamp\www\hronline\src\Hr\OnlineBundle\Form\EventListener\addTranslatedFieldSubscriber.php line 136
at AddTranslatedFieldSubscriber->postBind() in C:\wamp\www\hronline\app\cache\dev\classes.php line 1667
at ??call_user_func() in C:\wamp\www\hronline\app\cache\dev\classes.php line 1667
at EventDispatcher->doDispatch() in C:\wamp\www\hronline\app\cache\dev\classes.php line 1600
at EventDispatcher->dispatch() in C:\wamp\www\hronline\vendor\symfony\symfony\src\Symfony\Component\EventDispatcher\ImmutableEventDispatcher.php line 42
at ImmutableEventDispatcher->dispatch() in C:\wamp\www\hronline\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php line 631
at Form->submit() in C:\wamp\www\hronline\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php line 552
at Form->submit() in C:\wamp\www\hronline\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php line 645
at Form->bind() in C:\wamp\www\hronline\vendor\sonata-project\admin-bundle\Sonata\AdminBundle\Controller\CRUDController.php line 498
at CRUDController->createAction() in C:\wamp\www\hronline\app\bootstrap.php.cache line 2844
at ??call_user_func_array() in C:\wamp\www\hronline\app\bootstrap.php.cache line 2844
at HttpKernel->handleRaw() in C:\wamp\www\hronline\app\bootstrap.php.cache line 2818
at HttpKernel->handle() in C:\wamp\www\hronline\app\bootstrap.php.cache line 2947
at ContainerAwareHttpKernel->handle() in C:\wamp\www\hronline\app\bootstrap.php.cache line 2249
at Kernel->handle() in C:\wamp\www\hronline\web\app_dev.php line 28
at ??{main}() in C:\wamp\www\hronline\web\app_dev.php line 0
It appears that on this line of the event listener AddTranslatedFieldSubscriber:
if(strtolower($Translation->getField()) == strtolower($this->options['field']))
the $Translation variable comes as a string (e.g. string 'Lorem' (length=5)) instead of an object.
For some reason the form data is converted to an array of strings instead of an array of objects of type CategoryTranslation.
What could be the reason for this? Thanks!
Do yourself a favour and don't use the Gedmo Translatable behaviour. It is very buggy, slow and has a lot of weird edge cases. I recommend using the KNP translatable behaviour which is quite good (requires PHP 5.4) or the Prezent Translatable which is similar but can work on PHP 5.3. Disclaimer: I wrote that last one. It's beta but works fine. I just added the documentation for it.
You can use the a2lix bundle to integrate it all in Sonata Admin.

Symfony2 EntityManager#persist() expects parameter 1 to be an entity object, array given

I am new to Symfony2 and can't to figure out why I'm getting this error. Perhaps there is something wrong with my Entities? So I need some help with it.
An error:
EntityManager#persist() expects parameter 1 to be an entity object, array given.
500 Internal Server Error - ORMInvalidArgumentException
I have the following code:
User.php:
<?php
namespace Acme\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*/
class User
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $username;
/**
* #var string
*/
private $password;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
}
UserRegType.php
<?php
namespace Acme\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Length;
class UserRegType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('username', 'text', array(
'constraints'=>new Length(array('min' => 3))
));
$builder->add('password', 'repeated', array(
'first_name' => 'password',
'second_name' => 'confirm',
'type' => 'password',
'constraints' => new Length(array('min' => 5, 'max' => 8))
));
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Acme\MainBundle\Entity\User');
}
public function getName() {
return 'user';
}
}
?>
UserController.php:
<?php
namespace Acme\MainBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Acme\MainBundle\Form\Type\UserRegType;
class UserController extends Controller
{
public function registerAction()
{
$form = $this->createForm(new UserRegType());
return $this->render(
'AcmeMainBundle:User:register.html.twig',
array('form' => $form->createView())
);
}
public function createUserAction()
{
$em = $this->getDoctrine()->getEntityManager();
$form = $this->createForm(new UserRegType());
$form->bind($this->getRequest());
$username = $form["username"]->getData();
if ($form->isValid()) {
$reg = $form->getData();
$em->persist($reg);
$em->flush();
$session = $this->get('session');
$session->set('username', $username);
return $this->redirect($this->generateUrl('home'));
}
}
public function loginAction()
{
}
public function logoutAction()
{
}
}

Resources