Can't extend Doctrine's Repository - symfony

I'm trying to make a custom Doctrine's ORM Repository and extend it but I can't find a way to make it work. So far this is what i have:
The original Repository
//AppBundle\Repository\LocaleRepository.php
namespace AppBundle\Repository;
use Doctrine\ORM\EntityRepository;
use JMS\DiExtraBundle\Annotation as DI;
class LocaleRepository extends EntityRepository
{
protected myCustomFunction(){
}
}
The extended Repository
//OfficeBundle\Repository\OfficeRepository.php
namespace OfficeBundle\Repository;
use AppBundle\Repository\LocaleRepository;
class OfficeRepository extends LocaleRepository
{
//Empty class
}
My entiy:
namespace OfficeBundle\Entity;
// some calls to traits
use Doctrine\ORM\Mapping as ORM;
/**
* Office
*
* #ORM\Table(name="office__office")
* #ORM\Entity(repositoryClass="OfficeBundle\Repository\OfficeRepository")
*/
class Office implements TranslatableInterface{
//...
}
And Finally the call:
$em = $this->getDoctrine()->getManager();
$this->getEntityManager();
$office=$em->getRepository('OfficeBundle:Office')->myCustomeFunction($slug);
This trows the exception:
Undefined method 'myCustomFunction'. The method name must start with either findBy or findOneBy!
If I place myCustomeFunction inside the OfficeRepository it works fine but it brings down the purpose of extendind the repository. Also, the repository loaded by the controller is the correct one, vardumping the class shows: 'OfficeBundle\Repository\OfficeRepository'.
Finally I'm using KNP DoctrineBehaviors(translatable) on the office entity.

You must make your method public if you are going to use it outside the repository class.
class LocaleRepository extends EntityRepository
{
public function myCustomFunction()
{
....
}
}

Related

Symfony 4 autowire DataTransformerInterface

