Mysql Views Table in Symfony 2 - symfony

I have view table in my Database, how can I retrieve the data from this views?
I tried to use
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery('SELECT * FROM my_views');
$result = $query->getResult();
but it doesn't work.

If you want to perform a simple SQL query, you can do that :
$con = $this->getDoctrine()->getEntityManager()->getConnection();
$stmt = $con->executeQuery('SELECT * FROM my_views');
foreach ($stmt->fetchAll() as $row){
print_r($row);
}
When you use $em->createQuery(), you need to work with Doctrine entities.
If you want to use the mapping with your view, juste create an entity :
namespace Your\Bundle\Entity;
/**
* #ORM\Entity
* #ORM\Table(name="my_view")
*/
class MyView
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $someVarcharColumn;
public function getId()
{
return $this->id;
}
public function getSomeVarcharColumn()
{
return $this->someVarcharColumn;
}
}
And you can query it with DQL like this :
$results = $em->createQuery('
SELECT v
FROM YourBundle:MyView v
')->getResult();

Related

Saving information in controller symfony relation ManyToMany HELPPPPP

Hi I need to save information in my db, what I mean is, how to persist when the relationship is manytomany, I am doing like this but it doesn't work!...I will put some code of entity Menu.
/** Agrega nuevo menù
*
* #Route("/save", name="admin_menu_save")
* #Method({"GET", "POST"})
* #param Request $request
* #return Response
*/
public function saveAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$fecha_menu = $request->get('fecha');
$fecha_comprar = $request->get('fechacomprado');
$fecha_vencimiento = $request->get('fechavencimiento');
$alimentos = $request->get('select_alimentos');
$a = $em->getRepository('AdminBundle:Alimento')->findBy($alimentos);
$menu = new Menu();
$menu->setFecha(new \DateTime($fecha_menu));
$menu->setFechacomprar(new \DateTime($fecha_comprar));
$menu->setFechavence(new \DateTime($fecha_vencimiento));
$menu->setPrecio(6);
$menu->addAlimento($a);
$em->persist($menu);
$em->flush();
return new Response('Guardado OK');
}
//Menu Entity Definition (Just the necessary code):
/**
* #ORM\ManyToMany(targetEntity="Alimento", inversedBy="menu")
* #ORM\JoinTable(name="alimento_menu",
* joinColumns={
* #ORM\JoinColumn(name="menu_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="alimento_id", referencedColumnName="id")
* }
* )
*/
private $alimento;
/**
* Constructor
*/
public function __construct()
{
$this->alimento = new ArrayCollection();
}
/**
* Add alimento
*
* #param \AdminBundle\Entity\Alimento $alimento
*
* #return Menu
*/
public function addAlimento(Alimento $alimento)
{
$this->alimento[] = $alimento;
return $this;
}
/**
* Remove alimento
*
* #param \AdminBundle\Entity\Alimento $alimento
*/
public function removeAlimento(Alimento $alimento)
{
$this->alimento->removeElement($alimento);
}
/**
* Get alimento
*
* #return ArrayCollection
*/
public function getAlimento()
{
return $this->alimento;
}
}
I have not experience working with manytomany relations, I hope to solve this problem, that´s show very good, but I don´t know how to save,edit or remove in that manytomany table!....
First, this bit seems weird.
$alimentos = $request->get('select_alimentos');
$a = $em->getRepository('AdminBundle:Alimento')->findBy($alimentos);
Doctrine findBy takes an array with the entity field as a key and the specific entity value as the value. Like this:
$em-getRepository('AdminBundle:Alimento')->findBy(['id' => $id]);
If that's how your $alimentos variable is structured, that's fine. It just looks strange.
If this is a bi-directional relationship, you have to update both entities. So your controller code is like:
$a = $em->getRepository('AdminBundle:Alimento')->findBy($alimentos);
$menu = new Menu();
// -- more code ---//
$menu->addAlimento($a);
$a->addMenu($menu);
$em->persist($menu);
$em->flush();
Check this documentation.
I just realized what was...This was my solution:
foreach ($alimentos as $item) {
$a = $em->getRepository('AdminBundle:Alimento')->find($item);
$menu->addAlimento($a);
}
And of course later I persist menu.

Symfony2 How to find records which starts with specified character?

