Why Repository interface bind to service container - laravel

We need to use Repository in laravel application. We want create Two important things one is Repository Interface and another one Repository class
My doubt is Why Repository interface and Repository class register to service provider
I removed repository interface and class from service provider
show below error
"Target [App\Repository\UserInterface] is not instantiable while building "
<?php
namespace App\Repository\user;
use Illuminate\Support\ServiceProvider;
class UserRepoServiceProvide extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
// $this->app->bind('App\Repository\UserInterface', 'App\Repository\user\UserRepository');
}
}

An Interface class is just a definition of methods (without their body), hence is not instantiable. That means you can't do a new App\Repository\UserInterface().
Somewhere in your code you have a method (or maybe a constructor?) that takes a UserInterface dependency, something like
public function myMethod(UserInterface $repository) {
...
}
// or
public function __construct(UserInterface $repository) {
...
}
If you remove the binding, Laravel will try to instantiate an UserInterface and that will result in the error you get.
When working with interfaces you have always to bind() them with concrete classes.
I have a question, why did you remove the binding from ServiceProvider?

Related

Customize a trait class with AliasLoader::getInstance()?

I have a core trait class. This is integrated into core controllers and various independent modules (nwidart).
How is it possible to add or override functionality to a trait class? Without adjusting the controllers where the traits are integrated?
The goal is to override an existing trait function and I've tried that with "AliasLoader" so far, unfortunately so far without success.
namespace Modules\MyModule\Providers;
class Main extends Provider
{
public function register()
{
$loader = AliasLoader::getInstance();
$loader->alias('App\Traits\Documents', 'Modules\MyModule\Overrides\Traits\Documents');
}
}
namespace Modules\MyModule\Overrides\Traits;
use App\Traits\Documents as TraitTest;
trait Documents
{
use TraitTest {
getNextDocumentNumber as getNextDocumentNumber;
}
public function getNextDocumentNumber()
{
return '123456789';
}
}
The core trait is then integrated into a core controller, for example, and this cannot be adjusted!
namespace App\Notifications\Docu;
use App\Traits\Documents;
class Docu extends Notification
{
use Documents;
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
*/
public function toMail($notifiable): MailMessage
{
$message->title($this->getNextDocumentNumber($this->docu);
return $message;
}
}

How to use laravel repository pattern searchable array?

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

Inject services recursively in Laravel

I am using Laravel 5.2.45.
I am using dependency injection for my services.
Now, there is service A that needs service B, so I inject service B into A.
Also, there are methods in service B, that need service A, so I also injected service A into B.
However, this configuration seems to create a problem. This is my implementation:
class AService
{
/**
* #var BService
*/
protected $bService;
public function __construct(BService $bService) {
$this->bService = $bService;
}
}
class BService
{
/**
* #var AService
*/
protected $aService;
public function __construct(AService $aService) {
$this->aService = $aService;
}
}
First I noticed that my routes are not working, so I tried checking them with:
php artisan route:list
And I got:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 4096 bytes) in
/var/www/tacnet-plus/bootstrap/cache/compiled.php on line 1426
Segmentation fault (core dumped)
It seems that this configuration creates a memory overflow. I suspect that the first service creates the second and the second creates the first indefinitely.
I have had the same issue in the past with Java Spring, and I know you can inject your services there with a setter instead of the constructor, to avoid creating the dependency in the constructor and inject the service on demand through the setter. Is there something similar in Laravel?
It seems that there is nothing out of the box that will inject a service without using the constructor. However, I can change one of both services to inject the other service manually in a getter, instead of the constructor:
class AService
{
/**
* #var BService
*/
protected $bService;
public function __construct(BService $bService) {
$this->bService = $bService;
}
}
use App;
class BService
{
public function __construct() {
}
/**
* #return AService
*/
private function getAService() {
return App::make('Some\Namespace\AService');
}
}

Laravel 4.1.* issue registering events in service provider