I want to build a new form type to handle one of my problem.
But, using this code :
<?php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\DataTransformerInterface;
/**
* Entity hidden custom type class definition
*/
class EntityHiddenType extends AbstractType
{
/**
* #var DataTransformerInterface $transformer
*/
private $transformer;
/**
* Constructor
*
* #param DataTransformerInterface $transformer
*/
public function __construct(DataTransformerInterface $transformer)
{
$this->transformer = $transformer;
}
I got this error :
Cannot autowire service "App\Form\Type\EntityHiddenType": argument
"$transformer" of method "__construct()" references interface
"Symfony\Component\Form\DataTransformerInterface" but no such service
exists. Did you create a class that implements this interface?
I tried to put autowire to off, but I can't inject an interface right ?
Why I can't autowire this Symfony interface ?
If you have your DataTransformer in a own class (which implements DataTransformerInterface) you have to inject this class (your implementation) - not the interface.
see https://symfony.com/doc/current/form/data_transformers.html#using-the-transformer
you could of course aliasing the interface for your specific implementation - but then you only could have this one DataTransformer when injecting the Interface.
Because DataTransformerInterface is not autowirable.
Try this, to see autowiring classes/interfaces
bin/console debug:autowiring
The only way to make it work is to create a service class which implements DataTransformerInterface
Inject your new service by configuring it in service.yml

Symfony 3 - can't use custom Repository

I try to create default repository in my Symfony 3. First I created Repository class with method 'findByParentOrderedByName'. In next step I added in Entity line:
* #ORM\Entity(repositoryClass="AppBundle\Repository\ChildRepository")
Unfortunelly when I try to run findByParentOrderedByName() I get error
Undefined method 'findAllOrderedByName'. The method name must start with either findBy, findOneBy or countBy!
What I make incorrect?
Repository code:
<?php
namespace AppBundle\Entity;
/**
* Child
* #ORM\Entity(repositoryClass="AppBundle\Repository\ChildRepository")
*/
class Child
{
........
}
To use custom repository class properly, firstly repository class name must be defined in entity class.
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\ChildRepository")
*/
class Child
{
}
Then repository class created as like this:
namespace AppBundle\Repository;
use Doctrine\ORM\EntityRepository;
class ChildRepository extends EntityRepository
{
/**
* #return Child[]
*/
public function findAllOrderedByName()
{
return $this->getEntityManager()
->createQuery('SELECT * c FROM AppBundle:Child c ORDERED BY c.name ASC')
->getResult();
}
}

Attempted to load class "Stripe" from namespace "Stripe". Did you forget a "use" statement for another namespace?

Impossible to load Stripe classe in my Symfony controller see :
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Stripe\Stripe;
class PointsController extends Controller
{
/**
*
* #Route("/points/buy", name="points_buy")
*/
public function buyAction(Request $request)
{
\Stripe\Stripe::setApiKey('sk_test_');
return $this->render('points/buy.html.twig', [
]);
}
}
Stripe added with composer in vendor directory
I tried Stripe::setApiKey('sk_test_') but same error ...
Any idea?
If you're importing Stripe\Stripe in your use statement then I don't think you need the fully qualified class name.
use Stripe\Stripe;
//// etc.
/**
*
* #Route("/points/buy", name="points_buy")
*/
public function buyAction(Request $request)
{
Stripe::setApiKey($secretKey);
}
Here's a Stripe service I created for one of my projects.

One entity, two repositories in symfony

I would like use 2 repository for 1 entity.
The reason is : I have 2 bundles, both bundle use the same entity. I wish to separate both functionalities.
Sometimes I need specific queries into bundle.
It is possible to have 1 repository into a bundle and a second repository in the other one ?
Maybe it's a wrong way ?
If someone have an idea.
Thx !
2019 Update
I'd create 2 repositories. It makes no sense to add all methods to one repository, just because they share the entity. We could end up with 30 methods per repository this way.
First repository
namespace App\Repository;
use App\Entity\Post;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
final class FrontendPostRepository
{
/**
* #var EntityRepository
*/
private $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Post::class);
}
/**
* #return Post[]
*/
public function getAll(): array
{
// ...
}
}
...and 2nd repository
namespace App\Repository;
use App\Entity\Post;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
final class AdminPostRepository
{
/**
* #var EntityRepository
*/
private $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Post::class);
}
/**
* #return Post[]
*/
public function getUnpublished(): array
{
// ...
}
}
You can read more about this concept and whys in How to use Repository with Doctrine as Service in Symfony post
Well I don't really know it's a good practice but you can create a repository without linked entity (I mean, not with ORM annotation)
So I just create this in my service.yml :
renting.metadata.car:
class: Doctrine\ORM\Mapping\ClassMetadata
arguments: [ %car% ]
And this :
repair.repository.car:
class: carRepository
arguments: [#doctrine.orm.entity_manager, #renting.metadata.car]
That's works

Doctrine custom repository error

I've a brand new Symfony2 application and I'm 100% sure I've followed http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes to the letter. However I'm getting the following error;
Entity 'Core\MainBundle\Entity\LandingPromotions' has no field 'promotionType'. You can therefore not call 'findByPromotionType' on the entities' repository
I've no clue as to what I've missed. Code as follows;
LandingPromotions
<?php
namespace Core\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Core\MainBundle\Entity\LandingPromotions
*
* #ORM\Entity(repositoryClass="Core\MainBundle\Entity\PromotionRepository")
* #ORM\Table(name="landing_promotions")
*/
class LandingPromotions
{
//Normal entity stuff
}
PromotionRepository.php
namespace Core\MainBundle\Entity;
use Doctrine\ORM\EntityRepository;
class PromotionRepository extends EntityRepository
{
public function findByPromotionType($typeId)
{
}
}
Controller
namespace Core\MainBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Core\MainBundle\Entity\Game;
use Core\MainBundle\Entity\LandingPromotions as LandingPromotions;
class GameController extends Controller
{
/**
* #Route("{_locale}/games/")
* #Template()
*/
public function indexAction($_locale)
{
$lp_repo = $this->getDoctrine()->getRepository('CoreMainBundle:LandingPromotions');
$lp_repo->findByPromotionType(2);
}
}
After much hair pulling and cursing I discovered that the entities are not using PHP annotations, but rather the XML versions. How this got mixed up I've no idea, but that'll be tomorrow's issue.

Resources