Is there a possibility to read all available Values from an entity?
E.G.
class Properties
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="UserID", type="string", length=255)
*/
private $userID;
/**
* #var string
*
* #ORM\Column(name="Sport", type="string", length=1)
*/
private $sport;
.
.
.
So that I will get the name of the Value like: Id, UserID, Sport?
You can read the info you need thru the Doctrine metadata info as follow:
$doctrine = $this->getContainer()->get("doctrine");
$em = $doctrine->getManager();
$className = "Acme\DemoBundle\Entity\Properties";
$metadata = $em->getClassMetadata($className);
$nameMetadata = $metadata->fieldMappings['sport'];
echo $nameMetadata['type']; //print "string"
echo $nameMetadata['length']; // print "1"
// OR query for all fields
// Returns an array with all the identifier column names.
$metadata->getIdentifierColumnNames();
More info on the API DOC
Hope this help
You can make use of ReflectionClass::getProperties() to loop through all properties.
http://php.net/manual/en/reflectionclass.getproperties.php
Related
I'm trying to access to a foreign key stored in an entity using doctrine and querybuilder.
I got an entity named User which is linked to another entity called Client with a ManyToOne relationship.
I wanted to build a querybuilder that get me the field client_id in user table, that match the id of a client.
My User Entity :
/**
* AppBundle\EntityAppBundle\Entity\User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User extends FOSUser
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=255)
*
*
*/
private $nom;
/**
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Etablissement", inversedBy="users")
*
*/
private $etablissements;
/**
*
* #ORM\ManyToOne(targetEntity="Client", inversedBy="users")
*
*/
private $client;
My Client Entity :
/**
* AppBundle\EntityAppBundle\Entity\Client
*
* #ORM\Table(name="client")
* #ORM\Entity()
*/
class Client{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=255)
*
*
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="adresse", type="string", length=255)
*
*
*/
/**
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\User", mappedBy="client",
cascade={"persist"}, orphanRemoval=true)
*
*/
private $users;
In my database, my entity user has the client_id in foreign key column.
So in my queryBuilder in UserRepository, I do :
public function findClientIdViaUserId($myUserId, $myClientID)
{
return $this->createQueryBuilder('e')
->from('AppBundle:User', 'i')
->join('AppBundle:Client', 'c')
->where('c.id = :myClientID')
->andWhere('e.id = :myUserId')
->setParameter('myuserId', $myUserId)
->setParameter('myClientId', $myClientID)
->getQuery()
->getOneOrNullResult();
}
I expect to get the id of the client_id for a user_id.
Let's say that i wanted to get one client_id with the user_id called 1.
With my queryBuilder i got an error like :
[Syntax Error] line 0, col 67: Error: Expected Doctrine\ORM\Query\Lexer::T_WITH, got ','
How may I process to get the client_id from the user_id ?
Thank you for your replies !
Why don't you use EntityManager ?
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('AppBundle:User')->find(YOURUSERID);
$client = $user->getClient();
You made a mistake in chaining of Doctrine methods. You've already set an alias for User entity by calling createQueryBuilder('e'). Repository knows about entity it linked to.
When you call from('AppBundle:User', 'i') - an alias for User entity is i now. That's why Doctrine is throwing an error about wrong syntax in resulting DQL.
So, try this piece of code:
return $this
->createQueryBuilder('e')
->join('e.client', 'c')
->where('c.id = :myClientID')
->andWhere('e.id = :myUserId')
->setParameter('myUserId', $myUserId)
->setParameter('myClientId', $myClientID)
->getQuery()
->getOneOrNullResult();
I have two entities:
1)
/**
* Post
*
* #ORM\Table(name="article")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PostRepository")
*/
class Post
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
...
/**
* #var string
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Image", cascade={"persist"}, fetch="EAGER")
* #ORM\JoinColumn(name="image", referencedColumnName="id", nullable=true)
*/
private $image;
}
and 2)
/**
* Image
*
* #ORM\Table(name="image")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ImageRepository")
*/
class Image
{
/**
* #var int
*
* #ORM\Column(name="id", type="string", length=40)
* #ORM\Id
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="small", type="blob", nullable=true)
*/
private $small;
/**
* #var string
*
* #ORM\Column(name="medium", type="blob", nullable=true)
*/
private $medium;
/**
* #var string
*
* #ORM\Column(name="large", type="blob", nullable=true)
*/
private $large;
...
}
Both entities have getters and setters.
The controller sets the post to update
$requestFile = $request->files->get('image');
$em = $this->getDoctrine()->getManager();
$record = $em->getRepository('AppBundle:Post')->find($id);
if (!$record) {
throw $this->createNotFoundException(
'No product found for id '.$record
);
}
$record->setTitle($request->request->get('title'));
$record->constructAlias($request->request->get('title'));
...
if ($request->files->get('image')) {
// check if image already exists
$imgGeneratedId = sha1_file($request->files->get('image')->getPathName());
$imageRepo = $this->getDoctrine()->getRepository('AppBundle:Image');
$isPresent = $imageRepo->find($imgGeneratedId);
$image = $isPresent;
if (!$isPresent) {
$image = new Image();
$image->setId($imgGeneratedId);
$image->setLarge(file_get_contents($request->files->get('image')->getPathName()));
$mediumImage =
...
$em->persist($image);
}
$record->setImage($em->getReference('AppBundle:Image', $image->getId()));
}
$em->persist($record);
$em->flush();
Please ignore any syntax errors or other kinds; there are none.
The problem is that even if image already exists it is trying to create one which causes error in database. So, in order to avoid this I used getReference, but this causes other issues.
So, how can I force doctrine, not to insert an image if already exists and just set the article image with the image id?
Thanks.
I created two entities automatically ( using this manual http://symfony.com/doc/2.8/doctrine/reverse_engineering.html) based on ER model generated in Workbench. My intention was to create one-to-one relationship but annotation show it is one-to-many relationship. I created also embeed forms. I would like to insert client and new adress to database. I still get an error:
A new entity was found through the relationship 'UlaBundle\Entity\Client#adres' that was not configured to cascade persist operations for entity: qqq. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example #ManyToOne(..,cascade={"persist"}).
Error is shown even if i set #ManyToOne(..,cascade={"persist"}) and __toString function. What is the problem? Please help. Below my code:
///Client Entity
class Client
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=45, nullable=true)
*/
private $name;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \UlaBundle\Entity\Adres
*
* #ORM\ManyToOne(targetEntity="UlaBundle\Entity\Adres", cascade= {"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="adres_id", referencedColumnName="id")
* })
*/
private $adres;
/// Adres Entity
class Adres
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=45, nullable=true)
*/
private $name;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
///Controller
/**
* #Route("/client", name="client")
*/
public function clientAction(Request $request) {
$c = new Client();
$form = $this->createForm(ClientType::class,$c);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$m = $this->getDoctrine()->getManager();
$m->persist($c);
$m->flush();
return new Response('Added');
}
return $this->render('UlaBundle:Default:client_form.html.twig', array('form' => $form->createView()));
}
I think your problem come from the blank space in cascade= {"persist"}, you should remove it
/**
* #var \UlaBundle\Entity\Adres
*
* #ORM\ManyToOne(targetEntity="UlaBundle\Entity\Adres", cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="adres_id", referencedColumnName="id")
* })
*/
private $adres;
How can I solve a query where I want to get all data from the left table which isn't existing in the right table?
left table: ID | NAME | DATE
right table: ID | ID_left_table | NAME | DATE
It is confusing me a bit since I haven't got that experience with doctrine.
My entitys look like:
class NameData
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
.
.
.
and
class ValueData
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="TestBundle\Entity\NameData")
*/
private $nameid;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
.
.
.
1) First of all, fix $nameid property annotation in ValueData entity to this:
/**
* #ORM\ManyToOne(targetEntity="NameData")
* #ORM\JoinColumn(name="name_id", referencedColumnName="id")
**/
private $nameData;
This is basic Doctrine annotation mapping for relationships, in this case ManyToOne.
2) Modify valueData table to add foreign key, by typing php app/console doctrine:schema:update --force or with migrations
3) let Symfony generate the right setters and getters for ValueData entity, by running command in your console php app/console doctrine:generate:entities TestBundle:ValueData.
4) And then, if you need to get data in controller:
$valueData = $this->getDoctrine()->getRepository('TestBundle:ValueData')->find(1);//Find by ID 1 OR ->findAll() to get all records
$nameData = $valueData->getNameData(); //This line of code behind the scenes will
//join the valueData table with nameData, and get associated data
Add a comment if you will need help along the way.
Edit:
Below is the query builder to select all NameDatas which dont have any ValueData:
$nameDataRepo = $this->getDoctrine()->getRepository('TestBundle:NameData');
$nameDatasWithoutDatavalues = $nameDataRepo->createQueryBuilder('nameData')
->leftJoin('nameData.dataValues', 'dataValue')
->where('dataValue.id IS NULL')
->getQuery()
->getResult
Also, make sure to write bi-directional part of doctrine relationships, to be able to access children from parent entity NameData.php:
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(targetEntity="ValueData", mappedBy="nameData")
*/
private $valueDatas;
/**
* Constructor
*/
public function __construct()
{
$this->valueDatas = new \Doctrine\Common\Collections\ArrayCollection();
}
And in ValueData.php, edit $nameData property annotation to this:
/**
* #ORM\ManyToOne(targetEntity="NameData", inversedBy="valueDatas")
* #ORM\JoinColumn(name="name_id", referencedColumnName="id")
**/
private $nameData;
Here's what I'm having trouble with.
I've a Table which contains a column called shown_on_homepage and only one row should be set to 1, the rest should all be set to 0. I'm trying to add a new row to the database and this one should be set to 1, setting the one that previously had a 1 to 0.
In MySQL I know this can be achieved by issuing an update before the insert:
UPDATE table_name SET shown_on_homepage = 0
Here's my Entity:
class FeaturedPerson {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="content", type="string", length=2500, nullable=false)
*/
private $content;
/**
* #var \DateTime
*
* #ORM\Column(name="date_updated", type="datetime")
*/
private $dateUpdated;
/**
* #var bool
*
* #ORM\Column(name="shown_on_homepage", type="boolean", nullable=false)
*/
private $isShownOnHomepage;
//...
public function getIsShownOnHomepage() {
return $this->isShownOnHomepage;
}
public function setIsShownOnHomepage($isShownOnHomepage) {
$this->isShownOnHomepage = $isShownOnHomepage;
return $this;
}
}
And for the Controller I've:
$featured = new FeaturedPerson();
$featured->setContent('Test content.');
$featured->setDateUpdated('01/02/2013.');
$featured->setIsShownOnHomepage(TRUE);
$em = $this->getDoctrine()->getManager();
$em->persist($featured);
$em->flush();
It does add the new row, but the one that had a shown_on_homepage set to 1 still has it. I've researched but I couldn't find a way to achieve this, I hope you can help me.
You could execute a query prior to your existing code in your controller:
$queryBuilder = $this->getDoctrine()->getRepository('YourBundleName:FeaturedPerson')->createQueryBuilder('qb');
$result = $queryBuilder->update('YourBundleName:FeaturedPerson', 'd')
->set('d.isShownOnHomepage', $queryBuilder->expr()->literal(0))
->where('d.isShownOnHomepage = :shown')
->setParameter('shown', 1)
->getQuery()
->execute();
Change 'YourBundleName' to your bundle name.