How to find records which starts with specified character?
for example: only users where username starts with the A
User class
<?php
namespace DemoBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=50)
*/
protected $name;
/**
* #ORM\Column(type="string", length=50)
*/
protected $lastname;
public function __construct()
{
parent::__construct();
// your own logic
}
//getters and setters
}
and controller action with solution #Kwido
public function listAction($letter)
{
$queryBuilder = $this->getEntityManager()->createQueryBuilder();
$queryBuilder
->select(['user'])
->from(User::class, 'user')
->andWhere($queryBuilder->expr()->like('user.lastname', ':lastname'))
->setParameter('lastname', $queryBuilder->expr()->literal('A%'));
$result = $queryBuilder->getQuery()->getResult();
die(var_dump($result));
}
this is all what I have. This give me error
Attempted to call an undefined method named "getEntityManager" of
class DemoBundle\Controller\DefaultController"
Hi #Damian change your code to it.
public function listAction($letter)
{
$result = $this->getDoctrine()
->getManager()
->createQueryBuilder()
->select('u')
->from(User::class, 'u')
->where('u.lastname LIKE :lastname')
->setParameter('lastname', 'A%')
->getQuery()
->getResult();
dump($result);
// return response bellow
}
When the page is loaded click in the Symfony profiler bar and go to database section. Look the generated query and try run it directly on database.
Use the querybuilder Like expr of Doctrine:
// Example - $qb->expr()->like('u.firstname', $qb->expr()->literal('Gui%'))
public function like($x, $y); // Returns Expr\Comparison instance
To use the Like expression within your Repository class:
// getEntityManager() = $this->getDoctrine()->getManager();
$queryBuilder = $this->getEntityManager()->createQueryBuilder();
$queryBuilder
->select(['user'])
->from(User::class, 'user')
->andWhere($queryBuilder->expr()->like('user.userName', ':userName'))
->setParameter('userName', $queryBuilder->expr()->literal('A%'));
$result = $queryBuilder->getQuery()->getResult();

Doctrine returns many-to-many collection in incorrect order

