How can i convert three Doctrine queries to single one in symfony2 - php

I am doing this in my controller
$C100 = $em->getRepository('AcmeJunkieBundle:Junk')->findBy(array('type'=> 'C100'),array('day' => 'ASC'));
$C200 = $em->getRepository('AcmeJunkieBundle:Junk')->findBy(array('type'=> 'C200'),array('day' => 'ASC'));
$C300 = $em->getRepository('AcmeJunkieBundle:Junk')->findBy(array('type'=> 'C300'),array('day' => 'ASC'));
'type' is just string field
IS there any way to do that in single query and then do something like
$C100 = $result['C100']
$C200 = $result['C200']
$C300 = $result['C200']

We need to know about your Junk entity: is type just a string field?
Anyway you may write your own repository methods in associated repository class: your Junk class source will be something like this I assume:
src/Acme/JunkieBundle/Entity/Junk.php
namespace Acme\JunkieBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="Acme\JunkieBundle\Repository\JunkRepository")
* #ORM\Table(name="junk")
*/
class Junkie{ ... }
Make sure you have an annotation with the repository class name, then write up that class - the one being fetched by $C100 = $em->getRepository() method in the controller.
src/Acme/JunkieBundle/Repository/JunkRepository.php
namespace Acme\JunkieBundle\Repository;
use Doctrine\ORM\EntityRepository;
class JunkRepository extends EntityRepository
{
public function findByTypes(array $types)
{
//we build our query here
$qb = $this -> createQueryBuilder();
$query = $qb -> where( $qb -> expr() -> in ('type', $types) )
-> getQuery();
return $query -> getResults();
}
}
Now you may call
$em->getRepository('AcmeJunkieBundle:Junk')->findByTypes(array('C100', 'C200', 'C300'))
in your controller.
Be sure to check Doctrine docs.

you can do just :
$em->getRepository('AcmeJunkieBundle:Junk')
->findBy(array('type'=> array('C100', 'C200', 'C300')),array('day' => 'ASC'));
;) thanks

Related

Symfony3 repository method doesn't work

