Injecting Interface on class (Laravel Package) - laravel

I'm developing my own L5 package for handling payments. To be able to change the payment gateway in the future, I'm using interfaces.
My interface looks like this:
interface BillerInterface
{
public function payCash();
public function payCreditCard();
}
I also have a concrete implementation, which is the desired payment gateway.
class Paypal implements BillerInterface
{
public function payCash()
{
// Logic
}
public function payCreditCard()
{
// Logic
}
}
The Biller class is the main class, and the constructor method expects the above interface, like so:
class Biller {
protected $gateway;
public function __construct(BillerInterface $gateway)
{
$this->gateway = $gateway;
}
// Logic
}
Last, I created the service provider, to bind the interface to the gateway class.
public function register()
{
$this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');
}
Seems to be working, but I'm getting an error when trying to instantiate the Biller class...
Biller::__construct() must be an instance of Vendor\Biller\Contracts\BillerInterface, none given
I tried the following code but doesn't seem to work...
public function register()
{
$this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');
$this->app->bind(Biller::class, function ($app) {
return new Biller($app->make(BillerInterface::class));
});
}
Any clues?

You’re binding interfaces to an implementation fine in your service provider. But dependencies will only be resolved by the service container, i.e.
class SomeClass
{
public function __construct(Billing $billing)
{
$this->billing = $billing;
}
}
Laravel’s service container will read the type-hint of the constructor method’s parameters, and resolve that instance (and also any of its dependencies).
You won’t be able to “new up” the Billing instance directly (i.e. $billing = new Billing) because the constructor is expecting something implementing BillingInterface, which you’re not providing.

When you're binding interface to actual class try replacing the BillerInterface::class with a string '\Your\Namespace\BillerInterface'

This is how I've done it in my app and it seems to be working:
public function register()
{
$this->app->bind('DesiredInterface', function ($app) {
return new DesiredImplementationClass(
$app['em'],
new ClassMetaData(DesiredClass::class)
);
});
}

Talking about #MaGnetas answer
I prefer to bind class with interface using this way.
public function register()
{
$this->app->bind(AppointmentInterface::class, AppointmentService::class);
}
This helps IDEs to find the path of the class and we can jump to that class by just clicking on it.
If we pass class path as string path like shown below:
public function register()
{
$this->app->bind('App\Interfaces\AppointmentInterface', 'App\Services\AppointmentService');
}
Then IDE can not find the location of class when we click on this string.

Related

How to write a custom function in a model?

There is a model data:
class Order extends Model
{
}
How to write a custom method inside the Order class so that it can be called in constructor like this:
Order::myMethod()
Order->myMethod()
Where myMethod is:
public function myMethod() {
return DB::query(<SQL QUERY>);
}
Purpose is to move SQL queries inside model's class, that don't mess this code in controllers.
Rather create a custom function in Model, You can use traits to achieve the desired output.
Please follow either steps:-
https://medium.com/#kshitij206/traits-in-laravel-5db8beffbcc3
https://www.conetix.com.au/blog/simple-guide-using-traits-laravel-5
Guess you are asking about the static functions:
class Order extends Model {
public static function myMethod() {
}
}
and you can call it anywhere like
Order::myMethod();
You can achieve the desired behavior using magic methods __call and __callStatic
if your real method is static you can use __call() to intercept all "non static" calls and use it to call the static and use __callStatic to forward the calls to a new instance to that class .
Your methods should be always static because if a non static method exists and you are calling it statically php raises an error
Non-static method Foo::myMethod() should not be called statically
No problem if your method is static
class Order extends Model {
public static function myMethod() {
return static::query()->where(...)->get(); // example
}
public function __call($name, $arguments) {
return forward_static_call_array([__CLASS__, $name], $arguments);
}
public static function __callStatic($name, $arguments) {
return call_user_func_array([app(__CLASS__), $name], $arguments);
}
}
(new Order())->myMethod();
Order::myMethod();
I can't understand your exact problem is. but if you are using laravel, then you can write custom method inside the ABC model like this
class ABC extends Model
{
//here is your fillable array;
public function abc()
{
//Here is your Eloquent statement or SQL query;
}
}
just call this abc() method inside the controller like this
use ABC;
class AbcController extends Controller
{
private $_abc; // it is private variable
// this is constructor
public function __construct(ABC $abc)
{
$this->_abc= $abc;
}
public function abcMethod()
{
$this->_abc->abc();
}
}
Thanks
I don't believe I'm understanding your intention. You've stated:
Purpose is to move SQL queries inside model's class, that don't mess this code in controllers.
Why does the Order->myMethod() need calling inside the constructor? If you're trying to design your data access layer to work efficiently, you can use data repositories.

Laravel: use extended controller or Traits or something else?

