When I search the error 'Target Interface is not instantiable' I get a lot of results. Somehow I can still not find the solution to my problem.
I am not sure where it goes wrong.
PartnerController.php
<?php use CmsBlox\MOD\PartnerInterface;
class PartnerController extends BaseController {
public function __construct(PartnerInterface $partner)
{
$this->partner = $partner;
}
public function Get()
{
return "I'm the Get function in class PartnerController";
}
}
PartnerServiceProvider.php
<?php namespace CmsBlox\Providers;
use App, Illuminate\Support\ServiceProvider;
class PartnerServiceProvider extends ServiceProvider {
public function register()
{
}
public function boot()
{
app::bind('CmsBlox\MOD\PartnerInterface') ;
}
}
Routes.php
app::bind('CmsBlox\MOD\PartnerInterface') ;
PartnerInterface.php
<?php namespace CmsBlox\MOD;
interface PartnerInterface {
public function get();
}
I have also added the provider to App.php (for testing also a app::bind() in the routes.php)
'CmsBlox\Providers\PartnerServiceProvider'
As far I know every file should be correct. Somehow I am missing something!
I just found the answer! Thanks to the Laravel.io forums.
<?php use CmsBlox\MOD\PartnerInterface;
class PartnerController extends BaseController implements PartnerInterface {
public function get() {...}
}
Related
I am new into Phalcon framework. I just got the basic idea about it. Every controller has methods with multiple specific actions. I wrote a huge indexAction method but now I want to break it down with multiple private method so that I can reuse those functionality. But when I try to create any method without action suffix, it returns error(Page Not Found). How can I break it down into multiple methods?
<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller
{
public function indexAction()
{
$this->someMethod();
}
public function someMethod()
{
//do your things
}
}
Controllers must have the suffix “Controller” while actions the suffix “Action”. A sample of a controller is as follows:
<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller
{
public function indexAction()
{
}
public function showAction($year, $postTitle)
{
}
}
For calling another method, you would use it straight forward
<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller
{
public function indexAction()
{
echo $this->showAction();
}
private function showAction()
{
return "show";
}
}
Docs.
What exactly do you want? The answer seems trivial to me.
class YourController extends Phalcon\Mvc\Controller
{
// this method can be called externally because it has the "Action" suffix
public function indexAction()
{
$this->customStuff('value');
$this->more();
}
// this method is only used inside this controller
private function customStuff($parameter)
{
}
private function more()
{
}
}
I'm trying to write an SSO implementation and for that I need to override some methods such as Auth::check() which are implemented in the Guard class.
I don't understand, however, how to extend that class using service providers. I tried looking in the AuthServiceProvider but there is a whole lot of mumbo jumbo going on I don't understand.
I figured it out! Fairly simple:
<?php
namespace Animekyun\Providers;
use Animekyun\Auth\CustomGuard;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Support\ServiceProvider;
class SsoServiceProvider extends ServiceProvider
{
public function boot()
{
\Auth::extend('custom', function () {
return new CustomGuard(
new EloquentUserProvider(
$this->app['hash'],
$this->app['config']['auth.model']),
$this->app['session.store']);
});
}
public function register()
{
}
}
and the CustomGuard class:
<?php
namespace Animekyun\Auth;
use Illuminate\Auth\Guard;
class CustomGuard extends Guard
{
public function check() {
// do some stuff
return parent::check();
}
}
I have a class which acts like a storage (add/get item). I try to bind it as a singleton in one service provider, and resolve it in another's boot method.
The code is changed for simplicity.
app/Providers/BindingProvider.php
<?php namespace App\Providers;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\ServiceProvider as ServiceProvider;
class MyBindingFacade extends Facade {
public static function getFacadeAccessor() {
return 'my.binding';
}
}
class MyBinding {
protected $items = [];
public function add($name, $item) {
$this->items[$name] = $item;
}
public function get($name) {
return $this->items[$name];
}
public function getAll() {
return $this->items;
}
}
class BindingProvider extends ServiceProvider {
public function register() {
$this->app->singleton('my.binding', function($app) {
return $app->make('App\Providers\MyBinding');
});
}
public function provides() {
return [
'my.binding',
];
}
}
app/Providers/ResolvingProvider.php
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider as ServiceProvider;
use App\Providers\MyBinding;
class ResolvingProvider extends ServiceProvider {
public function boot(MyBinding $binding) {
$binding->add('foo', 'bar');
// $manual = $this->app->make('my.binding');
// $manual->add('foo', 'bar');
}
public function register() {}
}
app/Http/Controllers/WelcomeController.php
<?php
namespace App\Http\Controllers;
use App\Providers\MyBindingFacade;
class WelcomeController extends Controller {
public function index()
{
dd(MyBindingFacade::getAll()); // debug items
}
}
When I try to debug MyBinding state in my WelcomeController I'm getting empty item array. However, if I uncomment $manual part from my ResolvingProvider it returns an array containing 'foo' => 'bar'. Does it mean IoC resolution is broken in ServiceProvider::boot() method or am I misusing Laravel functionality?
Laravel version: 5.0.28
UPDATE: Added code sample from WelcomeController.
With this:
$this->app->singleton('my.binding', function($app) {
return $app->make('App\Providers\MyBinding');
});
You're saying: my.binding is a singleton and resolves to an instance of App\Providers\MyBinding.
That doesn't mean that App\Providers\MyBinding is registered as singleton too. What you should do instead is this:
$this->app->singleton('App\Providers\MyBinding');
$this->app->bind('my.binding', function($app) {
return $app->make('App\Providers\MyBinding');
});
Because the Facade binding uses $app->make() you should get the same instance you registered with $this->app->singleton() right above.
In the first example you are not using the Facade, you should be using:
use App\Providers\MyBindingFacade as MyBinding;
Which will in fact call make it using 'my.binding'.
Sorry for the English, but I am using the google translator.
First of all I leave my code:
FtpServiceProdiver.php
<?php namespace Jaimemse\Ftp;
use Illuminate\Support\ServiceProvider;
class FtpServiceProvider extends ServiceProvider {
protected $defer = false;
public function boot()
{
$this->package('jaimemse/ftp');
}
public function register()
{
$this->app->bind('ftp', function()
{
return new Ftp;
});
}
public function provides()
{
return array();
}
}
Ftp.php (the class)
<?php namespace Jaimemse\Ftp;
class Ftp {
public function hello()
{
return 'hola';
}
}
Facades/Ftp.php (Facade)
<?php namespace Jaimemse\Ftp\Facades;
use Illuminate\Support\Facades\Facade;
class Ftp extends Facade {
protected static function getFacadeAccessor() { return 'ftp'; }
}
app.php
'Jaimemse\Ftp\FtpServiceProvider',
'Ftp' => 'Jaimemse\Ftp\Facades\Ftp',
If instead of that Facade put this, if it works:
'Ftp' => 'Jaimemse\Ftp\Ftp',
The problem I have is that when using the alias in the file app.php seeks Ftp class in the folder Facades/Ftp.php
Call to undefined method Jaimemse\Ftp\Facades\Ftp::hello()
Someone can help me? Thanks!
You have to extend the BaseController:
<?php namespace Jaimemse\Ftp;
class Ftp extends \BaseController {
public function hello()
{
return 'hola';
}
}
Also your route should be (with namespace):
Route::get('/ftp', 'Jaimemse\Ftp\Ftp#hello');
Also
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\ServiceProvider;
should be
use \Illuminate\Support\Facades\Facade;
use \Illuminate\Support\ServiceProvider;
You should put in app.php
'Jaimemse\Ftp\FtpServiceProvider', in 'providers' array (before 'aliases')
and in 'aliases' array
'Ftp' => 'Jaimemse\Ftp\Facades\Ftp',
I fixed it by adding in register method:
FtpServiceProvider.php
public function register()
{
$this->app->bind('ftp', function()
{
return new Ftp;
});
$this->app->booting(function()
{
$loader = \Illuminate\Foundation\AliasLoader::getInstance();
$loader->alias('Ftp', 'Jaimemse\Ftp\Ftp');
});
}
Ftp.php
class Ftp {
public function hello()
{
return 'hello';
}
}
App.php
'Jaimemse\Ftp\FtpServiceProvider',
I have not added any app.php alias in the file. I deleted Facade file.
Now I can do things like:
Ftp::hello();
Hope that helps someone. Thank you!
I am having an issue getting a Facade to work properly with a dependency injected into the underlying class.
I have a class called 'Listing'. It has one dependency called 'AdvertRepository' which is an interface and a class called EloquentAdvert which implements the interface. The code for these three classes is here:
// PlaneSaleing\Providers\Listing.php
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
class Listing {
protected $advert;
public function __construct (AdvertRepository $advert_repository) {
$this->advert = $advert_repository;
}
public function test() {
$this->advert->test();
}
public function test2() {
echo "this has worked";
}
}
// PlaneSaleing\Repositories\Advert\AdvertRepository.php
<?php namespace PlaneSaleing\Repositories\Advert;
interface AdvertRepository {
public function test();
}
// PlaneSaleing\Repositories\Advert\EloquentAdvert.php;
<?php namespace PlaneSaleing\Repositories\Advert;
class EloquentAdvert implements AdvertRepository {
public function test() {
echo 'this has worked';
}
}
I have then created a service provider called ListingServiceProvider.php, which has the following code:
// PlaneSaleing/Providers/ListingServiceProvider.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
}
}
I also added this to the ServiceProviders array in app.php
Now, if I inject Listing as a dependency into a controller and call the test method (as shown below) Laravel correctly detects the dependency, instantiates EloquentAdvert via its binding and displays 'this has worked'.
// Controllers/TestController.php
use PlaneSaleing\Providers\Listing;
class TestController extends BaseController {
protected $listing;
public function __construct(Listing $listing) {
$this->listing = $listing;
}
public function test1() {
$this->listing->test();
}
}
Now, I then created a facade for Listing. I added a new facade as follows and added an alias in app.php:
// PlaneSaleing\Providers\ListingFacade.php
<?php namespace PlaneSaleing\Providers;
use Illuminate\Support\Facades\Facade;
class ListingFacade extends Facade {
protected static function getFacadeAccessor() {
return 'Listing';
}
}
I also added the following new lines to ListingServiceProvider.php:
<?php namespace PlaneSaleing\Providers;
use PlaneSaleing\Repositories\Advert\AdvertRepository;
use PlaneSaleing\Repositories\Advert\EloquentAdvert;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
class ListingServiceProvider extends ServiceProvider {
public function register() {
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', 'PlaneSaleing\Repositories\Advert\EloquentAdvert');
// New lines...
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
}
}
NOW...if I call Listing::test(), I get the following error: Cannot instantiate interface PlaneSaleing\Repositories\Advert\AdvertRepository.
If I call Listing::test2() , I get 'this has worked' so it seems the Facade is working correctly.
It seems that when accessing Listing via its Facade the binding between AdvertRepository and EloquentAdvert doesnt work. I have looked at my code in the ServiceProvider thinking it was the issue, but I cant figure it out.
Both the Facade and binding work when tested individually but not when both are used at the same time.
Any ideas???
OK, So I have figured it out...For those who run into a similar problem...
The offending statement was in ListingServiceProvider.php which read:
$this->app['Listing'] = $this->app->share(function() {
return new Listing(new AdvertRepository);
});
The error is the new AdvertRepository statement. The reason being is that, we are telling php to directly instantiate the interface 'AdvertRepository'. Instead, we need to tell Laravel to instantiate the appropriate implementation of the 'AdvertRepository' interface. To do that, we use App::make('AdvertRepository'). That way, Laravel uses the binding previously declared to instantiate the correct implementation.
If your constructor is not being inject with a class, you must tell Laravel what class will be used when it needs to instantiate a particular interface:
Put this in your filters or bindings file:
App::bind('PlaneSaleing\Repositories\Advert\AdvertRepository', function()
{
return new PlaneSaleing\Repositories\Advert\EloquentAdvert;
});