How do I use Doctrine in a service container?
The Code just causes an error message "Fatal error: Call to undefined method ...::get()".
<?php
namespace ...\Service;
use Doctrine\ORM\EntityManager;
use ...\Entity\Header;
class dsdsf
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function create()
{
$id = 10;
$em = $this->get('doctrine')->getEntityManager();
$em->getRepository('...')->find($id);
}
}
services.yml
service:
site:
class: ...\Service\Site
According to your code, you already have an EntityManager injected. You don't need to call $em = $this->get('doctrine')->getEntityManager() — just use $this->em.
If you don't inject an EntityManager already, read this.
UPDATE:
You need to make the container inject an EntityManager into your service. Here's an example of doing it in config.yml:
services:
your.service:
class: YourVendor\YourBundle\Service\YourService
arguments: [ #doctrine.orm.entity_manager ]
I prefer to define bundles' services in their own services.yml files, but that's a bit more advanced, so using config.yml is good enough to get started.
For easily accessing the Entitymanager use the following one:
//services.yml
your service here:
class: yourclasshere
arguments: [#doctrine.orm.entity_manager]
And in the class itself:
class foo
{
protected $em;
public function __construct(\Doctrine\ORM\EntityManager $em)
{
$this->em = $em;
}
public function bar()
{
//Do the Database stuff
$query = $this->em->createQueryBuilder();
//Your Query goes here
$result = $query->getResult();
}
}
This is my first answer so any comments are appreciated :)
Please try this code:
$em=$this->container->get('doctrine')->getEntityManager();
$rolescheduels=$em->getRepository('OCSOCSBundle:RoleScheduel')->findByUser($user->getId());
For Symfony 3.x
The most easy-peasy solution for me was to just turn on autowiring/autoconfiguring, and then injecting the service I needed via the constructor. Note that I have also allowed any controller to be injected as a service by setting resource: '../../src/AppBundle/*'
#services.yml or config.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
# Allow any controller to be used as a service
AppBundle\:
resource: '../../src/AppBundle/*'
# you can exclude directories or files
# but if a service is unused, it's removed anyway
exclude: '../../src/AppBundle/{Entity,Repository,Tests,DataFixtures,Form}'
Then in any service, you can inject & use the entity manager $em (or any other service/controller) via the constructor like this:
// class xyz
private $em;
// constructor
public function __construct(\Doctrine\ORM\EntityManager $em) {
$this->em = $em;
}
public function bar() {
//Do the Database stuff
$query = $this->em->createQueryBuilder();
//Your Query goes here
$result = $query->getResult();
}
for anyone who works with symfony3: u need to do the following inside config/services.yml in order to use doctrine in Service Container:
servicename_manager:
class: AppBundle\Services\MyServiceClass
arguments: [ "#doctrine.orm.entity_manager" ]
in the Symfony 3.4. If you want to use Doctrine in a service you can do it:
Only this method worked for me
services.yml:
YourBundle\PatchService\YourService:
public: true
arguments: [ '#doctrine.orm.entity_manager' ]
Service:
class YourService
{
private $em;
public function __construct($em) {
$this->em = $em;
}
Controller:
use YourBundle\PatchService\YourService;
/**
* #Route("/YourController/",name="YourController")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$Notification = new YourService($em);
I am using Symfony 3.4. If you want to create a service in a bundle this works for me:
services:
Vendor\YourBundle\Service\YourService:
arguments:
$em: '#doctrine.orm.entity_manager'
In your Service.php
<?php
namespace Hannoma\ElternsprechtagBundle\Service;
use Doctrine\ORM\EntityManager;
use Hannoma\ElternsprechtagBundle\Entity\Time;
class TimeManager
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
}
Since 2017 and Symfony 3.3 you can register Repository as service, with all its advantages it has.
Your code would change like this.
1. Service configuration
# app/config/services.yml
services:
_defaults:
autowire: true
...\Service\:
resource: ...\Service
2. Create new class - custom repository:
use Doctrine\ORM\EntityManagerInterface;
class YourRepository
{
private $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(YourEntity::class);
}
public function find($id)
{
return $this->repository->find($id);
}
}
3. Use in any Controller or Service like this
class dsdsf
{
private $yourRepository;
public function __construct(YourRepository $yourRepository)
{
$this->yourRepository = $yourRepository;
}
public function create()
{
$id = 10;
$this->yourRepository->find($id);
}
}
Do you want to see more code and pros/cons lists?
Check my post How to use Repository with Doctrine as Service in Symfony.
Related
I am using laravel-repository pattern ,i have one api which is responsible for getting all users it's working fine ,if we are using that package by default search should support for that i set $fieldSearchable array in the repository class.
i hit an api like this localhost.com/api/lists?search=foo,it's not working can you please help me where did i mistake
UserController.php
public function __construct(UserRepositoryInterface $repository)
{
$this->repository = $repository;
}
public function getUsers(){
$data = $this->repository->show();
return response()->json(fractal($data, new UserTransformer()));
}
UserRepositoryInterface.php
interface UserRepositoryInterface extends RepositoryInterface
{
public function show();
}
UserRepository.php
<?php
namespace App\Repositories;
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Criteria\RequestCriteria;
use App\User as AppUser;
use App\UserSection;
use App\Validators\UserValidator;
use Illuminate\Support\Facades\DB;
/**
* Class UserRepositoryEloquent.
*
* #package namespace App\Repositories;
*/
class UserRepository extends BaseRepository implements UserRepositoryInterface
{
protected $fieldSearchable = ['phone_number'];
/**
* Specify Model class name
*
* #return string
*/
public function model()
{
return AppUser::class;
}
/**
* Boot up the repository, pushing criteria
*/
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
}
public function show(){
return $this->model()::get();
}
}
It maybe resolved by utilising pre-difined methods No need to write show() function logic because by default l5-Repository pattern contains some methods to get all the data all()or paginate().in your controller write like this in getUsers()
$data = $this->repository->all();
or
$data = $this->repository->paginate('25');
all() is for fetch all the data from DB and paginate($limit) is fetch the data per page based on the limit.
if you are using any one of the above mentioned method then automatically search functionality will work
I have custom service in Laravel:
<?php
namespace App\Library\Services;
class RegisterCustomerService
{
public function do()
{
return 'Output from DemoOne';
}
}
In which cases I should create provider for this service, when not?
Could I use RegisterCustomerService as composition in specific class like:
$c = new RegisterCustomerService();
Or am i obligated to create Provider?
Service providers are only necessary if the service needs custom configuration. You can typehint any class in the constructor and Laravel will try to resolve it to an instance.
An example service provider that configures a service with a config value is shown below:
class MyServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(MyCustomService::class, function ($app) {
return new MyCustomService(config('api_token'));
});
}
}
usage:
class ProjectController {
// Receives the service configured by the service provider above.
public function __construct(MyCustomService $service){
$this->service = $service;
}
}
More details about service providers: https://laravel.com/docs/5.8/providers
Below is the EmailNotifier Class
class EmailNotifier
{
public function notify()
{
echo 'Sending payment notification via email' ;
}
}
Below is my AppServiceProvider
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
}
public function register()
{
$this->app->make(App\EmailNotifier::class); // resolve the EmailNotifier Class
}
}
Below is billing class
class Billing
{
protected $notifier;
public function __construct(EmailNotifier $notifier)
{
$this->notifier = $notifier;
}
public function pay()
{
// Process the bill payment
$this->notifier->notify();
}
}
and in my controller I did
$data = new Billing(1);
As you can see I already resolve the EmailNotifier Class at the AppServiceProvider Class but when I call that like the code above, it throws an error said 'must be an instance of EmailNotifier'
and based on the laravel documentation, it's stated that :
you may "type-hint" the dependency in the constructor of a class that
is resolved by the container (for the automatic injection)
how do I achieve automatic injection for the type-hint in laravel ?
Use $data = resolve(Billing::class); instead of $data = new Billing(1); and you can remove $this->app->make(App\EmailNotifier::class); // resolve the EmailNotifier Class from service provider's register method.
I have a class to build a report about course registration in Laravel. Following is my class:
class Report {
protected $user;
protected $course;
protected $registration;
public function __construct(User $user, Course $course, Registration $registration) {
$this->user = $user;
$this->course = $course;
$this->registration = $registration;
}
public function build() {
// build report
}
}
Laravel will auto inject the instance of User, Course and Registration Models into Report.
If I need more other Model classes that should be used to build the report, I will need to add more arguments to the constructor of Report.
class Report {
protected $user;
protected $course;
protected $registration;
public function __construct(User $user, Course $course, Registration $registration, Another1 $another1, Another2 $another2, ... ) {
$this->user = $user;
$this->course = $course;
$this->registration = $registration;
}
public function build() {
// build report
}
}
Is this a correct way ?
Does have any other way to aggregate those classes that will be used in the Report class ? Should I use Facade Pattern to refactor it ?
Any help is appreciated.
If you really need that many Model injections it seems highly likely that you need to refactor your code and re-consider how a Report class is constructed.
Instead of Models, learn more about Repositories.
I recommend you also learn more regarding the Single Responsibility principle.
wiki
Since Laravel will inject new instances of these classes, you can consider doing this instead:
public function __construct()
{
$this->createInstances();
}
protected function createInstances()
{
$this->user = new User;
$this->course = new Course;
$this->registration = new Registration;
...
}
EDIT:
Or this to resolve any dependencies of these classes:
protected function createInstances()
{
$this->user = $this->app->make('User');
$this->course = $this->app->make('Course');
$this->registration = $this->app->make('Registration');
...
}
all.
For a Laravel project I'm working on, I've started to use Dependency Injection in order to mock classes in my tests. However, I've found that if I try to inject into a custom class with no explicit parent, two things are true:
The dependency injection works correctly when running the application
The injection fails when running tests in PHPUnit
Here is some sample code similar to what I'm using:
DemoController
// The controller we're testing
class DemoController extends Controller
{
// The injection and constructor
private $helpLayer1;
public function __construct(HelpLayer1 $helpLayer1)
{
$this->helpLayer1 = $helpLayer1;
}
...
// The test function I call
public function testDeps()
{
$this->helpLayer1->testLayer1();
}
}
HelperLayer1
// Our first helper class
class HelperLayer1
{
private $helpLayer2;
public function __construct(HelpLayer2 $helpLayer2)
{
$this->helpLayer2 = $helpLayer2;
}
...
// The testing function
public function testLayer1()
{
// When called via route, this dumps the actual object
// When called via test, this returns null
dd($this->helperLayer2);
}
}
Helper1ServiceProvider
class Helper1ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer1', function()
{
return new HelperLayer1(App::make('HelperLayer2'));
});
}
[OR]
public function register()
{
$this->app->bind('HelperLayer1', 'HelperLayer1');
}
}
Helper2ServiceProvider
class Helper2ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer2', 'HelperLayer2');
}
}
I'm relatively new to using DI, so I'm not entirely sure that this set-up is correct, but I'm at a loss.
Any help would be greatly appreciated! Thank you!