To maintain my Laravel application and save myself from a lot of duplicate code I have made the following solution:
BaseController
class BaseController extends Controller
{
public function get($id){
return $this->baseService->get($id);
}
public function getAll(){
return $this->baseService->getAll();
}
}
BaseService
class BaseService
{
protected $model;
public function __construct($model){
$this->model = $model;
}
public function get($id){
return response()->json($this->model->where('id', $id)->first());
}
public function getAll()
{
return $this->model->get();
}
}
MyController
class MyController extends BaseController
{
protected $model;
protected $baseService;
public function __construct(){
$this->model= new Model();
$this->baseService = new BaseService($this->model);
}
/**
* This controller has all the functionality from BaseController now
*/
}
What I'm wondering if this is a good method. Should I stick with this or should I use a different approach? I've heard about Traits but not sure if they are doing the same thing. It's Laravel 5.5 I'm using.
Yes, traits are used to move methods out of a controller regularly. A good example that the Laravel framework uses is the ThrottlesLogin trait. Take a look at https://github.com/laravel/framework/blob/5.5/src/Illuminate/Foundation/Auth/ThrottlesLogins.php#L20
to see how the methods are moved outside of a controller but can be still accessed by importing the trait using the use keyword.
While traits would work for your use case I wouldn't use them here for the functionality you are looking for. I would use the repository pattern. It would better separate your code and make it more reusable.
Take a look at https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5/ for more information on the repository pattern. Basically, you would separate your code into a separate repository and use Laravel's built in IoC to inject the repository into your controller.
MyController
class MyController extends Controller
{
protected $repo;
public function __construct(MyRepository $myRepository)
{
$this->repo = $myRepository;
}
public function index()
{
$myStuff = $this->repo->all();
}
// you can also inject the repository directly in the controller
// actions.
// look at https://laravel.com/docs/5.5/controllers#dependency-injection-and-controllers
public function other(MyRepository $repo)
{
$myStuff = $repo->all();
}
}
This is the perfect use case for a Trait. Traits are intended for reusable functions. They're super simple to implement, and won't take more than a few minutes to change what you have.
Here is a great article on them: https://www.conetix.com.au/blog/simple-guide-using-traits-laravel-5

Declare value ONCE to use in multiple controller methods - Laravel 5.2

I currently have to declare my Stripe api key in every controller method that will make an api call to Stripe. For example
public function __construct()
{
\Stripe\Stripe::setApiKey(env('STRIPE_KEY'));
}
public function addCard()
{
Stripe::setApiKey(env('STRIPE_KEY'));
}
public function updateCard()
{
Stripe::setApiKey(env('STRIPE_KEY'));
}
public function deleteCard()
{
Stripe::setApiKey(env('STRIPE_KEY'));
}
This is getting very annoying as I have more than 10 methods that are doing this. My question is, is there a way i can declare the key somewhere ONCE and not have to call it in every controller method?
Yep, I'd do it in your AppServiceProvider. You'll find this at app/Providers/AppServiceProvider.php.
Stick it in the register method:
public function register()
{
Stripe::setApiKey(env('STRIPE_KEY'));
}
That will run during bootstrap for every request.
Alternatively you could set this in the constructor for your Controller. This would cause it to run for all actions in this one controller only.
class PaymentController extends Controller {
public function __construct() {
Stripe::setApiKey(env('STRIPE_KEY'));
}
public function addCard() {
...
I'd argue this is less desirable, your service providers should primarily be responsible for wiring up your dependencies. Up to you.

Laravel dependency injection into custom non-controller class fails in PHPUnit

all.
For a Laravel project I'm working on, I've started to use Dependency Injection in order to mock classes in my tests. However, I've found that if I try to inject into a custom class with no explicit parent, two things are true:
The dependency injection works correctly when running the application
The injection fails when running tests in PHPUnit
Here is some sample code similar to what I'm using:
DemoController
// The controller we're testing
class DemoController extends Controller
{
// The injection and constructor
private $helpLayer1;
public function __construct(HelpLayer1 $helpLayer1)
{
$this->helpLayer1 = $helpLayer1;
}
...
// The test function I call
public function testDeps()
{
$this->helpLayer1->testLayer1();
}
}
HelperLayer1
// Our first helper class
class HelperLayer1
{
private $helpLayer2;
public function __construct(HelpLayer2 $helpLayer2)
{
$this->helpLayer2 = $helpLayer2;
}
...
// The testing function
public function testLayer1()
{
// When called via route, this dumps the actual object
// When called via test, this returns null
dd($this->helperLayer2);
}
}
Helper1ServiceProvider
class Helper1ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer1', function()
{
return new HelperLayer1(App::make('HelperLayer2'));
});
}
[OR]
public function register()
{
$this->app->bind('HelperLayer1', 'HelperLayer1');
}
}
Helper2ServiceProvider
class Helper2ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer2', 'HelperLayer2');
}
}
I'm relatively new to using DI, so I'm not entirely sure that this set-up is correct, but I'm at a loss.
Any help would be greatly appreciated! Thank you!

IoC binding to a resourceful controller method, not constructor

Is it possible to bind an instance into a method parameter of a resourceful controller in laravel 4?
Is this even a good idea? If I have an object that I need for just one method, is it worth it to include it as a constructor parameter?
app/routes.php
Route::Resource('track', 'TrackController');
app/controller/TrackController.php
class TrackController extends BaseController {
public function __construct(/Foo/Bar p1, /Foo/Baz p2)
{
// All these bindings seem to work
}
public function show($id, /Foo/Xyz $xyz)
{
// This binding doesn't work, even though the exact same binding
// in the constructor will work.
}
}
Automatic Resolution works only for constructors:
When a type is not bound in the container, it will use PHP's Reflection facilities to inspect the class and read the constructor's type-hints. Using this information, the container can automatically build an instance of the class.
The best you could do in this case might be:
class TrackController extends BaseController {
public function __construct(/Foo/Bar p1, /Foo/Baz p2, /Foo/Xyz $xyz)
{
$this->xyz = $xyz;
}
public function show($id)
{
echo $this->xyz->property;
}
}

Resources