I'am trying to make a form for entity content with a OneToMany relation to URL. I want to display all the URL's in a radio input field.
so the form will look like this:
//an input field for content
url:
o url1
o url2
the user can choose one of the url's linked to the content to be the canonical url.
content entity
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\HasLifecycleCallbacks*
*/
class Content
{
/**
* #var integer
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* SeoUrl's from page
*
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="Application\Entity\Url", mappedBy="content", cascade={"remove", "persist"})
*/
protected $urls;
URL entity
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Entity Class representing our Url module.
*
* #ORM\Entity
* #ORM\Table(name="url")
*/
class Url {
/**
* #ORM\Id
* #ORM\Column(type="integer");
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
protected $id;
/**
* Content with Url
*
* #ORM\ManyToOne(targetEntity="Application\Entity\Content", inversedBy="urls")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="content_id", referencedColumnName="id", onDelete="CASCADE")
* })
*/
protected $content;
/**
* #ORM\Column(type="string")
* #var string
*/
protected $url;
My formfield
namespace Content\Form\Fieldset;
use Content\Entity\Content;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
class ContentFieldset
{
protected $em;
public function __construct()
{
parent::__construct('content');
$this->setObject(new Content());
}
public function init()
{
$this->em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$this->setHydrator(new DoctrineHydrator($this->em));
$this->add(
array(
'name' => 'id',
'type' => 'Zend\Form\Element\Hidden'
)
);
$this->add(
array(
'name' => 'url',
'type' => 'DoctrineModule\Form\Element\ObjectRadio',
'options' => array(
'label' => 'Url',
'object_manager' => $this->em,
'target_class' => 'Application\Entity\Url',
'property' => 'url',
'is_method' => true,
'find_method' => array(
'name' => 'findBy',
'params' => array(
'criteria' => array('content' => 1),// I need this to be the content id
'orderBy' => array(),
),
)
)
)
);
}
I want only the Url's that are related so i found find_method, but i can only use hard coded cricteria. My question is, how can i give the ObjectRadio form the id of content to search for in the url entity.
I tried to use $this->getObject->getId() , but no luck.
Side note: in the Url Entity there will be a field the hold the information of the url is canonical or not. And will be used to check it's ObjectRadio.
My form
$this->add(
array(
'name' => 'url',
'type' => 'Zend\Form\Element\Radio',
'options' => array(
'value_options' => array(
'' => ''
)
)
)
);
and then i overwrite the value_options in my view like this
$options = array();
$urls = $content->get('urls')->getFieldsets();
foreach($urls as $url) {
$url_id = $url->getObject()->getId();
$url_url = $url->getObject()->getUrl();
$options[$url_id] = $url_url;
}
echo $this->formRow($content->get('url')->setAttributes(
array(
'options' => $options
)
));
I hope someone in the future can use this answer.
Beter answers are allways welcome.
Related
I've got the next error in my development:
[Doctrine\ORM\Mapping\MappingException]
The target-entity Game\Entity\UserEntity cannot be found in
'Game\Entity\ChallengeRosterEntity#user'.
I have two modules:
User
Game
In these modules I have defined several entities where one of them is relationed with other entity which belongs to other module.
\Game\Entity\ChallengeRosterEntity.php
<?php
namespace Game\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use User\Entity;
/** #ORM\Entity
* #ORM\Table(name="challenge_roster")
* #ORM\Entity(repositoryClass="Game\Repository\ChallengeRosterRepository")
*/
class ChallengeRosterEntity{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="ChallengeEntity", inversedBy="challengeRoster")
*
**/
protected $challenge;
/**
* #ORM\ManyToOne(targetEntity="UserEntity", inversedBy="userInRosters")
*
**/
protected $user;
/**
* #ORM\Column(type="integer", nullable = true)
*/
protected $points;
/**
* Fecha y hora de creación del roster del desafío por parte del usuario
*
* #ORM\Column(type="datetime", nullable = false)
*/
protected $date;
/**
* #ORM\ManyToMany(targetEntity="BasketballPlayerStatsEntity")
* #ORM\JoinTable(name="players_roster",
* joinColumns={#ORM\JoinColumn(name="challenge_roster_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="basketball_player_stats_id", referencedColumnName="id")}
* )
**/
protected $basketballPlayers;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set points
*
* #param integer $points
* #return ChallengeRosterEntity
*/
public function setPoints($points)
{
$this->points = $points;
return $this;
}
/**
* Get points
*
* #return integer
*/
public function getPoints()
{
return $this->points;
}
/**
* Set date
*
* #param \DateTime $date
* #return ChallengeRosterEntity
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set challenge
*
* #param \Game\Entity\ChallengeEntity $challenge
* #return ChallengeRosterEntity
*/
public function setChallenge(\Game\Entity\ChallengeEntity $challenge = null)
{
$this->challenge = $challenge;
return $this;
}
/**
* Get challenge
*
* #return \Game\Entity\ChallengeEntity
*/
public function getChallenge()
{
return $this->challenge;
}
/**
* Set user
*
* #param \Game\Entity\UserEntity $user
* #return ChallengeRosterEntity
*/
public function setUser(\Game\Entity\UserEntity $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \Game\Entity\UserEntity
*/
public function getUser()
{
return $this->user;
}
/**
* Constructor
*/
public function __construct()
{
$this->basketballPlayers = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add basketballPlayers
*
* #param \Game\Entity\BasketballPlayerStatsEntity $basketballPlayers
* #return ChallengeRosterEntity
*/
public function addBasketballPlayer(\Game\Entity\BasketballPlayerStatsEntity $basketballPlayers)
{
$this->basketballPlayers[] = $basketballPlayers;
return $this;
}
/**
* Remove basketballPlayers
*
* #param \Game\Entity\BasketballPlayerStatsEntity $basketballPlayers
*/
public function removeBasketballPlayer(\Game\Entity\BasketballPlayerStatsEntity $basketballPlayers)
{
$this->basketballPlayers->removeElement($basketballPlayers);
}
/**
* Get basketballPlayers
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getBasketballPlayers()
{
return $this->basketballPlayers;
}
}
\User\Entity\UserEntity.php
<?php
namespace User\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Game\Entity;
/** #ORM\Entity
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="User\Repository\UserRepository")
*/
class UserEntity{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="string", length = 20, nullable = false)
*/
protected $nick;
/**
* #ORM\Column(type="string", length = 100, nullable = false)
*/
protected $email;
/**
* #ORM\Column(type="string", length = 100, nullable = true)
*/
protected $thumb;
/**
* #ORM\Column(type="integer", nullable = false)
*/
protected $totalRetodones;
/**
* #ORM\Column(type="integer", nullable = false)
*/
protected $challengeWon;
/**
* #ORM\Column(type="integer", nullable = false)
*/
protected $points;
/**
* #ORM\Column(type="integer", nullable = false)
*/
protected $spentRetodones;
/**
* #ORM\Column(type="string", length = 100, nullable = true)
*/
protected $twitterAccount;
/**
* #ORM\Column(type="string", length = 100, nullable = true)
*/
protected $facebookAccount;
/**
* #ORM\OneToMany(targetEntity="StatusEntity", mappedBy="users")
**/
protected $status;
/**
* #ORM\OneToMany(targetEntity="UserEntity", mappedBy="refered")
**/
protected $referedBy;
/**
* #ORM\ManyToOne(targetEntity="UserEntity", inversedBy="referedBy")
* #ORM\JoinColumn(name="refered_id", referencedColumnName="id")
**/
protected $refered;
/**
* #ORM\ManyToMany(targetEntity="UserEntity", mappedBy="myFriends")
**/
protected $friendsWithMe;
/**
* #ORM\ManyToMany(targetEntity="UserEntity", inversedBy="friendsWithMe")
* #ORM\JoinTable(name="user_friends",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="friend_user_id", referencedColumnName="id")}
* )
**/
protected $myFriends;
/**
* #ORM\ManyToOne(targetEntity="ChallengeEntity", inversedBy="userChallenger")
*
**/
//protected $usersChallenger;
/**
* #ORM\ManyToOne(targetEntity="ChallengeEntity", inversedBy="userChallenged")
*
**/
//protected $usersChallenged;
/**
* #ORM\ManyToOne(targetEntity="ChallengeRosterEntity", inversedBy="user")
*
**/
protected $userInRosters;
/**
* Constructor
*/
public function __construct()
{
$this->status = new \Doctrine\Common\Collections\ArrayCollection();
$this->referedBy = new \Doctrine\Common\Collections\ArrayCollection();
$this->friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection();
$this->myFriends = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nick
*
* #param string $nick
* #return UserEntity
*/
public function setNick($nick)
{
$this->nick = $nick;
return $this;
}
/**
* Get nick
*
* #return string
*/
public function getNick()
{
return $this->nick;
}
/**
* Set email
*
* #param string $email
* #return UserEntity
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set thumb
*
* #param string $thumb
* #return UserEntity
*/
public function setThumb($thumb)
{
$this->thumb = $thumb;
return $this;
}
/**
* Get thumb
*
* #return string
*/
public function getThumb()
{
return $this->thumb;
}
/**
* Set totalRetodones
*
* #param integer $totalRetodones
* #return UserEntity
*/
public function setTotalRetodones($totalRetodones)
{
$this->totalRetodones = $totalRetodones;
return $this;
}
/**
* Get totalRetodones
*
* #return integer
*/
public function getTotalRetodones()
{
return $this->totalRetodones;
}
/**
* Set challengeWon
*
* #param integer $challengeWon
* #return UserEntity
*/
public function setChallengeWon($challengeWon)
{
$this->challengeWon = $challengeWon;
return $this;
}
/**
* Get challengeWon
*
* #return integer
*/
public function getChallengeWon()
{
return $this->challengeWon;
}
/**
* Set points
*
* #param integer $points
* #return UserEntity
*/
public function setPoints($points)
{
$this->points = $points;
return $this;
}
/**
* Get points
*
* #return integer
*/
public function getPoints()
{
return $this->points;
}
/**
* Set spentRetodones
*
* #param integer $spentRetodones
* #return UserEntity
*/
public function setSpentRetodones($spentRetodones)
{
$this->spentRetodones = $spentRetodones;
return $this;
}
/**
* Get spentRetodones
*
* #return integer
*/
public function getSpentRetodones()
{
return $this->spentRetodones;
}
/**
* Set twitterAccount
*
* #param string $twitterAccount
* #return UserEntity
*/
public function setTwitterAccount($twitterAccount)
{
$this->twitterAccount = $twitterAccount;
return $this;
}
/**
* Get twitterAccount
*
* #return string
*/
public function getTwitterAccount()
{
return $this->twitterAccount;
}
/**
* Set facebookAccount
*
* #param string $facebookAccount
* #return UserEntity
*/
public function setFacebookAccount($facebookAccount)
{
$this->facebookAccount = $facebookAccount;
return $this;
}
/**
* Get facebookAccount
*
* #return string
*/
public function getFacebookAccount()
{
return $this->facebookAccount;
}
/**
* Add status
*
* #param \User\Entity\StatusEntity $status
* #return UserEntity
*/
public function addStatus(\User\Entity\StatusEntity $status)
{
$this->status[] = $status;
return $this;
}
/**
* Remove status
*
* #param \User\Entity\StatusEntity $status
*/
public function removeStatus(\User\Entity\StatusEntity $status)
{
$this->status->removeElement($status);
}
/**
* Get status
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getStatus()
{
return $this->status;
}
/**
* Add referedBy
*
* #param \User\Entity\UserEntity $referedBy
* #return UserEntity
*/
public function addReferedBy(\User\Entity\UserEntity $referedBy)
{
$this->referedBy[] = $referedBy;
return $this;
}
/**
* Remove referedBy
*
* #param \User\Entity\UserEntity $referedBy
*/
public function removeReferedBy(\User\Entity\UserEntity $referedBy)
{
$this->referedBy->removeElement($referedBy);
}
/**
* Get referedBy
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getReferedBy()
{
return $this->referedBy;
}
/**
* Set refered
*
* #param \User\Entity\UserEntity $refered
* #return UserEntity
*/
public function setRefered(\User\Entity\UserEntity $refered = null)
{
$this->refered = $refered;
return $this;
}
/**
* Get refered
*
* #return \User\Entity\UserEntity
*/
public function getRefered()
{
return $this->refered;
}
/**
* Add friendsWithMe
*
* #param \User\Entity\UserEntity $friendsWithMe
* #return UserEntity
*/
public function addFriendsWithMe(\User\Entity\UserEntity $friendsWithMe)
{
$this->friendsWithMe[] = $friendsWithMe;
return $this;
}
/**
* Remove friendsWithMe
*
* #param \User\Entity\UserEntity $friendsWithMe
*/
public function removeFriendsWithMe(\User\Entity\UserEntity $friendsWithMe)
{
$this->friendsWithMe->removeElement($friendsWithMe);
}
/**
* Get friendsWithMe
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getFriendsWithMe()
{
return $this->friendsWithMe;
}
/**
* Add myFriends
*
* #param \User\Entity\UserEntity $myFriends
* #return UserEntity
*/
public function addMyFriend(\User\Entity\UserEntity $myFriends)
{
$this->myFriends[] = $myFriends;
return $this;
}
/**
* Remove myFriends
*
* #param \User\Entity\UserEntity $myFriends
*/
public function removeMyFriend(\User\Entity\UserEntity $myFriends)
{
$this->myFriends->removeElement($myFriends);
}
/**
* Get myFriends
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getMyFriends()
{
return $this->myFriends;
}
/**
* Set userInRosters
*
* #param \User\Entity\ChallengeRosterEntity $userInRosters
* #return UserEntity
*/
public function setUserInRosters(\User\Entity\ChallengeRosterEntity $userInRosters = null)
{
$this->userInRosters = $userInRosters;
return $this;
}
/**
* Get userInRosters
*
* #return \User\Entity\ChallengeRosterEntity
*/
public function getUserInRosters()
{
return $this->userInRosters;
}
}
Doctrine 2 has the next configuration in each file.
\Game\config\module.config.php
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
* #copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Game;
return array(
'router' => array(
'routes' => array(
/* 'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
), */
// The following is a route to simplify getting started creating
// new controllers and actions without needing to create a new
// module. Simply drop new controllers in, and you can access them
// using the path /application/:controller/:action
'application' => array(
'type' => 'Literal',
'options' => array(
'route' => '/juego',
'defaults' => array(
'__NAMESPACE__' => 'Game\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
'service_manager' => array(
'abstract_factories' => array(
'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
'Zend\Log\LoggerAbstractServiceFactory',
),
'aliases' => array(
'translator' => 'MvcTranslator',
),
),
'translator' => array(
'locale' => 'en_US',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'controllers' => array(
'invokables' => array(
'Game\Controller\Index' => 'Game\Controller\IndexController'
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'game/index/index' => __DIR__ . '/../view/game/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
// Doctrine config
'doctrine' => array(
'driver' => array(
__NAMESPACE__ . '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity')
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
)
)
)
),
// Placeholder for console routes
'console' => array(
'router' => array(
'routes' => array(
),
),
),
);
\User\config\module.config.php
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
* #copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace User;
return array(
'router' => array(
'routes' => array(
// The following is a route to simplify getting started creating
// new controllers and actions without needing to create a new
// module. Simply drop new controllers in, and you can access them
// using the path /application/:controller/:action
'application' => array(
'type' => 'Literal',
'options' => array(
'route' => '/user',
'defaults' => array(
'__NAMESPACE__' => 'User\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
'service_manager' => array(
'abstract_factories' => array(
'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
'Zend\Log\LoggerAbstractServiceFactory',
),
'aliases' => array(
'translator' => 'MvcTranslator',
),
),
'translator' => array(
'locale' => 'en_US',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
'controllers' => array(
'invokables' => array(
'User\Controller\Index' => 'User\Controller\IndexController'
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'user/index/index' => __DIR__ . '/../view/user/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
// Doctrine config
'doctrine' => array(
'driver' => array(
__NAMESPACE__ . '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity')
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
)
)
)
),
// Placeholder for console routes
'console' => array(
'router' => array(
'routes' => array(
),
),
),
);
What am I doing wrong?
I have a list of Doctrine entities (called "Circuit") and would like to generate a form listing them within a <table> and add a way to tick them for mass deletion (kind of what Sonata Admin does, without the need for an admin class).
I've looked everywhere but I can't figure out for the life of me what to do. There is just one layer to this class (plain old object), and every time I try to add a collection type to my form builder I get the following error:
Neither the property "circuits" nor one of the methods "getCircuits()", "circuits()", "isCircuits()", "hasCircuits()", "__get()", "__call()" exist and have public access in class "NetDev\CoreBundle\Entity\Circuit".
Am I supposed to create a "proxy" class to create a collection of circuits ? Did I miss something ?
All the howtos I found so far are using a "master" class like "Article" and a collection of child classes like "Categories" which doesn't apply to my present issue.
Here is my CircuitsController.php (I use the "addAction" for the tests, eventually everything will be located in indexAction):
<?php
namespace NetDev\WebManagerBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use NetDev\CoreBundle\Form\CircuitType;
use NetDev\CoreBundle\Entity\Circuit;
class CircuitsController extends Controller {
public function indexAction($page = 1) {
$listCircuits = $this->getDoctrine()->getManager()->getRepository('NetDevCoreBundle:Circuit')->findAll();
$content = $this->get('templating')->render('NetDevWebManagerBundle:Circuits:index.html.twig',
array('listCircuits' => $listCircuits));
return new Response($content);
}
public function addAction(Request $request) {
$circuit = new Circuit();
$form = $this->createForm(new CircuitType(), $circuit);
if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()) {
/* some action that is not actually relevant */
}
return new Response($this->get('templating')->render('NetDevWebManagerBundle:Circuits:add.html.twig',
array('circuit' => $circuit,
'form' => $form->createView())));
}
The CircuitType.php file:
<?php
namespace NetDev\CoreBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CircuitType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('circuits', 'collection', array('type' => 'entity', 'allow_add' => true,
'allow_delete' => true, 'by_reference' => false,
'label' => false,
'options' => array('class' => 'NetDevCoreBundle:Circuit',
'label' => false, 'multiple' => true,
'expanded' => true)
))
/* ->add('vlanId', 'integer', array('required' => true, 'label' => 'VLAN ID')) */
/* ->add('popOut', 'text', array('required' => true, 'label' => 'Injecting PoP', */
/* 'max_length' => 3)) */
/* ->add('popsIn', 'textarea', array('required' => true, 'label' => 'Listening PoP')) */
/* ->add('bandwidth', 'integer', array('label' => 'Bandwidth')) */
/* ->add('xconnectId', 'text', array('label' => 'Cross-connect ID')) */
/* ->add('Create', 'submit') */
;
}
/**
* #return string
*/
public function getName()
{
return 'netdev_corebundle_circuit';
}
}
And finally, the Circuit.php entity file:
<?php
namespace NetDev\CoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Circuit
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="NetDev\CoreBundle\Entity\CircuitRepository")
*/
class Circuit
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="vlan_id", type="integer")
* #Assert\Type(type="int")
* #Assert\Range(min="1", max="4096")
*/
private $vlanId;
/**
* #var array
*
* #ORM\Column(name="pop_out", type="array")
* #Assert\NotBlank()
* #Assert\Length(max=3)
*/
private $popOut;
/**
* #var array
*
* #ORM\Column(name="pops_in", type="array")
* #Assert\NotBlank()
*/
private $popsIn;
/**
* #var integer
*
* #ORM\Column(name="bandwidth", type="integer")
* #Assert\Type(type="int")
*/
private $bandwidth;
/**
* #var string
*
* #ORM\Column(name="xconnect_id", type="string", length=255)
* #Assert\NotBlank()
* #Assert\Length(max="255")
*/
private $xconnectId;
/* Getters and Setters stripped for clarity's sake */
public function __toString() {
return "{$this->vlanId}-{$this->popOut}";
}
}
If you need the twig template tell me, I haven't added it because I am not even close to having something outputted aside from that Exception.
As said by #Cerad, the answer here was to pass the result of
$listCircuits = $this->getDoctrine()->getManager()->getRepository('NetDevCoreBundle:Circuit')->findAll();
directly to the collection. Everything worked nicely afterwards.
I would like to make one form in which I could have elements to populate two entities.
How can I do that? One of the objects is mapped to the other one.
For example I have something like this:
Table user:
id | login | password
Table user_email:
id | user_id | email
There can be more than one row user_email mapped to user - user can have more than one email.
But - when I'm adding first occurrence of the user I have to get his first email.
I know everything how to map entities but I have problem with populating objects from ZF2 form.
Can anyone suggest how should I do this? I've tried to make two fieldsets but I cannot bind object to fieldset. If this is the solution how bind objects to form which have two filedsets? Every fieldset have mapped doctrine2 hydrator but when I'm trying to bind one of the entity to form (not fieldset which i cannot do) I have error message:
Zend\Stdlib\Hydrator\ArraySerializable::extract expects the provided object to implement getArrayCopy()
Before my example I have to explan what i want to achieve. I have a table cameras - which contain link and some other information about streaming cameras. Second table: cameras_desc contain descriptions to those cameras in different languages. In my CMS i want to add two rows: one in cameras and second in cmaeras_desc in one form. cameras_desc will have first translation in polish language (which would be default language for CMS). As u can see cameras and cameras_desc are mapped with some other entites (cameras with checkpoints and cameras_desc with languages). but thats not a point. What i want to achieve is to populate two rows in two tables by one form. lang in cameras_desc is set by PHP code, but checkpoint is set by user in form by select element. everything works in code below but it isnt made honestly.
This is my code:
First entity:
namespace Granica\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Cameras
*
* #ORM\Table(name="cameras", indexes={#ORM\Index(name="IDX_6B5F276AF27C615F", columns={"checkpoint_id"})})
* #ORM\Entity
*/
class Cameras
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="link", type="text", nullable=false)
*/
private $link;
/**
* #var string
*
* #ORM\Column(name="direction", type="string", length=4, nullable=false)
*/
private $direction;
/**
* #var \Granica\Entity\Checkpoints
*
* #ORM\ManyToOne(targetEntity="Granica\Entity\Checkpoints")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="checkpoint_id", referencedColumnName="id")
* })
*/
private $checkpoint;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set link
*
* #param string $link
* #return Cameras
*/
public function setLink($link)
{
$this->link = $link;
return $this;
}
/**
* Get link
*
* #return string
*/
public function getLink()
{
return $this->link;
}
/**
* Set direction
*
* #param string $direction
* #return Cameras
*/
public function setDirection($direction)
{
$this->direction = $direction;
return $this;
}
/**
* Get direction
*
* #return string
*/
public function getDirection()
{
return $this->direction;
}
/**
* Set checkpoint
*
* #param \Granica\Entity\Checkpoints $checkpoint
* #return Cameras
*/
public function setCheckpoint(\Granica\Entity\Checkpoints $checkpoint = null)
{
$this->checkpoint = $checkpoint;
return $this;
}
/**
* Get checkpoint
*
* #return \Granica\Entity\Checkpoints
*/
public function getCheckpoint()
{
return $this->checkpoint;
}
}
Second entity:
<?php
namespace Granica\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* CamerasDesc
*
* #ORM\Table(name="camera_desc", indexes={#ORM\Index(name="lang", columns={"lang"}), #ORM\Index(name="camera_id", columns={"camera_id"})})
* #ORM\Entity
*/
class CameraDesc
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=false)
*/
private $description;
/**
* #var \Granica\Entity\Languages
*
* #ORM\ManyToOne(targetEntity="Granica\Entity\Languages")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="lang", referencedColumnName="id")
* })
*/
private $lang;
/**
* #var \Granica\Entity\Cameras
*
* #ORM\ManyToOne(targetEntity="Granica\Entity\Cameras")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="camera_id", referencedColumnName="id")
* })
*/
private $camera;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set description
*
* #param string $description
* #return CamerasDesc
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set lang
*
* #param \Granica\Entity\Languages $lang
* #return CamerasDesc
*/
public function setLang(\Granica\Entity\Languages $lang = null)
{
$this->lang = $lang;
return $this;
}
/**
* Get lang
*
* #return \Granica\Entity\Languages
*/
public function getLang()
{
return $this->lang;
}
/**
* Set camera
*
* #param \Granica\Entity\Cameras $camera
* #return CamerasDesc
*/
public function setCamera(\Granica\Entity\Cameras $camera = null)
{
$this->camera = $camera;
return $this;
}
/**
* Get camera
*
* #return \Granica\Entity\Cameras
*/
public function getCamera()
{
return $this->camera;
}
}
Fieldset ( for camera_desc ):
namespace Granica\Form;
use Zend\Form\Fieldset;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use DoctrineORMModule\Stdlib\Hydrator\DoctrineEntity;
use Granica\Entity\Languages;
class CameraDescFieldset extends Fieldset implements ObjectManagerAwareInterface
{
protected $objectManager;
public function __construct(ObjectManager $objectManager)
{
parent::__construct('camera_desc');
$this->setObjectManager($objectManager);
$this->setHydrator(new DoctrineHydrator($this->getObjectManager(),'Granica\Entity\CameraDesc'));
$this->add(array(
'name' => 'description',
'attributes' => array(
'type' => 'text',
'placeholder' => 'Opis',
'required' => 'true',
),
'options' => array(
'label' => 'Opis kamery',
),
));
}
// implementacja interfajsu objectmanager
public function setObjectManager(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
return $this;
}
public function getObjectManager()
{
return $this->objectManager;
}
}
Form (for camera):
use Zend\Form\Form;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Granica\Form\CameraDescFieldset;
class AddCameraForm extends Form implements ObjectManagerAwareInterface
{
protected $objectManager;
public function __construct(ObjectManager $objectManager)
{
parent::__construct('checkpoint');
$this->setObjectManager($objectManager);
// tworzenie formularza
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'checkpoint',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
'label' => 'Punkt graniczny',
'object_manager' => $this->getObjectManager(),
'target_class' => 'Granica\Entity\Checkpoints',
'property' => 'name',
'empty_option' => '--- wybierz przejście ---'
),
));
$this->add(array(
'name' => 'link',
'attributes' => array(
'type' => 'text',
'placeholder' => 'Link',
'required' => 'true',
),
'options' => array(
'label' => 'Adres URL kamery',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'direction',
'attributes' => array(
'required' => 'true',
),
'options' => array(
'label' => 'Kierunek',
'empty_option' => '--- wybierz kierunek ---',
'value_options' => array(
'from' => 'FROM: Wyjazd z Polski',
'to' => 'TO: Wjazd do Polski',
),
)
));
$this->add(new CameraDescFieldset($this->getObjectManager()));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Zapisz',
'id' => 'submitbutton',
),
));
}
// implementacja interfajsu objectmanager
public function setObjectManager(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
return $this;
}
public function getObjectManager()
{
return $this->objectManager;
}
}
And the add controller:
public function addAction()
{
$camera = new Cameras();
$cameraDesc = new CameraDesc();
$lang = $this->getEntityManager()->getRepository('Granica\Entity\Languages')->find('pl');
$form = new AddCameraForm($this->getEntityManager());
$cameraDescFieldset = new CameraDescFieldset($this->getEntityManager());
$form->setHydrator(new DoctrineHydrator($this->getEntityManager(),'Granica\Entity\Cameras'));
$form->bind($camera);
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$data = $form->getData();
$cameraDesc->setLang($lang);
$cameraDesc->setDescription($request->getPost()['camera_desc']['description']);
$this->getEntityManager()->persist($camera);
$cameraDesc->setCamera($camera);
$this->getEntityManager()->persist($cameraDesc);
$this->getEntityManager()->flush();
return $this->redirect()->toRoute('cameras');
}
}
return new ViewModel(array('form' => $form));
}
As you can see I've managed to overcome my problem - I've populate camera_desc with data which I get from post. This work but isn't the best solution - for example filters didn't work on cameraDesc descrition.
I have been searching before for an answer for this problem but after hours I need to ask you.
I have one Entity called Pedidos, that have another entity related called PedidosMateriales, as you can see:
(...)
/**
* Pedidos
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="ochodoscuatro\IntranetBundle\Entity\PedidosRepository")
*/
class Pedidos
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
(...)
/**
* #ORM\OneToMany(targetEntity="PedidosMateriales", mappedBy="pedido")
*/
private $pedidosmateriales;
public function __construct() {
$this->pedidosmateriales = new \Doctrine\Common\Collections\ArrayCollection();
$this->pagos = new \Doctrine\Common\Collections\ArrayCollection();
}
public function addPedidosmateriales(\ochodoscuatro\IntranetBundle\Entity\PedidosMateriales $pedidosmateriales){
$this->pedidosmateriales[] = $pedidosmateriales;
}
public function getPedidosmateriales(){
return $this->pedidosmateriales;
}
(...)
}
When I submit a form, if I get $_POST, I can see all the information good there, but just after doing
$form->handleRequest($request);
I get this error:
Neither the property "pedidosmateriales" nor one of the methods "addPedidosmaterial()", "addPedidosmateriale()", "setPedidosmateriales()", "__set()" or "__call()" exist and have public access in class "ochodoscuatro\IntranetBundle\Entity\Pedidos".
But I have them already written!
I've read that with "multiple" => true I could get the answer, but it launch another error telling that the option "multiple" does not exist.
My form is this:
$builder->add('fechapedido', 'date', array(//Fecha del pedido
'widget' => 'single_text',
'format' => 'dd/MM/yyyy',
'attr' => array('class' => 'datepicker'),
'data' => new \DateTime() //Valor (Fecha actual)
))
->add('cliente', 'entity', array(
'class' => 'ochodoscuatroIntranetBundle:Clientes',
'property' => 'nombre',
'empty_value' => 'Nombre cliente'))//Nombre del "placeholder"
->add('pedidosmateriales', 'collection', array('type' => new PedidosMaterialesType(), 'allow_add' => true, 'by_reference' => false,));
}
I have some problem with colection in zf2 and doctryne.
Problem: I add some client and need have some multiselect.
ClientEntity
/**
* #ORM\MappedSuperclass
*/
class Client {
...
/**
* #ORM\ManyToOne(targetEntity="\Module\Model\Job")
* #ORM\JoinColumn(name="job_id", referencedColumnName="id")
*/
protected $job;
/**
* #ORM\OneToMany(targetEntity="SomeOption", mappedBy="job", cascade= {"persist", "remove"})
* */
protected $someOption;
...
public function __construct() {
$this->someOption= new ArrayCollection();
}
OptionEntity
/**
* #ORM\MappedSuperclass
*/
class SomeOption{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="\Module\Model\Client")
* #ORM\JoinColumn(name="job_id", referencedColumnName="id")
* */
protected $job;
/**
* #ORM\Column(type="string", nullable=false)
*/
protected $option;
}
Bought model have getter and setter, in Client model have:
public function addSomeOption(Collection $options) {
foreach ($options as $option) {
$option->setJob($this);
$this->someOption->add($option);
}
return $this;
}
public function removeSomeOption(Collection $options) {
foreach ($options as $option) {
$option->setJob(null);
$this->someOption->removeElement($option);
}
return $this;
}
public function getSomeOption() {
return $this->someOption;
}
Form:
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'someOption',
'attributes' => array(
'id' => 'someOption',
),
'options' => array(
'label' => 'Rozliczenie',
'value_options' => array(
array('value' => '1r', 'label' => '1/rok'),
array('value' => '1m', 'label' => '1/miesiąc'),
array('value' => '1w', 'label' => '1/tydzień'),
array('value' => '1d', 'label' => '1/dzień'),
),
),
'attributes' => array(
'class' => 'span12 settlement chosen',
'multiple' => 'multiple'
)
));
after this i need have 1 row of client and 1+ row of someOption, may any help to repair code ? or much more will be explain what i make wrong.