Laravel 5 - Interface is not instantiable - php

I know that this question was asked so many times, but none of answers helped me.
I'm getting exception in Laravel 5
BindingResolutionException in Container.php line 785:
Target [App\Contracts\CustomModelInterface] is not instantiable.
What I've done without success:
Register App\Providers\AppRepositoryProvider in app.php providers
php artisan clear-compiled
Everything works if I replace interfaces on repositories in MyService, but I feel that it's wrong (should it be handled by IoC container?).
Structure:
app
- Contracts
- CustomModelInterface.php
- Models
- CustomModel.php
- Repositories
- CustomModelRepository.php
- Providers
- AppRepositoryProvider.php
- Services
- MyService.php
App\Contracts\CustomModelInterface.php
<?php namespace App\Contracts;
interface CustomModelInterface {
public function get();
}
App\Repositories\CustomModelRepository.php
<?php namespace App\Repositories;
use App\Contracts\CustomModelInterface;
use App\Models\CustomModel;
class CustomModelRepository implements CustomModelInterface {
private $Model;
public function __construct(CustomModel $model) {
$this->Model = $model;
}
public function get() {
return 'result';
}
}
App\Services\MyService.php (Keep business logic / layer between controller and repositories)
<?php namespace App\Services;
use App\Contracts\CustomModelInterface;
class MyService {
private $Model;
public function __construct(CustomModelInterface $customModel) {
$this->Model= $customModel;
}
public function getAll() {
return $this->Model->get();
}
}
App\Providers\AppRepositoryProvider.php
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppRepositoryProvider extends ServiceProvider {
public function boot() {}
public function register() {
$models = array(
'CustomModel'
);
foreach ($models as $idx => $model) {
$this->app->bind("App\Contracts\{$model}Interface", "App\Repositories\{$model}Repository");
}
}
}
My controller looks like:
<?php namespace App\Http\Controllers;
use App\Services\MyService;
class SuperController extends Controller {
private $My;
public function __construct(MyService $myService) {
$this->My = $myService;
}
public function getDetails() {
return $this->My->getAll();
}
}
composer.json
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/",
"App\\Models\\": "app/Models/",
"App\\Contracts\\": "app/Contracts/",
"App\\Repositories\\": "app/Repositories/"
}
},

Thank you everyone, but problem was in my AppRepositoryProvider. As it's binding exception, then obviously the problem was with binding :)
Correct file is:
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppRepositoryProvider extends ServiceProvider {
public function boot() {}
public function register() {
$models = array(
'CustomModel',
'CustomModel2',
'CustomModel3'
);
foreach ($models as $model) {
$this->app->bind("App\Contracts\\{$model}Interface", "App\Repositories\\{$model}Repository");
}
}
}
Note, that I'm using "App\Contracts\\{$model}Interface" (not escaping "{" symbol) and it generate correct string App\Contracts\CustomModelInterface instead of App\Contracts\{$model}Interface (with unexpected escaping).

Every time I create a new repository/contract pair I make sure I do the following:
check the classes used in the service provider (copy/paste the namespaces)
register a new binding in config/app.php
php artisan optimize
Many hours of useless debugging led me to this short checklist.

For me, I forgot to bind in app->providers->RepositoryServiceProvider
the repository like this in the register method
public function register()
{
$this->app->bind(
\App\Play\Contracts\PatientRepository::class,
\App\Play\Modules\PatientModule::class
);
}
Make sure your RepositoryServiceProvider is registered in AppServiceProvider.
public function register()
{
$this->app->register(RepositoryServiceProvider::class);
}

I got past this error running:
php artisan config:clear
php artisan clear-compiled
php artisan optimize
php artisan config:cache
Related to:
Target is not instantiable. Laravel 5 - App binding service provider

The problem is solved by adding your repository in app/providers/AppServiceProvider
like the example below.
public function register()
{
$this->app->singleton(UserRepository::class, EloquentUser::class);
}
Dont forget the name space
use Test\Repositories\EloquentUser;
use Test\Repositories\UserRepository;
It worked for me

