I`m trying to get instanse of my class using dependency injection.
This class has own service provider that registered in app.php
class Something
{
private $variable;
public function __construct(string $variable)
{
$this->variable = $variable;
}
}
this is service provider
class SomethingServiceProvider extends ServiceProvider
{
public function boot()
{
}
public function register()
{
$this->app->singleton('Something', function () {
return new Something( 'test');
});
}
}
and when I try to use this class instance in controller...
class TestController extends AppBaseController
{
public function __construct(Something $something)
{
$this->something = $something;
}
...
I got error:
"Unresolvable dependency resolving [Parameter #0 [ string $variable ]]
in class Something at
Container->unresolvablePrimitive(object(ReflectionParameter)) in
Container.php (line 848) "
I guess YourServiceProvider::__construct accepts a non-typed $app instance. This means that Laravel cannot automatically resolve it. Try typing it; public function __construct(Application $app) with the proper use-statement.
More: https://laravel.com/docs/5.3/container#automatic-injection
When you register something to be injected you need to use the fully qualified class name:
public function register()
{
$this->app->singleton(Something::class, function () {
return new Something( 'test');
});
}
Otherwise Laravel will try to automatically inject something which implies that it will try to inject the dependencies of Something first and then determine that this is a string and fail.
Related
Is possible to call invoke function from a service in symfony?
this is the controller
class FooController extends AbstractController
{
private $fooService;
public function __construct(FooService $fooService)
{
$this->fooService = $fooService;
}
#[Route('/foo', name: 'app_foo')]
public function index(): Response
{
return new Response($this->fooService->__invoke());
//is not possible to do
//return new Response($this->fooService());
}
}
and the service
namespace App\Service;
class FooService
{
public function __invoke()
{
return 'hello';
}
}
I have to call __invoke function explicitly instead to make $this->fooService() is not possible to do it?
In PHP the method call has higher priority than property access so you need to use parentheses.
($this->fooService)()
To access the property and call it.
i dont know how to write mock test for my service
here is my compressContract Interface
interface compressContract
{
public function compress();
}
here is my ZipCompress class
<?php
namespace App\Http\Controllers\My\compression;
class ZipCompress implements compressContract
{
public function compress()
{
var_dump('im zip compression');
}
}
and here is my compressManager class
class compressManager
{
public compressContract $compressContract;
public function __construct(compressContract $compressContract)
{
$this->compressContract = $compressContract;
}
public function compressFile(Request $request)
{
//do somthing
}
}
and here is AppServiceProvider class in the boot method
public function boot()
{
$this->app->bind(CompressContract::class , ZipCompress::class);
}
i read articles about mocking a class but i cant write mock for these class
Firstly basics, class names are pascal cased. compressContract should be CompressContract.
A unit test, mocking the compression contract would look like this. Laravel has helpers in the test cases to help you actual bind the mocked instance to the container. This is described in the documentation here.
/** #test **/
public function your_test()
{
$this->mock(CompressContract::class, function (MockInterface $mock) {
$mock->shouldReceive('compress')->once()->andReturn('If you want correct return');
});
// call your class or http test your controller.
}
I'm trying to build a structure that uses dependency injection on lumen.
I Have a Service Layer and repository layer.
I want to inject the repository layer to service layer. Let me try to show you the code
interface IUserRepostitory {
public function getByID($id);
}
class UserRepository extends BaseRepository implements IRepository{
public function getByID($id) {
//Please don't think how this function works, my question about dependency injection
return $this->findOrFail($id);
}
}
interface IService {
public function getByID($id);
}
class UserService implements IService{
private $Repository;
public __construct(IUserRepositor $UserRepository) {
$this->Repository = $UserRepository
}
public function getByID($id) {
return $this->Repository->getByID($id);
}
}
Here I'm registering the dependency resolver.
//Dependency resolver for Repository Layer
class RepositoryServiceProvider extends ServiceProvider {
public function register()
{
$this->app->singleton(IUserRepository::class, function () {
return new UserRepository();
});
}
}
Here I'm registering Service Layer
class ServiceServiceProvider extends ServiceProvider {
public function register()
{
$this->app->singleton(IUserService::class, function () {
//Here is what I don't like
//It would be great a solution that automaticly resolve UserRepository.
return new UserService(new UserRepository());
});
}
}
As you see, I want to auto resolve the dependency into UserService. But singleton method need to create the returning object.
Is there a better way for this?
*** note : please don't pay attention on syntax, I'm writing it on lumen but the same problem on laravel.
Once you bind the UserRepository to the IUserRepository, you may then instantiate the IUserService with the IUserRepository by resolving with the make function!
Modifying your ServiceServiceProvider as such:
class ServiceServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(IUserService::class, function ($app) {
return new UserService($app->make(IUserRepository::class));
});
}
}
I am following this link to implement it
I did below steps to implement the Contract in my existing class.
Below is the class where I will write some logic also before sending it to controller
namespace App\Classes\BusinessLogic\Role;
use App\Classes\DatabaseLayer\Role\RoleDb;
use App\Classes\Contract\Role\IRole;
class RoleBL implements IRole {
public function All() {
return (new RoleDb())->All();
}
}
Database Function
namespace App\Classes\DatabaseLayer\Role;
class RoleDb {
public function All() {
$Roles = \App\Models\Role\RoleModel
::all();
return $Roles;
}
}
Interface
namespace App\Classes\Contract\Role;
interface IRole {
public function All();
}
Service Provider class
namespace App\Providers\Role;
class RoleServiceProvider extends \Illuminate\Support\ServiceProvider {
public function register()
{
$this->app->bind('App\Classes\Contract\Role\IRole', function($app){
return new \App\Classes\BusinessLogic\Role\RoleBL($app['HttpClient']);
});
}
}
Finally in config/app.php in provider wrote below line.
App\Providers\Role\RoleServiceProvider::class
Controller - Constructor
protected $roles;
public function __construct(\App\Classes\Contract\Role\IRole $_roles) {
parent::__construct();
$roles = $_roles;
}
Controller Action method
public function index(IRole $roles) {
$RoleTypes = $roles->All();
}
So far everything works fine if I keep Interface as parameter in method.
if I try to use the variable $roles in index method and remove the variable, it is always null.
Please guide me if I missed anything?
You incorrectly assign the $roles property in your __construct() method.
Replace
$roles = $_roles;
with
$this->roles = $_roles;
and then in your index method do:
$RoleTypes = $this->roles->All();
I'm developing a package for Laravel and I'm getting an error which I can't figure out how to fix:
Argument 1 passed to Cartalini\Drayman\Drayman::__construct() must be an instance of Cartalini\Drayman\Repositories\UserRepositoryInterface, none given, called in /Applications/MAMP/htdocs/l4/app/controllers/HomeController.php on line 10 and defined
Here's my code...
namespace Cartalini\Drayman;
use Cartalini\Drayman\Repositories\UserRepositoryInterface;
class Drayman
{
protected $user;
public function __construct(UserRepositoryInterface $user)
{
$this->user = $user;
}
public function deliverBeer()
{
return $this->user->all();
}
}
UserRepository...
namespace Cartalini\Drayman\Repositories;
class UserRepository implements UserRepositoryInterface
{
public function all()
{
return User::all();
}
}
UserRepositoryInterface...
namespace Cartalini\Drayman\Repositories;
interface UserRepositoryInterface
{
public function all();
}
Service provider...
public function register()
{
$this->app->bind('Cartalini\Drayman\Repositories\UserRepositoryInterface', 'Cartalini\Drayman\Repositories\UserRepository');
}
And finally my controller...
use Cartalini\Drayman\Drayman as Drayman;
class HomeController extends BaseController
{
public function showWelcome()
{
$drayman = new Drayman;
return $drayman->deliverBeer();
}
}
Can anyone help me to debug this please?
In your showWelcome function:
public function showWelcome()
{
// need to pass a UserRepositoryInterface object here:
$drayman = new Drayman;
return $drayman->deliverBeer();
}
Since you did not pass a UserRepositoryInterface object that your code requires you get that error.
it might be a to late, but i had the same problem and the reason was my concrete class didn't implement it's corresponding interface class. after implementing it, all went well.
although you are correctly implementing it, so this error might have a few reason, which one of them is what i described.