I've bind my interface called CustomerRepository to EloquentCustomerRepository. This is my CustomerServiceProvider:
public function register()
{
$this->app->bind(CustomerRepository::class,EloquentCustomerRepository::class);
$this->app->bind(PackageRepository::class,EloquentPackageRepository::class);
}
When I try to instantiate it in my controller like this:
<?php
namespace App\Http\Controllers\api\v1;
use Lsupport\repositories\api\v1\customer\CustomerRepository;
use App\Http\Controllers\Controller;
use Lsupport\customer\Customer;
use App\Http\Requests;
class CustomerController extends Controller
{
protected $CustomerRepository;
public function __construct(CustomerRepository $CustomerRepository)
{
$this->CustomerRepository = $CustomerRepository;
}
It throws the following error:
Target [Lsupport\repositories\api\v1\Customer\CustomerRepository] is not instantiable while building [App\Http\Controllers\api\v1\CustomerController].
I also registered it in app.config:
App\Providers\CustomerServiceProvider::class,
What am I doing wrong?
CustomerServiceProvider
<?php
namespace App\Providers;
use Lsupport\repositories\api\v1\customer\EloquentCustomerRepository;
use Lsupport\repositories\api\v1\customer\EloquentPackageRepository;
use Lsupport\repositories\api\v1\customer\CustomerRepository;
use Lsupport\repositories\api\v1\customer\PackageRepository;
use Illuminate\Support\ServiceProvider;
class CustomerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->bind(CustomerRepository::class,EloquentCustomerRepository::class);
$this->app->bind(PackageRepository::class,EloquentPackageRepository::class);
}
}
CustomerRepository
<?php
namespace Lsupport\repositories\api\v1\Customer;
interface CustomerRepository
{
public function create($request);
}
**EloquentCustomerRepository**
<?php
namespace Lsupport\repositories\api\v1\customer;
use Lsupport\repositories\api\v1\customer\CusteromRepositoryTrait;
use Lsupport\repositories\api\v1\remain\RightTrait;
use Lsupport\repositories\api\v1\remain\JsonTrait;
use Lsupport\customer\Customer;
class EloquentCustomerRepository implements CustomerRepository
{
use JsonTrait;
use RightTrait;
use CustomerRepositoryTrait;
code.....
Ok, the first thing I notice is that you probably want the same namespaces on the interface and on the class. So, the namespace of EloquentCustomerRepository should be
namespace Lsupport\repositories\api\v1\Customer;
and not
namespace Lsupport\repositories\api\v1\customer;
(with lower customer).
Now, on your CustomerServiceProvider, you should use:
public function register()
{
$this->app->bind('Lsupport\repositories\api\v1\Customer\CustomerRepository', 'Lsupport\repositories\api\v1\Customer\EloquentCustomerRepository');
}
Make sure you run composer dumpautoload -o on the command line.
Related
I'm working with Laravel 9 and I have a Controller like this:
use App\Repositories\HomeRepositoryInterface;
class HomeController extends Controller
{
private $homeRespository;
public function __construct(HomeRepositoryInterface $homeRepository)
{
$this->homeRespository = $homeRepository;
}
...
And here is the HomeRepositoryInterface:
<?php
namespace App\Repositories;
interface HomeRepositoryInterface
{
public function newest();
}
And this is the HomeRepository itself:
<?php
namespace App\Repositories;
use App\Models\Question;
class HomeRepository implements HomeRepositoryInterface
{
public function newest()
{
return $ques = Question::orderBy('created_at', 'DESC')->paginate(10);
}
}
But now I get this error:
Target [App\Repositories\HomeRepositoryInterface] is not instantiable while building [App\Http\Controllers\HomeController].
So what's going wrong here?
How can I solve this issue?
It seems that you did not introduce the service container.
For this, it is better to create a service provider as shown below and introduce the repository class to the container.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Repositories\HomeRepositoryInterface;
use App\Repositories\HomeRepository;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
// Bind Interface and Repository class together
$this->app->bind(HomeRepositoryInterface::class, HomeRepository::class);
}
}
Next, you should introduce this service provider in the config/app.php file.
'providers' => [
...
...
...
App\Providers\RepositoryServiceProvider::class,
],
Laravel CQRS
I am applying CQRS in Laravel just to learn how to use it.
I created a simple user registration and a controller that creates a command to dispatch the handle and use the right use case.
When Trying to use the interface in the controller, it looks like that I need to bind the interface and the implementation because it doesn't know which one to use but in this case I don't really understand how to bind the interface.
CreateUserController.php
<?php
declare(strict_types=1);
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\Users\CreateUserRequest;
use Illuminate\Http\RedirectResponse;
class CreateUserController extends Controller
{
public function __construct(private \Src\User\Infrastructure\CreateUserController $userController)
{
}
public function __invoke(CreateUserRequest $request): RedirectResponse
{
$this->userController->__invoke($request);
return redirect()->route('verify');
}
}
Src\User\Infrastructure\CreateUserController
<?php
declare(strict_types=1);
namespace Src\User\Infrastructure;
use App\Http\Requests\Users\CreateUserRequest;
use Src\Shared\Domain\Bus\Command\CommandBus;
use Src\User\Application\Create\CreateUserCommand;
final class CreateUserController
{
public function __construct(private CommandBus $commandBus)
{
}
public function __invoke(CreateUserRequest $request)
{
$name = $request->name;
$email = $request->email;
$password = $request->password;
$command = new CreateUserCommand($name, $email, $password);
$this->commandBus->dispatch($command);
}
}
CommandBus
<?php
declare(strict_types=1);
namespace Src\Shared\Domain\Bus\Command;
interface CommandBus
{
public function dispatch(Command $command): void;
}
Command
<?php
declare(strict_types=1);
namespace Src\Shared\Domain\Bus\Command;
interface Command
{
}
CreateUserCommandHandler
<?php
declare(strict_types=1);
namespace Src\User\Application\Create;
use Src\User\Domain\ValueObjects\UserEmail;
use Src\User\Domain\ValueObjects\UserName;
use Src\User\Domain\ValueObjects\UserPassword;
final class CreateUserCommandHandler
{
public function __construct(
private UserCreator $creator
)
{
}
public function __invoke(CreateUserCommand $command)
{
$name = new UserName($command->name());
$email = new UserEmail($command->email());
$password = new UserPassword($command->password());
$this->creator->__invoke($name, $email, $password);
}
}
The Error
I tried this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Src\Shared\Domain\Bus\Command\Command;
use Src\User\Application\Create\CreateUserCommand;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(
Command::class,
CreateUserCommand::class
);
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
Here is how you can bind with the interface.
Create a class in app/Providers folder. You can give any name to this class. Eg. InterfaceServiceProvider. extends it with Illuminate\Support\ServiceProvider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class InterfaceServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->bind(YourInterFace::class, YourController::class);
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
Add this InterfaceServiceProvider in config/app.php in providers array
Eg.
'providers' => [
App\Providers\InterfaceServiceProvider::class,
]
I know there are so many answer, but I cannot really solve this.
I did follow this answer (How to make a REST API first web application in Laravel) to create a Repository/Gateway Pattern on Laravel 5.7
I have also the "project" on github, if someone really kindly want test/clone/see : https://github.com/sineverba/domotic-panel/tree/development (development branch)
App\Interfaces\LanInterface
<?php
/**
* Interface for LAN models operation.
*/
namespace App\Interfaces;
interface LanInterface
{
public function getAll();
}
App\Providers\ServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
/**
* Solve the "Key too long" issue
*
* #see https://laravel-news.com/laravel-5-4-key-too-long-error
*/
Schema::defaultStringLength(191);
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->register(RepositoryServiceProvider::class);
}
}
App\Providers\RepositoryServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
'app\Interfaces\LanInterface', // Interface
'app\Repositories\LanRepository' // Eloquent
);
}
}
App\Gateways\LanGateway
<?php
/**
* The gateway talks with Repository
*/
namespace App\Gateways;
use App\Interfaces\LanInterface;
class LanGateway
{
protected $lan_interface;
public function __construct(LanInterface $lan_interface) {
$this->lan_interface = $lan_interface;
}
public function getAll()
{
return $this->lan_interface->getAll();
}
}
App\Repositories\LanRepository
<?php
/**
* Repository for LAN object.
* PRG paradigma, instead of "User"-like class Model
*/
namespace App\Repositories;
use App\Interfaces\LanInterface;
use Illuminate\Database\Eloquent\Model;
class LanRepository extends Model implements LanInterface
{
protected $table = "lans";
public function getAll()
{
return 'bla';
}
}
I did add also App\Providers\RepositoryServiceProvider::class, in providers section of config\app.php
This is finally the controller (I know that it is not complete):
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Gateways\LanGateway;
class LanController extends Controller
{
private $lan_gateway;
/**
* Use the middleware
*
* #return void
*/
public function __construct(LanGateway $lan_gateway)
{
$this->middleware('auth');
$this->lan_gateway = $lan_gateway;
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$this->lan_gateway->getAll();
return view('v110.pages.lan');
}
}
And the error that I get is
Target [App\Interfaces\LanInterface] is not instantiable while building [App\Http\Controllers\LanController, App\Gateways\LanGateway].
I did try:
php artisan config:clear
php artisan clear-compiled
I think #nakov might be right about it being case-sensitive. I don't believe PHP itself cares about upper/lowercase namespaces, but the composer autoloader and the Laravel container use key->value array keys, which do have case-sensitive keys, to bind and retrieve classes from the container.
To ensure the names always match, try using the special ::class constant instead, like this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Repositories\LanRepository;
use App\Interfaces\LanInterface;
class RepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(
LanInterface::class,
LanRepository::class
);
}
}
In my case i forgot to enlist the provider to confit/app.php that's why the error.
Clear the old boostrap/cache/compiled.php:
php artisan clear-compiled
Recreate boostrap/cache/compiled.php:
php artisan optimize
I am trying to use Laravel view composer. I have registered my class in config/app.php but I keep getting the following error:
"Class App\Http\ViewComposers\PostComposer does not exist
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use View;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
View::composer('plain','App\Http\ViewComposers\PostComposer');
}
/**
* Register services.
*
* #return void
*/
public function register()
{
//
}
}
my post composer class
<?php
namespace App\Http\ViewComposer;
use Illuminate\View\View;
use App\Post;
class PostComposer
{
public function comspose(View $view)
{
$posts = Post::all();
$view->with('postha', $posts );
}
}
and here is the screenshot of my browser:
![folder structure in my app][]
Your namespace is wrong.
You're importing from (plural):
App\Http\ViewComposers\PostComposer
but the namespace of your ViewComposer isn't plural:
App\Http\ViewComposer
try it : namespace App\Http\ViewComposer To namespace App\Http\ViewComposers
I have the following files:
ModelObserverProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Models\User;
use App\Models\Profile;
use App\Observers\UserObserver;
use App\Observers\ProfileObserver;
class ModelObserverProvider extends ServiceProvider
{
public function boot()
{
User::observe(UserObserver::class);
Profile::observe(ProfileObserver::class);
}
public function register()
{}
}
UserObserver.php
<?php
namespace App\Observers;
use App\Models\User;
class UserObserver
{
public function creating(User $user)
{
dd('Creating...');
// Hash the users password when creating.
$user->password = bcrypt($user->password);
// Create a new profile for the user.
$user->profiles()->create(['name' => 'guest-' . time()]);
}
}
I have loaded the ModelObserverProvider in my config/app.php, however, notice the dd('Creating...'); ? When creating a new user via User::create($request->all()) this does not appear to be firing at all? Any ideas?
Try this
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Models\User;
use App\Models\Profile;
use App\Observers\UserObserver;
use App\Observers\ProfileObserver;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
User::observe(UserObserver::class);
Profile::observe(ProfileObserver::class);
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{}
}