On App\Services\MyService.php you are passing that interface with dependency injection which tries to instantiate that -
public function __construct(CustomModelInterface $customModel) {
$this->Model= $customModel;
}
which is wrong.
Try implement that in that class - class MyService implements CustomModelInterface { and use the function of that interface like -
$this->get();
Or you are using it - class CustomModelRepository implements CustomModelInterface {
So if you do -
public function __construct(CustomModelRepository $customModel) {
$this->Model= $customModel;
}
then also you can access the interface methods.

I've just experienced an issue similar to this and the cause of my error was that I had set $defer to true in the service provider class but I had not implemented the required provides() method.
If you have deferred the creation of your class until it is need rather than it being loaded eagerly, then you need to also implement the provides method which should simply return an array of the classes that the provider provides. In the case of an interface, I believe it should be the name of the interface rather than the concrete class.
E.g.
public method provides(): array
{
return [
MyInterface::class,
];
}
Current documentation: https://laravel.com/docs/5.5/providers#deferred-providers
I hope this helps somebody else.

Don't worry guys. I have a solution to your problem.
I have an example for you.
Step1: php artisan make:repository Repository/Post //By adding this command you can create a repository and eloquent files
Step2: After adding that file you have to add/use this repository in the controller in which you want to use.
for eg: use App\Repositories\Contracts\PostRepository;
Step3: After adding that repo in your controller if you will run the app you will get an error like " Interface is not instantiable". It comes because you have created a repo and used in a controller, but laravel don't know where this repository is register and bind with which eloquent. So that it throws an error.
Step4: To solve this error you have to bind your repo with your eloquent in AppServiceProvider.
E.g:
AppServiceProvider.php file
<?php
namespace App\Providers;
// **Make sure that your repo file path and eloquent path must be correct.**
use App\Repositories\Contracts\PostRepository; // **Use your repository here**
use App\Repositories\Eloquent\EloquentPostRepository; **// Use your eloquent here**
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
/**
* Register any application services.
*
* #return void
*/
public function register() {
**// And bind your repository and eloquent here. **
$this->app->bind(PostRepository::class, EloquentPostRepository::class);
}
}
Step5: After binding repo and eloquent you can use all method of repo in your controller. Enjoy.....
Please let me know if you have any query.

execute this command :
composer dump-autoload
this command will remap your laravel autoload classes together with all other vendor's i had same issue before and this did the trick you can use it together with "-o" param for optimization .

Note that this can also be caused by the _constructor on the class being declared private, or otherwise being blocked...
If it cant call the constructor, the binding will fail

I think the problem here is that you don't bind App\Contracts\CustomModelInterface to anything so Laravel tries to create instance of interface.
In App\Providers\AppRepositoryProvider.php you have only:
$models = array(
'Model'
);
but you should have in this array CustomModel also, so it should look like this:
$models = array(
'Model',
'CustomModel',
);

The last thing you do is to use the interface you bound to the repository.
Set it up and try running your laravel app to make sure you get no errors.
In my case I had a mismatch between my repository and interface.
interface UserRepositoryInterface{
public function get($userId);
}
class UserRepository implements UserRepositoryInterface{
public function get(int $userId);
}
As you can see the interface get method does not include a type hint but the UserRepository class' get method has a type hint.
You won't get this error if you immediately start to use your Interface Binding.

register a new binding in config/app.php

In my case I forgot use App\Repositories\UserRepository in App\Providers\AppRepositoryProvider.php
intelephense wasn't complaining and the error-message did not give me any clue, but somehow I found out that it's missing and adding this line did the trick

I had this error, and found out that I should restart the queue because it runs in the job:
php artisan queue:restart

Related

Error: Call to undefined function Tests\factory()

In laravel I have written the following test:
public function testUserCanCreateAssortment()
{
$this->signIn();
$this->get('/assortments/create')->assertStatus(200);
$this->followingRedirects()
->post('/assortments', $attributes = Assortment::factory()->raw())
->assertSee($attributes['title'])
->assertSee($attributes['description']);
}
}
When I run it with the command phpunit --filter testUserCanCreateItem I get the following error:
Error: Call to undefined function Tests\factory()
No idea what is causing it. I have looked at my factories and my testcase.php but I could not find a solution. What am I doing wrong?
My testcase.php:
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
protected function signIn($user = null)
{
$user = $user ?: User::factory()->create();
$this->actingAs($user);
return $user;
}
}
Here the lines the error provides:
/var/www/tests/TestCase.php:13
/var/www/tests/Feature/ItemTest.php:29
In Laravel 8, the factory helper is no longer available. Your testcase model class should use HasFactory trait, then you can use your factory like this:
testcase::factory()->count(50)->create();
Please note that you should also update your call to User factory: factory('App\User')->create()->id;
Here is the relevant documentation:
https://laravel.com/docs/8.x/database-testing#creating-models
However, if you prefer to use the Laravel 7.x style factories, you can use the package laravel/legacy-factories You may install it with composer:
composer require laravel/legacy-factories
Guys I found the solution to my answer.
I needed to add the model name in my AssortmentFactory. So I did:
protected $model = Assortment::class;
and I also needed to import the model by doing use App/Models/Assortment.
In the UserFactory I also needed to import the model by doing App/Models/Assortment.
This solved my issue.
First run this command composer require laravel/legacy-factories
public function YourMethodName()
{
$user = factory(User::class)->create();
$this->actingAs($user);
//code...
}
You may have to specify that you are using an other class.
Did you write use Assortment or use \Assortment above ?
You can also use the manager to find the class you are using

