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.
Related
Thanks to the symfony doc https://symfony.com/doc/current/doctrine.html#updating-an-object, i am able to use get/set methods from my entity called 'Produit'.
But when i call the method setProduit() (from Paniers entity) Phpstorm say "expected App\Entity\Paniers, got Object" for the $produitSelected.
i don't know why phpstorm say that because i'm able to use methods, what's the problem ?
find() return an entity object, right ?
class PaniersController extends AbstractController
{
/**
* #Route("/paniers/add/{id}", name="paniers.add")
*/
public function addPanier(Request $request, Environment $twig, RegistryInterface $doctrine, $id)
{
$produitSelected = $doctrine->getRepository(Produit::class)->find($id);
if (!$produitSelected) {
throw $this->createNotFoundException(
'Pas de produit trouvé pour l\' id : '.$id
);
}
$lignePanier=$doctrine->getRepository(Paniers::class)->findOneBy(['produit' => $produitSelected, 'user' =>$this->getUser()]);
if($produitSelected->getStock()>0){
if ($lignePanier){
$quantite =$lignePanier->getQuantite();
$lignePanier->setQuantite($quantite+1);
} else {
$lignePanier = new Paniers();
$lignePanier->setUser($this->getUser())
->setDateAjoutPanier(new \DateTime(date('Y-m-d')))
->setQuantite(1)
->setProduit($produitSelected);
}
$doctrine->getManager()->persist($lignePanier);
$produitSelected->setStock($produitSelected->getStock()-1);
$doctrine->getManager()->persist($produitSelected);
$doctrine->getManager()->flush();
}
}
}
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\PaniersRepository")
* #ORM\Table(name="paniers")
*/
class Paniers
{
//...
/**
* #ORM\ManyToOne(targetEntity="Produit")
* #ORM\JoinColumn(name="produit_id", referencedColumnName="id")
*/
private $produit;
public function getProduit(): ?Produit
{
return $this->produit;
}
public function setProduit(?Produit $produit): self
{
$this->produit = $produit;
return $this;
}
}
In addition to Denis V's correct answer, I want to add that you could also modify your controller like this:
public function addPanier(Request $request, Environment $twig, RegistryInterface $doctrine,ProduitRepository $produitRepository, $id)
{
$produitSelected = $produitRepostiory->find($id);
//rest of the code
}
This way phpstorm also knows the type of the returned object, as every returned object is type hinted in the corresponding repository.
PhpStorm is apparently not that smart to understand that the actual type of the return value of find($id) in this case will be Produit. But you can help it:
/** #var Produit $produitSelected */
$produitSelected = $doctrine->getRepository(Produit::class)->find($id);
To make it working you should either use Produit with the full namespace or add the namespace directly within the type hint.
Of course this doesn't guarantee or ensure that the actual type will be Produit. So, if you make a mistake, PhpStorm will report the type incorrectly.
You first need to fix code :
Don't inject $id, you only need to typehint your entity: https://symfony.com/doc/current/best_practices/controllers.html#using-the-paramconverter
Don't inject $doctrine, use $em = $this->getDoctrine()->getManager();
Don't inject $twig, use return $this->render('...template', []);
Use English, it is always the rule. Not only other people could help you but also because Symfony understands it and you will need that when you start using form collections: https://symfony.com/doc/current/form/form_collections.html
Inject repository and you will have autocomplete and spot errors easier. Use ```make:entity`` command and you will see what I think, hard to explain.
i'm new on doctrine orm so i try to learn some tutorial on
ps:knpuniversity.com/screencast/doctrine-queries/dql
but i still confused for exp:
src/AppBundle/Entity/Category.php
class Category
{
private $id;
private $name;
private $iconKey;
private $fortuneCookies;
We can access build in method by
$categoryRepository = $this->getDoctrine()
->getManager()
->getRepository('AppBundle:Category');
$categories = $categoryRepository->findAll();
But if we want to access new method we can do this
$categoryRepository = $this->getDoctrine()
->getManager()
->getRepository('AppBundle:Category');
$categories = $categoryRepository->findAllOrdered();
Then provide class for repository
src/AppBundle/Entity/CategoryRepository.php
class CategoryRepository extends EntityRepository
{
public function findAllOrdered()
{
die('this query will blow your mind...');
}
}
i still not get it!!
$categoryRepository = $this->getDoctrine()
->getManager()
->getRepository('AppBundle:Category');
if those above point to category entity, how come it suddenly can link to CategoryRepository and we could access findAllOrdered() method?
did i missed something guys please help?
As I understood you are using annotations and most probably you have an annotation of the entity class. You just have to specify the repository class like this:
/**
* #ORM\Entity(repositoryClass="AppBundle\Entity\CategoryRepository")
* #ORM\Table(name="Category")
*/
Specify
As several developers told you, it's important to link your Entity class with your Repository class through the annotations.
#ORM\Table(name="your_entity_name")
#ORM\Entity(repositoryClass="Your_RepositoryClass")
If you want to call your repository with a name more customized (e.g. 'repository.category' instead of 'AppBundle:Category'), you can create a service through a yml file.
I'm using doctrine Doctrine MongoDB ODM 1.0.3. When trying to update document using doctrine I'm getting the following error:
Class XXX is not a valid document or mapped super class.
I have the following class for the document:
<?php
namespace Documents;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/**
* #ODM\Document(collection="posts")
*/
class Posts
{
/** #ODM\Id */
private $id;
/** #ODM\Field(type="string") */
private $title;
/** #ODM\EmbedMany(targetDocument="Comment") */
private $comments = array();
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function addComment($comment)
{
$this->comments[] = $comment;
}
public function getComments()
{
return $this->comments;
}
}
The following code is used to add new document:
$post = new \Documents\Posts();
$post->setTitle( $_POST['title'] );
$dm->persist($post);
$dm->flush();
Later I want to update the added document to add new comment for example. I use the following code:
$comment = new \Documents\Comment($_POST['comment_text']);
$dm->createQueryBuilder('Posts')
->update()
->field('comments')->push($comment)
->field('_id')->equals(new \MongoId($_POST['id']))
->getQuery()
->execute();
but getting the above mentioned error.
As you stated in your own answer you need to provide fully qualified name of class. Just wanted to add that better than to pass the string it is to use static class property like this instead: createQueryBuilder(\Documents\Posts::class); It works much better with IDEs (autocompletion, refactoring etc...)
For people getting this error in PHP 8 and above, check that you are not mixing annotations (e.g. /** #Entity */) and attributes (e.g. #[Entity]), and that you have indicated which method you are using in your config:
mappings:
App:
# pick one:
type: annotation
type: attribute
This always trips me up when I start a new project and the config defaults to annotations when I'm used to using attributes.
In case anyone else have a similar problem, you need to pass fully qualified class name to createQueryBuilder. My document classes are all inside Documents namespace so after passing it like this createQueryBuilder('\Documents\Posts') the problem is solved.
Based on the other varying answers here, it seems this error isn't super precise.
In my case the class was missing the EmbeddedDocument annotation.
namespace Foo;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/**
* #ODM\EmbeddedDocument
*/
class Bar { }
I am trying to resolve class via __construct using Laravel's bind() method.
Here what I do:
routes.php (of course I will move it away from here)
// Bindings
App::bind(
'License\Services\ModuleSelector\SelectorInterface',
'License\Services\ModuleSelector\ModuleSelector'
);
SelectorInterface.php - interface that I will expect in __construct method.
<?php namespace License\Services\ModuleSelector;
interface SelectorInterface {
/**
* Simply return query that will select needle module fields
*
* #return mixed
*/
public function make();
}
ModuleSelector.php - this is class that I want to resolve via Laravel's DI (see example below).
<?php namespace License\Services\ModuleSelector;
use License\Services\ModuleSelector\Selector;
class ModuleSelector extends Selector
{
/**
* Get module by it's code
*
* #return mixed
*/
public function find()
{
return $this->make()
->where('code', $module_code)
->first();
}
}
Module.php
<?php namespace License\Services\ModuleType;
use License\Services\ModuleType\TypeInterface;
use License\Services\ModuleSelector\SelectorInterface;
class Module
{
...
function __construct(SelectorInterface $selector)
{
$this->selector = $selector;
}
...
}
And the place when error occurs:
In my repo I have use License\Services\ModuleType\Module as ModuleService;.
Than there is method called find():
/**
* Find module by its code with all data (types, selected type)
* #return mixed
*/
public function find($module_code)
{
$module = new ModuleService;
// Get module id in order to use build in relations in framework
$module = $this->module->find($module_code);
...
}
So, in other words, I have 2 classes and one interface. What I am trying to do is:
1) Create Class1.php / Class2.php / Class2Interface.php.
2) In Class1.php in the __construct I specify __construct(Class2Interface $class2).
3) Instantiate Class2.
What I am doing wrong? Examples found here.
In this line:
$module = new ModuleService;
You are directly invoking the Module class and not passing in an instance of SelectorInterface.
For the IoC to work you bind and make classes using it. Try that line again with :
$module = App::make('License\Services\ModuleSelector\SelectorInterface');
An alernative is to inject it directly into your repos constructor, as long as the repo is created by the IoC container, your concrete will be automatically injected.
Nowhere do you have a class marked to actually "implement SelectorInterface".
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