I'm starting to struggle with finding a solution for this online/offline so maybe someone has an answer or suggestion of best approach.
The problem is that a Question entity has a many-to-many relation tags which should return Tag entities in alphabetical order. The generated SQL is correct, but the collection which is returned doesn't follow the order.
I'm starting to lean towards using:
a) lifecycle events to call a method which will sort the tags collection.
b) on getTags() method call a method which will check if collection was sorted (for performance to avoid multiple sorts) and then sort the collection if it's the first time.
Does anyone know why collection is not sorted or which solution will be best?
Some info of code:
Generated SQL
SELECT
q0_.id AS id0,
q0_.question AS question1,
t1_.id AS id2,
t1_.name AS name3
FROM question q0_
LEFT JOIN questions_tags q2_ ON q0_.id = q2_.question_id
LEFT JOIN tag t1_ ON t1_.id = q2_.tag_id
ORDER BY
q0_.question ASC,
t1_.name ASC
Available data
INSERT INTO `question` (`id`,`question`) VALUES (1,'Who are you?');
INSERT INTO `questions_tags` (`question_id`,`tag_id`) VALUES (1,1);
INSERT INTO `questions_tags` (`question_id`,`tag_id`) VALUES (1,2);
INSERT INTO `questions_tags` (`question_id`,`tag_id`) VALUES (1,3);
INSERT INTO `tag` (`id`,`name`) VALUES (1,'personal');
INSERT INTO `tag` (`id`,`name`) VALUES (2,'jobs');
INSERT INTO `tag` (`id`,`name`) VALUES (3,'achievements');
Partial dump of getQuestions() method
Doctrine\ORM\PersistentCollection {#3131
-owner: AppBundle\Entity\Question {#3118
-id: 1
-question: "Who are you?"
-tags: Doctrine\ORM\PersistentCollection {#3131}
}
-coll: Doctrine\Common\Collections\ArrayCollection {#3127
-_elements: array:3 [
0 => AppBundle\Entity\Tag {#3121
-id: 1
-name: "personal"
}
1 => AppBundle\Entity\Tag {#3123
-id: 2
-name: "jobs"
}
2 => AppBundle\Entity\Tag {#3074
-id: 3
-name: "achievements"
}
]
}
}
Question entity
<?php
namespace AppBundle\Entity;
use AppBundle\Entity\Tag;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Question
*
* #ORM\Table(name="question")
* #ORM\Entity(repositoryClass="AppBundle\Entity\QuestionRepository")
*/
class Question
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="question", type="text")
*/
private $question;
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Tag", inversedBy="questions", cascade={"persist"})
* #ORM\JoinTable(name="questions_tags")
* #ORM\OrderBy({"name"="ASC"})
*/
private $tags;
public function __construct()
{
$this->tags = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set question
*
* #param string $question
* #return Question
*/
public function setQuestion($question)
{
$this->question = $question;
return $this;
}
/**
* Get question
*
* #return string
*/
public function getQuestion()
{
return $this->question;
}
/**
* Add tags
*
* #param \AppBundle\Entity\Tag $tags
* #return Question
*/
public function addTag(Tag $tags)
{
$this->tags[] = $tags;
return $this;
}
/**
* Remove tags
*
* #param \AppBundle\Entity\Tag $tags
*/
public function removeTag(Tag $tags)
{
$this->tags->removeElement($tags);
}
/**
* Get tags
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTags()
{
return $this->tags;
}
}
Tag entity
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Tag
*
* #ORM\Table(name="tag")
* #ORM\Entity(repositoryClass="AppBundle\Entity\TagRepository")
*/
class Tag
{
/**
* #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=128)
*/
private $name;
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Question", mappedBy="tags")
*/
private $questions;
public function __construct()
{
$this->questions = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Tag
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add questions
*
* #param \AppBundle\Entity\Question $questions
* #return Tag
*/
public function addQuestion(\AppBundle\Entity\Question $questions)
{
$this->questions[] = $questions;
return $this;
}
/**
* Remove questions
*
* #param \AppBundle\Entity\Question $questions
*/
public function removeQuestion(\AppBundle\Entity\Question $questions)
{
$this->questions->removeElement($questions);
}
/**
* Get questions
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getQuestions()
{
return $this->questions;
}
public function __toString()
{
return $this->name;
}
}
QuestionRepository
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\EntityRepository;
class QuestionRepository extends EntityRepository
{
/** #return Question[] */
public function getQuestions()
{
return $this->createQueryBuilder('q')
->select(['q', 't'])
->leftJoin('q.tags', 't')
->orderBy('q.question', 'ASC')
->getQuery()
->execute()
;
}
}
EDIT 2015-03-27:
For the time being I chose to extend the question entity with sort method:
<?php
// ...
class Question
{
// ...
/** #var boolean a flag to check if tags collection was sorted */
private $isTagsSorted = false;
// ...
/**
* Get tags
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getTags()
{
$this->sortTagsAlphabetically();
return $this->tags;
}
/** #return void */
private function sortTagsAlphabetically()
{
if ($this->isTagsSorted) {
return;
}
$tags = $this->tags->toArray();
usort($tags, function ($a, $b) {
return $a->getName() > $b->getName();
});
$this->tags = new ArrayCollection($tags);
}
}
You need a subquery to achieve this, because the order by affect the main query so obviously it will try to order first by question it does it and then try to order the questions by tag (not the tags). So something like this should do it :
SELECT
q0_.id AS id0,
q0_.question AS question1,
t1_.id AS id2,
t1_.name AS name3
FROM question q0_
LEFT JOIN questions_tags q2_ ON q0_.id = q2_.question_id
LEFT JOIN (select * from tag t1_ ORDER BY t1_.name ) t1_
ON t1_.id = q2_.tag_id
ORDER BY
q0_.question ASC,
t1_.name ASC
For the DQL i am sorry but i think you will have to do it the old fashion way NativeSql since doctrine doesnt support joining subqueries with dql :
https://groups.google.com/forum/#!msg/doctrine-user/0rNbXlD0E_8/xMNiQgp9c3QJ
But nativesql would be fine :) also :
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html
Just use the query i gave you, change it a bit to be readable then use :
$sql = "your query"
$connection = $this->getEntityManager()->getConnection();
$query = $connection->prepare($sql);
$query->execute();
$results = $query->fetchAll();
return $results;
The annotation of ordering is used only if the content is not already fetched, as example if you have fetch from the dm only the .. if you call the get.. method the result is sorted.
In your case, you get all the data in one shot, so the annotation doesn't work as expected.
In your case you can add a mehod in the Tag entity for sort the data on the fly, as example:
public function getSortedTags()
{
$criteria = Criteria::create()
->orderBy(array("name" => Criteria::ASC));
return $this->tags->matching($criteria);
}
Hope this help

Doctrine and join result type

I've 2 simple tables with many-to-one mono directional relations:
class Event extends BaseEvent
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\ManyToOne(targetEntity="Rposition")
* #ORM\JoinColumn(name="owner", referencedColumnName="id",onDelete="CASCADE", nullable=false )
**/
private $owner;
....
and the origin of the owner field class:
class Rposition
{
/**
* #var integer
*
* #ORM\Column(name="id", type="string", length=36)
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
*
*
* #ORM\Column(name="scenario", type="string", length=255, nullable=false)
*/
private $scenario;
both class having the right getter/setter and a __tostring()
I need to implements a query like this:
public function findAllByScenario($scenario) {
$q = $this->getEntityManager()->createQuery("SELECT e , r.scenario , r.id
FROM LapoMymeBundle:Event e
JOIN LapoMymeBundle:Rposition r
WITH e.owner = r.id
WHERE r.scenario = :scenario
ORDER BY e.start ASC, e.end ASC
")->setParameter('scenario', $scenario);
try {
return $q->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
-is it the right way to making a join and sending back result from it?
-what are the right way for fetching the fields from the array of objects?
something like that's:
$events=$this->getDoctrine()->getManager()
->getRepository('LapoMymeBundle:Event')->findAllByScenario($scenario);
$outputUsersArray = Array();
foreach($events as $event)
{
$eventArray = Array();
$eventArray[JSONResponseFields::KEY_ID] = $event->getId();
$eventArray[JSONResponseFields::KEY_NAME] = $event->getOwner()->getId();
$outputEventsArray[] = $eventArray;
} ....
rise an error likes:
FatalErrorException: Error: Call to a member function getId() on a non-object in.....
You can use Doctrine Query builder to get this working. Assuming you have Querybuilder instance. The query would look like
$qb = this->getDoctrine()->getRepository('BundleName:Event')->createQueryBuilder('e');
$query = $qb
->select('e','p')
->innerjoin('u.owner','r')
->where('r.scenario= :scenario')
->setParameter('scenario', $scenarioid)
->getQuery();
$chatuser = $query->getResult();

Symfony2-Doctrine -- Selecting data with WHERE from DoctrineArray

In an entity I have a field that looks like this:
/**
* #ORM\Column(type="array")
*/
protected $category;
and QueryBuilder
$qb = $this->createQueryBuilder('s');
$qb->select($fields)
->where( 's.category IN (:category)') //////////// <----
->orderBy('s.name', 'ASC')
->setParameter('category', $category_id);
So in database field category is Doctrine2 Array. I want to select records from database with QueryBuilder. My question is, how can i do this, with WHERE clause that will be checking fields from that array ?
A look here may help you
// Instead, use $qb->expr()->in('value', array('?1')) and bind your parameter to ?1 (see section above)
public function in($x, $y); // Returns Expr\Func instance
$qb->select($fields)
->where($qb->expr()->in('s.category', $categories))
#Cerad gave you a perfectly valid comment. One of the problem of storing arrays is that you don't have any chance of searching.
See PHP/MySQL - Storing array in database, and Storing arrays in the database. As you can see, it is a terrible practice.
The best way is to simply create a Category entity, and to have a OneToMany relation with that category.
Here is an example of an entity Book that has many categories:
1 Create your category entity:
class Category implements CategoryInterface
{
//.....
/**
* Title of the category
*
* #ORM\Column(type="string", length=100)
*/
protected $title;
/**
* Relation with your book entity for example
*
* #ORM\ManyToOne(targetEntity="Book", inversedBy="categories")
* #ORM\JoinColumn(name="book_id", referencedColumnName="id")
*/
private $book;
/**
* Set book
*
* #param BookInterface $book
*/
public function setBook(BookInterface $book)
{
$this->book = $book;
}
/**
* Get book
*
* #return BookInterface
*/
public function getBook()
{
return $this->book;
}
}
2 Your book entity:
use Doctrine\Common\Collections\ArrayCollection;
class Book implements BookInterface
{
/**
* Categories for the books
*
* #ORM\OneToMany(targetEntity="Category", mappedBy="book")
* #var CategoryInterface[]
*/
protected $categories ;
public function __construct()
{
$this->categories = new ArrayCollection();
}
/**
* Add Categories
*
* #param CategoryInterface $category
*/
public function addCategory(CategoryInterface $category)
{
$category->setBook($this);
$this->categories->add($category);
}
/**
* Remove Category
*
* #param CategoryInterface $category
* #return bool
*/
public function removeCategory(CategoryInterface $category)
{
return $this->categories->removeElement($category);
}
/**
* Get Categories
*
* #return Doctrine\Common\Collections\Collection
*/
public function getCategories()
{
return $this->categories;
}
/**
* Set Categories
*
* #param ArrayCollection $categories
*/
public function setCategories($categories) {
$this->categories->clear();
foreach ($categories as $category) {
$this->addCategory($category);
}
return $this;
}
3 Your can now search properly.

Resources