Laravel 5.6 Facade/Alias not registering/working

I am trying to make my own custom Facade and register is with a custom service container and finally creating a custom alias for this facade.
I am not sure what part is not working, maybe there is a problem with the service container registering or maybe with the alias?
Let's start with my facade:
/**
*
* #see \App\Library\Facades\ViewWrapper\CustomView
*/
class CustomViewFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'customview';
}
}
My CustomView class with the logic and the show function
namespace App\Library\Facades\ViewWrapper;
...
class CustomView
{
public function show(...) { ... }
...
}
My CustomViewServiceProvider
namespace App\Providers;
...
class CustomViewServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(CustomViewFacade::class);
$this->app->alias(CustomViewFacade::class, 'customview');
}
}
How I register the provider in the config\app.php
App\Providers\CustomViewServiceProvider::class,
How I create the alias in the config\app.php
'CustomView' => App\Library\Facades\ViewWrapper\CustomViewFacade::class
In my controller I use the facade like this:
use CustomView;
...
public function show(ImageRequest $imagerequest)
{
return CustomView::show(...);
}
I get the following error in the controller:
Class 'CustomView' not found
What am I doing wrong here?
EDIT
After clearing config and composer autoload dump I get the following error:
Call to undefined method App\Library\Facades\ViewWrapper\CustomViewFacade::show()
I think you haven't quite clearly understood how Facades work. They are just an easy way to access your services without having to deal with dependency injection. I'm not a fan of this methodology, but here's how you do it properly.
You need to bind your actual service to the container, not the facade. The facade is almost just a symbolic link to your service within the container.
You need to import the actual service, not the facade. Laravel will automatically bind your dependency in the type-hinted variable, thanks to its behind the scenes magic.
Use:
use App\Library\Facades\ViewWrapper\CustomView;
(small note: your namespace here should be your service's namespace, be aware to not mix up the semantic between facade and service. The service contains the logic, the facade is just an accessor to a service that is already injected. This is important!!)
Instead of:
use CustomView;
It should solve the issue.
Also, I'd suggest you do define how the class should be constructed and injected in the Service Container by using a Closure in the bootstrap function.
class CustomViewServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->singleton(CustomView::class, function () {
return new CustomView(...);
);
}
}
Also, the alias function is not necessary in your case. It'd simply allow you to access the service by using the customview key in the Service Container.
Just define the Facade in your config/app.php file.
Another small suggestion: use PHP 7 class selectors instead of strings in your facade accessor definition. For example: CustomView::class intead of customview. It makes your code neater and easier to read.
Please run below command and check:
php artisan config:cache
php artisan cache:clear

how to fix Service provider class not found when using repository?

I am new to repository in laravel and trying to work on it , But when i run the application it throws the error
Class 'App\Repositories\User\UserRepoServiceProvider' not found
My interface and repository files are located in App\Repositories\User where Service Provider is also located
Here is my service provider
namespace App\Repositories\User
use Illuminate\Support\ServiceProvider;
class UserRepoServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('App\Repositories\User\userinterface','App\Repositories \User\userrepository');
}
}
Here is my userrepository.php
namespace App\Repositories\User
use App\Repositories\User\userinterface;
use App\car;
class userrepository implements userinterface
{
public function __construct(car $car){
$this->car = $car;
}
public function get($id)
{
return $this->car->findCar($id);
}
public function delete($id)
{
return $this->car->deleteCar($id);
}
}
Here is my interface userinterface.php
namespace App\Repositories\User;
interface userinterface{
public function get($id);
public function delete($id);
}
I have also registered it in config/app.php file
App\Repositories\User\UserRepoServiceProvider::class
I did composer dump-autoload -o but no use. I cannot do composer update , when i do it throws the same error
I usually check in bootstrap/cache/config.php for the package, sometimes after composer remove nameofthepackage, the package is still listed there
You have to register the service provider in config/app.php.
https://laravel.com/docs/5.3/providers#registering-providers
I'm facing this problem Class 'App\Respositories\BackendServiceProvider' not found
It was due to spelling mistake in config/app.php file. I changed Respositories to Repositories and open this BackendServiceProvider and changed namespace also. so problem has been solved.
Respositories to Repositories
namespace App\Respositories to namespace App\Repositories;
Working for me. You can try it!
Remove "laravel/ui" reference and its provider from packges.php file.

