I have a Timesheet.php class in Symfony2, and i need, in this class, use for example :
$this->getDoctrine()->getRepository()->find();
$this->getDoctrine()->getManager()->remove();
How can i do that ? I have try to call the class as a service, manually add variable in constructor and other but no effect...
Do you have a good solution ?
This is because $this->getDoctrine() is method of Symfony\Bundle\FrameworkBundle\Controller class. When you check this method there is $this->container->get('doctrine') so what you need is having doctrine available in your Timesheet class. To do so, define your Timesheet class as a service:
your.service_id:
class: Acme\DemoBundle\Timesheet
arguments: [#doctrine]
Then your Timesheet class:
use Doctrine\Bundle\DoctrineBundle\Registry;
class Timesheet
{
/**
* #var Registry
*/
private $doctrine;
/**
* #param Registry $doctrine Doctrine
*/
public function __construct(Registry $doctrine)
{
$this->doctrine = $doctrine;
}
public function yourMethod()
{
//this is what you want to achieve, right?
$this->doctrine->getManager()->remove();
$this->doctrine->getRepository()->find();
}
}
Related
I'm using JMSSerializerBundle in my entities definition, and RestBundle's annotations in controllers.
I have an entity with public and admin-protected attributes, let's say
use JMS\Serializer\Annotation as Serializer;
class UserAddress {
/**
* #Serializer\Expose
* #Serializer\Groups(groups={"address:read"})
*/
private $nonSecretAttribute;
/**
* #Serializer\Expose
* #Serializer\Groups(groups={"address:admin-read"})
*/
private $secretAttribute;
}
and a User like :
class User {
// ...
/**
* #ORM\OneToMany(targetEntity="UserAddress", mappedBy="user")
*/
private $addresses;
and my controller looks like
use FOS\RestBundle\Controller\Annotations as Rest;
class UsersController {
/**
* #Rest\Get("/users/{user}/addresses", requirements={"user"="\d+"})
* #Rest\View(serializerGroups={"address:read"})
* #IsGranted("user_read", subject="user")
*/
public function getUsersAddresses(User $user)
{
return $user->getAddresses();
}
}
but how could I add the address:admin-read to the serializer groups here if the logged in user happens to have the ADMIN_ROLE role ?
Is that possible in the #Rest\View annotation ?
Do I have a way to modify the groups in the controller's method, inside a conditional loop verifying my logged in user's roles ?
You should instantiate the fos-rest View manually and add a Context. On that Context you can set the serialization groups at runtime by evaluating the users roles.
Something like this should work:
use FOS\RestBundle\View\View;
use FOS\RestBundle\Context\Context;
class UsersController
{
public function getUsersAddresses(User $user): View
{
$isAdmin = in_array('ROLE_ADMIN', $user->getRoles());
$context = new Context();
$context->setGroups($isAdmin ? ['address:admin-read'] : ['address:read']);
$view = VVV::create()->setContext($context);
return $view
->setContext($context)
->setData($user->getAddresses());
}
}
I would like to know how to extend a custom repository and call the extended repository from doctrine entity manager in doctrine.
My Entity class :
/**
* #ORM\Entity(repositoryClass="Vendor\MyBundle\Repository\MyEntityRepository")
*/
class MyEntity
{
...
My Entity Repository class:
class MyEntityRepository extends EntityRepository
{
...
My Extended Repository class:
class MyExtendedEntityRepository extends MyEntityRepository
{
...
Call of MyEntityRepository:
class MyEntityManager
{
protected $emr;
/**
*
* #return MyEntityRepository
*/
public function getRepository()
{
return $this->emr->getRepository('MyVendorBundle:MyEntity');
}
...
Call of MyExtendedEntityRepository?
class MyOtherEntityManager
{
protected $emr;
/**
*
* #return MyExtendedEntityRepository
*/
public function getRepository()
{
//This is what i want to know: How to access to the extended repository?
}
...
Thanks
You can't, doctrine getRepository() works with the entity and resolve the repository related. I does not understand what is the logical or use case, but if you need reuse some part of repository throw other entities its recommended the use of traits. In the other hand if you really need use that scenario you can simply build MyExtendedEntityRepository in the getRepository method.
/**
*
* #return MyExtendedEntityRepository
*/
public function getRepository()
{
$class = $this->emr->getClassMetadata(MyEntity::class);
return new MyExtendedEntityRepository($this->emr, $class);
}
I always use doctrine from controllers or from entity repository classes, now I am trying to use it from a static class but I can't find any example on how to do id.
Basically I'd need (I think) a way to create the entity manager in a static method.
thanks
M
You may call a setter function, injecting entity manager, where you call the static method:
MyController
Class MyController extends Controller
{
public function newAction()
{
$entityManager = $this->getDoctrine()->getManager();
SomeClass::setEntityManager($entityManager);
$result = SomeClass::myStaticMethod();
}
}
SomeClass
Class SomeClass
{
private static $entityManager;
public static function setEntityManager($entityManager)
{
self::$entityManager = $entityManager;
}
public static function myStaticMethod()
{
return $entityManager->getRepository(SomeEntity::class)->findAll();
}
}
I'm not sure from your question what you mean by static class/method, some code example might help. But you could declare this class as a service, which it sounds like it might be meant to be anyway, and then inject the entity manager as a dependency.
services.yml
services:
my_service:
class: Acme\AppBundle\Services\MyService
arguments: ["#doctrine.orm.entity_manager"]
Then in your class you will have the entity manager available like this:
<?php
namespace Acme\AppBundle\Services;
use Doctrine\ORM\EntityManager;
class MyService
{
/**
* Entity Manager
*
* #var Doctrine\ORM\EntityManager
*/
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
...
}
And you can then use this service in your controllers like so:
$this->get('my_service')->doSomething();
I am new at symfony and trying to create REST api using FOSRest Bundle. Also i want to use flysystem library as service in my controllers. It is simple as that
class FileController extends FOSRestController
{
public function getFilesAction()
{
$filesystem = $this->container->get('oneup_flysystem.application_filesystem');
...
}
}
This works fine, but my idea is to Inject this service into FileController so i can use $filesystem service in every method in my controller.
I read about it, that I have to make my controller as service, but then something went wrong. What is the proper way to make this injection.
We use something like this:
YourBundle/Resources/config/services.yml
controller.file:
class: YourBundle\Controller\FileController
arguments:
- #yourFileService
- #service_container
YourBundle/Controller/FileController.php
/**
* #Route("/file", service="controller.file")
*/
class FileController extends Controller
{
/**
* #var Filesystem
*/
private $filesystem;
/**
* #param Filesystem $filesystem
* #param $container
*/
public function __construct(
Filesystem $filesystem,
$container
) {
$this->filesystem = $filesystem;
$this->container = $container;
}
All of my query in Entity Repository needs to be filtered by user.
Now I want to know how can I access the currently logged in user in Entity Repository directly.
What I did today is to get the currently logged in user in my controller, through the use of $this->getUser() and then pass it to Entity Repository and this is not efficient.
You need to inject security.token_storage service into another one to get the current user, but as of Repository classes belong to Doctrine project, not Symfony, it is not recommended to do this.. May be there is a way to achieve it by creating custom entityManager class as described here, but I don't think it would a good solution..
Instead of customizing an entityManager better create a service which calls repository classes' methods, inject desired services into it.. Let Repository classes do their job.
Implementation would be something like this:
RepositoryClass:
class MyRepository extends EntityRepository
{
public function fetchSomeDataByUser(UserInterface $user)
{
// query
}
}
Service:
class MyService
{
private $tokenStorage;
public function _construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
// other services
}
public function getSomeDataByUser()
{
$user = $this->tokenStorage->getToken()->getUser();
return $this->entityManager->getRepository(MyREPOSITORY)->fetchSomeDataByUser($user);
}
}
Usage:
public function someAction()
{
$dataByUser = $this->get(MYSERVICE)->getSomeDataByUser();
}
If you use JMSDiExtraBundle it can be done by adding setter injection:
use Doctrine\ORM\EntityRepository;
use JMS\DiExtraBundle\Annotation as DI;
class YourRepository extends EntityRepository
{
/** #var User current user entity */
protected $user;
/**
* #DI\InjectParams({
* "token_storage" = #DI\Inject("security.token_storage")
* })
*/
public function setSimplaManager(TokenStorageInterface $tokenStorage)
{
$token = $tokenStorage->getToken();
if (!is_object($user = $token->getUser())) {
// e.g. anonymous authentication
return;
}
$this->user = $user;
}
}