I am trying to register events with the service provider but I keep getting reflection class error. I have searched and could not find a solution, perhaps this is an issue with the core.
// AppServiceProvider.php
<?php namespace App;
use Illuminate\Support\ServiceProvider;
use App\Events\UserEventHandler;
class AppServiceProvider extends ServiceProvider {
public function register() {
// Events
$this->app->events->subscribe(new UserEventHandler);
}
}
// UserEventHandler.php
<?php namespace App\Events;
class UserEventHandler {
/**
* Handle user login events.
*/
public function onUserLogin($event)
{
echo 'subscriber logged in'; exit;
}
/**
* Register the listeners for the subscriber.
*
* #param Illuminate\Events\Dispatcher $events
* #return array
*/
public function subscribe($events)
{
$events->listen('auth.login', 'UserEventHandler#onUserLogin');
}
}
$this->app->events->subscribe(new UserEventHandler); is firing fine, because I can reach the subscribe method, however $events->listen('auth.login', 'UserEventHandler#onUserLogin'); is returning an exception Class UserEventHandler does not exist
I have tried the same code on global.php and works fine, so the problem lies on the ServiceProvider, I have tried both methods register() and boot() and get the same error.
[UPDATED]
I have found that you need to specifically specify the full namespace when listening for the event.
public function subscribe($events)
{
$events->listen('auth.login', 'App\Events\UserEventHandler#onUserLogin');
}
You need to declare the full path to the class if it is in a different directory to the service provider.

Laravel 4 facade class not calling functions on facade root class

I've set up a package in laravel 4 via the artisan workbench command. I created a facade class and followed this tutorial to come up with the following service provider, facade and root classes:
src/Spoolphiz/Infusionsoft/InfusionsoftServiceProvider.php:
namespace Spoolphiz\Infusionsoft;
use Illuminate\Support\ServiceProvider;
class InfusionsoftServiceProvider extends ServiceProvider {
protected $defer = false;
/**
* Bootstrap the application events.
*
* #return void
*/
public function boot()
{
$this->package('spoolphiz/infusionsoft');
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
// Register 'infusionsoft' instance container to our Infusionsoft object
$this->app['infusionsoft'] = $this->app->share(function($app)
{
return new Spoolphiz\Infusionsoft\Infusionsoft;
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return array();
}
}
src/Spoolphiz/Infusionsoft/Facades/Facade.php:
namespace Spoolphiz\Infusionsoft\Facades;
use Illuminate\Support\Facades\Facade;
class Infusionsoft extends Facade {
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() { return 'infusionsoft'; }
}
Finally I've set up the underlying class thats to be connected to the facade at src/Spoolphiz/Infusionsoft/Infusionsoft.php:
namespace Spoolphiz\Infusionsoft;
//use Spoolphiz\Infusionsoft\iSDK;
/*
This is hackish and a un-laravel way to handle the requirement of \iSDK but unfortunately the xmlrpc3.0 lib doesn't want to correctly encode values when run with a namespace. Will try to resolve this later.
*/
require_once(__DIR__.'/isdk.php');
class Infusionsoft extends \iSDK {
protected $_app;
/**
* Init the sdk
*
*/
public function __construct( $connectionName )
{
$this->_app = parent::cfgCon($connectionName);
}
public function test()
{
dd('works');
}
}
I set up the service provider and the facade alias of Infusionsoft in app/config/config.php.
When I try running methods belonging to the extended iSDK class against an instance of Spoolphiz\Infusionsoft\Facade\Infusionsoft I get undefined method errors, such as the following:
Call to undefined method Spoolphiz\Infusionsoft\Facades\Infusionsoft::loadCon()
Why is this? The whole point of facades is to be able to call methods against its root class...
Looks like I was being stupid. I was developing this package in the laravel workbench. Once it was done I submitted it to packagist and set up a requirement for it in the same laravel app. Having the package installed in vendors directory and in the workbench caused some sort of conflict.
Lesson learned: make sure you dont have the same package in your workbench and in your application's vendors directory.

Resources