Attempting to use custom facade results in 'Call to undefined method' on Application::create() in Laravel?

I am attempting to create my own custom facade for a Search feature, but I'm having a little difficulty:
type: Symfony\Component\Debug\Exception\FatalErrorException
message: Call to undefined method Illuminate\Foundation\Application::create()
file: H:\myproj\vendor\laravel\framework\src\Illuminate\Container\Container.php
line: 165
This error is caused by my code hitting:
Search::indexObject();
Where my Search facade is set up as follows:
SearchServiceProvider
<?php
namespace MyProj\Search;
use Illuminate\Support\ServiceProvider;
class SearchServiceProvider extends ServiceProvider {
public function register() {
$this->app->bind('search', 'MyProj\Search\Search');
}
}
Search Facade
<?php
namespace MyProj\Facades;
use Illuminate\Support\Facades\Facade;
class Search extends Facade {
public static function getFacadeAccessor() {
return 'search';
}
}
Search class
<?php
namespace MyProj\Search;
use Elasticsearch\Client;
use Credential;
class Search {
private $elasticSearchClient;
public function __construct() {
$this->elasticSearchClient = new Client(array(
'hosts' => [Credential::ElasticSearchHost]
));
}
public function indexObject($object) {
// Code
return $this->elasticSearchClient->index($params);
}
public function get() {
return $this->$elasticSearchClient;
}
}
I have run composer dump-autoload without success, and my facade and service provider is loaded in app.php as follows:
Aliases array
'Search' => 'MyProj\Facades\Search',
Providers array
'MyProj\Search\SearchServiceProvider'
I've spent the past 30 minutes debugging and searching for this error without any fix. What's going on here?
EDIT: I've added in the stack trace, which you can see below. Additionally, I can see that getFacadeAccessor() is being called correctly, but anything beyond that is outside of my understanding.
The highlighted frame represents the last occurrence of normal operation, both frames on Handler.php represent the formatting and outputting of the error at the top of the question.
Appreciate this is a bit of an old thread, however you'd get the problems described if you compiled cache wasn't cleared after adding your new Facade.
You should run:
php artisan clear-compiled

Laravel 4: Target Interface is not instantiable

I've been comparing my code to this question and many other guides online but with little success. Everything works fine until I try to inject the the interface in my controller. When I do inject it, I get the Target Interface is not instantiable error.
app\models\Interfaces\InterviewInterface.php
<?php namespace app\models\Interfaces;
interface InterviewInterface {
public function fetch($id);
}
app\models\Interview.php
use app\models\Interfaces\InterviewInterface;
class Interview extends Eloquent implements InterviewInterface {
public function fetch($id)
{
return Interview::find($id);
}
}
routes.php
App::bind('app\models\Interfaces\InterviewInterface');
composer.json
"psr-4": {
"Blog\\Articles\\" : "app/lib/Blog/Articles",
"app\\models\\Interfaces\\" : "app/models/Interfaces/InterviewInterface.php"
}
AdminInterviewController.php
use app\models\Interfaces\InterviewInterface as InterviewInterface;
class AdminInterviewController extends BaseController {
public function __construct(InterviewInterface $interview)
{
$this->interview = $interview;
$this->beforeFilter('auth');
}
}
As soon as I add the
use app\models\Interfaces\InterviewInterface as InterviewInterface;
and
__construct(InterviewInterface $interview)
$this->interview = $interview;
lines, it gives me the error. I pull them out, no error.
I have run php composer.phar dump-autoload and php artisan dump-autoload commands multiple times and they succeed.
Any ideas? I really appreciate it.
You need to bind the interface to a class in order to resolve it from the IOC:
In routes.php, assuming it is not namespaced:
App::bind('app\modesl\Interfaces\InterviewInterface', 'Interview');

Categories