I'm trying to call a method in the repository ArticleRepository from my controller ArticleController. However it says :
Undefined method 'afficheArticle'. The method name must start with either findBy or findOneBy!
my Entity Article : (Entity\Article.php)
/**
* Article
*
* #ORM\Table(name="Article", indexes={#ORM\Index(name="I_FK_Article_TypeArticle", columns={"idTypeArticle"})})
* #ORM\Entity(repositoryClass="erp-gkeep\new_erp\gkeepBundle\Repository\ArticleRepository")
*/
class Article
{
my ArticleController (Controller\ArticleController)
/**
* #Route("viewArticle2", name="viewArticle2")
*/
public function listAction2()
{
$data = $this->getDoctrine()->getRepository('gkeepBundle:Article')->afficheArticle();
my ArticleRepository
<?php
/**
* Created by PhpStorm.
*/
namespace gkeepBundle\Repository;
use Doctrine\ORM\EntityRepository;
class ArticleRepository extends EntityRepository
{
public function afficheArticle(){
$em=$this->getEntityManager();
$query = $em->createQuery(
'SELECT a.reference, a.designationfr, a.designationen, a.plan, a.url, a.datecreation, a.idtypearticle
FROM gkeepBundle:Article a
'
);
$articles = $query->getArrayResult();
return $articles;
}
}
if someone can help me please ! I'm pretty sure it's a stupid error :/
The value of repositoryClass in your mapping annotation needs to be the namespace + class name of your repository, it looks like you've maybe added some of the directory structure as well. - actually isn't a valid character in a PHP namespace, so the value you've got now definitely isn't right.
Try
#ORM\Entity(repositoryClass="gkeepBundle\Repository\ArticleRepository")
For reference: when this classname is not valid, Doctrine falls back to the default repository - this is what's throwing the error you're seeing.

Table objects used Cake\ORM\Table instead of a concrete class: How to fix?

I have this warning in my CakePHP logs:
The following Table objects used Cake\ORM\Table instead of a concrete
class:
Jobs
Here is my controller class:
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\ORM\TableRegistry;
/**
* Jobs Controller
*
* #property \App\Model\Table\JobsTable $Jobs
*/
class JobsController extends AppController
{
public $name = 'Jobs';
/**
* Index method
*
* #return void
*/
public function index()
{
//Set Query Options
$options = array(
'order' => array('Jobs.created' => 'desc'),
'limit' => 1
);
//Get Jobs info
$getjobs = TableRegistry::get('Jobs');
$jobs = $getjobs->find('all',$options);
$this->set('jobs',$jobs);
}
}
Is there another/better way to access my db and read data from it?
I'm using latest version of CakePHP.
It's my first time using it, so I would like to know if there is a better way to do this MySQL interaction.
Inside of src/Model/Table/, define a class named JobsTable.php:
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
class JobsTable extends Table
{
// ... Jobs Table logic defined here
}
This should build your Table object from TableRegistry::get() with this class rather than the delegated Cake class.
You can learn more about building Table objects in CakePHP 3.x here:
CakePHP 3.x Table Objects

How to query database data with Doctrine and Symfony

I have a line like this
// $repository is my repository for location data
$locationObject = $repository->findOneBy(array('name' => $locationName));
Which selects the first record it can find from the Locations table. Which is fair enough.
However, I have some additional data in that table to make the query more precise. Specifically, an "item_name" column. In the Location class it is specified as such:
/**
* #ORM\ManyToOne(targetEntity="Item", inversedBy="locations", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="item_id", referencedColumnName="item_id", onDelete="CASCADE")
*/
protected $item;
So there is also an Item table with item_id, item_name, etc.
What I want to do is change the original findOneBy() to also filter by item name. So I want something like:
$locationObject = $repository->findOneBy(array('name' => $locationName, 'item' => $itemName));
But because $item is an object in the Locations class rather than a string or an ID obviously that wouldn't work. So really I want to somehow much against item->getName()...
I'm not sure how I can do this. Does anyone have any suggestions?
Thanks
I guess you must create a custom query with join. It's better you create a custom repository class for this entity and then creates a custom query build inside it.
Entity:
// src/AppBundle/Entity/Foo.php
/**
* #ORM\Table(name="foo")
* #ORM\Entity(repositoryClass="AppBundle\Repository\FooRepository")
*/
class Foo
{
...
}
Your repository:
// src/AppBundle/Repository/FooRepository.php
use Doctrine\ORM\EntityRepository;
class FooRepository extends EntityRepository
{
public function findByYouWant($id)
{
// your query build
}
}
Controller:
// src/AppBundle/Controller/FooController.php
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class FooController extends Controller
{
public function showAction()
{
// ... your code
$locationObject = $repository->findByYouWant($id);
}
}
You should add a method to your Location repository class, and create a query similiar to the one below:
class LocationRepository extends EntityRepository
{
public function findLocationByItemName($locationName, $itemName)
{
$qb = $this->createQueryBuilder('location');
$qb->select('location')
->innerJoin(
'MyBundle:Item',
'item',
Query\Expr\Join::WITH,
$qb->expr()->eq('location.item', 'item.item_id')
)
->where($qb->expr()->like('location.name', ':locationName'))
->andWhere($qb->expr()->like('item.name', ':itemName'))
->setParameter('locationName', $locationName)
->setParameter('itemName', $itemName);
$query = $qb->getQuery();
return $query->getResult();
}
}
You have to use a custom dql.You can construct it using the querybuilder.
//in your controller
protected function getEntities($itemName){
$em = $this->get('doctrine.orm.default_entity_manager');
$qb = $em->createQueryBuilder();
$qb->select('a')->from('YourBundleAlias:YourEntityName', 'a')->join('a.item','b')->where('b.item = :item')->setParameter('item', $itemName);
return $qb->getQuery()->execute();
}
This is as easy as:
$locationObject = $repository->findOneBy(array(
'name' => $locationName,
'item' => $itemObject
));
Using Doctrine2 in order to do a findBy on a related entity field you must supply an entity instance: $itemObject.

Symfony2 : Repository Class not found

Today I stuck in Repository Class Function I got this error
Undefined method 'test'. The method name must start with either findBy or findOneBy!
I allready checked these solutions -
Solution 1
Solution 2
Solution 3
Is anything I need to add into config file ?
This is my Entity Class
// src/Foo/NewsBundle/Entity/News.php
namespace Foo\NewsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* News
* #ORM\Entity(repositoryClass="Foo\NewsBundle\Repository\NewsRepository")
* #ORM\Table(name="news")
* #ORM\HasLifecycleCallbacks()
*/
class News
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $title;
This is my repository Class
// Foo/NewsBundle/Repository/NewsRepository.php
namespace Foo\NewsBundle\Repository;
use Doctrine\ORM\EntityRepository;
Class NewsRepository extends EntityRepository
{
public function test()
{
return "Nisarg";
}
}
And I am calling this test() function this wat from the controller
public function indexAction()
{
// $news = $this->getDoctrine()
// ->getRepository('FooNewsBundle:News')
// ->findAll();
$em = $this->getDoctrine()
->getManager();
$news = $em->getRepository('FooNewsBundle:News')->test();
if (!$news) {
throw $this->createNotFoundException('No news found');
}
$build['news'] = $news;
return $this->render('FooNewsBundle:Default:news_show_all.html.twig', $build);
}
Check if you have specified your repository class in your News orm config file.
There must be somthing like "repositoryClass: Foo\NewsBundle\Repository\NewsRepository"
And don't forget to clear cache!
In your entity you are not using annotation, check if you have a news.yml file in Resources/config/doctrine
I think the standard for repository classes is to put it in a subdirectory of the entity folder and still use the same entity namespace. Yours used a different namespace which is why I think you have the error.
According to the cookbook this is how the entity and custom respistory are defined.
link to custom repository class in the cookbook.
Entity
// src/Acme/StoreBundle/Entity/Product.php
namespace Acme\StoreBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="Acme\StoreBundle\Entity\ProductRepository")
*/
class Product
{
//...
}
Repository:
// src/Acme/StoreBundle/Entity/ProductRepository.php
namespace Acme\StoreBundle\Entity;
use Doctrine\ORM\EntityRepository;
class ProductRepository extends EntityRepository
{
public function findAllOrderedByName()
{
return $this->getEntityManager()
->createQuery(
'SELECT p FROM AcmeStoreBundle:Product p ORDER BY p.name ASC'
)
->getResult();
}
}
Fedor Petrick is right!
You should look for the orm file that corresponds to the entity.
In my case, I have created a custom repository named: OfertaRepository.php in the folder OfertaBundle\Entity
On the other hand, I have a file Oferta.orm.xml
In line three , It said :
<entity name="OfertaBundle\Entity\Oferta" table="oferta">
But it should be :
<entity name="OfertaBundle\Entity\Oferta" table="oferta" repository-class="OfertaBundle\Entity\OfertaRepository">
Now, the method in the OfertaRepository.php works well!
Your code look correct in the Entity and Repository. Perhaps you could try to call the getRepository directly without ->getManager.
$this->getDoctrine->getRepository('FooNewsBundle:News')->test();
If you need a specific field you should have a look at the short notations with findOneBy and findBy in most cases its much easier instead of writing a custom class.
http://symfony.com/doc/current/book/doctrine.html
Are you in production ? Perhaps clearing your cache is the solution :
php app/console cache:clear --env=prod --no-debug
If clearing your cache doesn't work, is $em->getRepository('FooNewsBundle:News') instanceOf Foo\NewsBundle\Repository\NewsRepository true or false? By the looks of things, your not getting the correct repository somehow?
have you generated the entities?
php app/console doctrine:generate:entities BUNDLENAME
launch this command and then retry your code

Symfony2 Doctrine Custom Repository Class [Semantical Error] line 0, col 14 near 'Project p': Error: Class 'Project' is not defined

I'm really new in Symfony 2 and Doctrine, and have a simple problem:
There is a pretty simple code in my repository:
<?php
namespace BakeryIT\BakeryBundle\Entity;
use Doctrine\ORM\EntityRepository;
class ProjectRepository extends EntityRepository
{
public function findHistory(){
return $this->getEntityManager()
->createQueryBuilder()
->select('p')
->from('Project','p')
->getQuery()
->getResult();
}
}
And two simple functions in my controller:
<?php
namespace BakeryIT\BakeryBundle\Controller;
/*
...
*/
class ProjectController extends Controller
{
public function indexAction()
{
return $this->index('Project', 'findHistory');
}
}
And Controller looks like this:
public function index($entity, $query = 'findAll')
{
$repository = $this->getDoctrine()
->getRepository('BakeryBundle:'.$entity);
$data = $repository->$query();
return $this->render('BakeryBundle:'.$entity.':index.html.twig',
array('data' => $data));
}
This code throw me the Semantical Error [Semantical Error] line 0, col 14 near 'Project p': Error: Class 'Project' is not defined.
On the other hand everything works perfectly if I change this line in my repository:
->from('Project','p')
to
->from('BakeryIT\BakeryBundle\Entity\Project','p')
I don't know why this example doesn't work in the first case.
Namespace in my BakeryIT\BakeryBundle\Entity\Project is set in this way:
namespace BakeryIT\BakeryBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Project
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="BakeryIT\BakeryBundle\Entity\ProjectRepository")
*/
class Project
{
/*
..
*/
}
In order to use the short form, you'll need to provide the bundle name too. This is constructed from the vendor and bundle name. In your case it would be something like:
from('BakeryITBakeryBundle:Project')
See the following link for more information on bundles:
http://symfony.com/doc/current/cookbook/bundles/best_practices.html
On my local system I could use
$entityManager->createQuery('DELETE FROM BellaShopBundle:cache c WHERE c.expires < :now')->setParameter('now', $date);
But on production it was necessary to capitalise the entity or class name, which I guess I was thinking of as the table name, thus:
$entityManager->createQuery('DELETE FROM BellaShopBundle:Cache c WHERE c.expires < :now')->setParameter('now', $date);

Categories