What does the make() method do in Laravel? - laravel

In the Laravel documentation, I found the following - https://laravel.com/docs/5.4/container#the-make-method
but I am still confused as to what exactly the make() method does. I know the create() method uses the make() method and then persists them into the database, so does make() methods just temporarily save it in php tinker or something? Sorry, I'm Laravel noob. I'm trying to figure out these functions. Thank you! :)

The make method will return an instance of the class or interface you request.
Where you request to make an interface, Laravel will lookup a binding for that interface to a concrete class.
E.g.
$app->make('App\Services\MyService'); // new \App\Services\MyService.
One advantage to using the make method, is that Laravel will automatically inject any dependencies the class may define in it's constructor.
E.g. an instance of the Mailer class would be automatically injected here.
namespace App\Services;
use \Illuminate\Mail\Mailer;
class MyService
{
public function __construct(Mailer $mailer) {
$this->mailer = new Mailer;
}
}

I discovered recently that when you use make (), you are installing the class and you can access the methods of that class or model, this is a useful for the Test and validate that you are getting what you want Example:
User model
class User extends Authenticatable
{
public function getRouteKeyName ()
     {
         return 'name';
     }
}
Test user
class UserTest extends TestCase
{
public function route_key_name_is_set_to_name ()
     {
$ user = factory (User :: class) -> make ();
$ this-> assertEquals ('name', $ user-> getRouteKeyName ());
// When you access the getRouteKeyName method you get the return, that is 'name'
}
}
On the other hand if you use "create" that would give an error because you are creating a user

Related

Laravel dependency injection without relying on the controller

I'm trying to figure out how to inject a dependency into a class in Laravel.
My structure:
SimpleController extends BaseController
{
public function example(SimpleModel $model, SimpleValidationRequest $request)
{
$result = $model->doStuff()
return $this->makeResponse($result);
}
}
SimpleModel extends Model
{
public function doStuff(ComplexService $service)
{
$service->doComplexLogic($this);
}
}
I have registered the ComplexService in my own service provider:
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(ComplexService::class);
}
}
I want to inject the service straight into the simpleModel's doStuff method, without having to inject it into the controller and then into the model. We're busy moving a monolithic application to Laravel and have service classes that contain all the complex business logic. Much of the logic is shared between different classes, so a controller method might call a model that calls a service that ends up making 4 or 5 calls to other services, and I want to be able to inject another service into any method that needs it without having to send it down from the controller all the way through to the bottom method that might need it.
Is there a way to do this? I have been looking online but everything I've found has required me to inject the service into the controller and then sending it through the application from there, which I want to avoid.
You can simply call the singleton inside the method via the app() helper
SimpleModel extends Model
{
public function doStuff(ComplexService $service)
{
app()->singleton(ComplexService::class)->doComplexLogic($this);
}
}
or recover the singleton by injecting it in the model via it's __construct() method.

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.

How to use different method of a controller in laravel application

In my laravel application i should use some create and update method of some controller in another controller
According to my search is not a good thing to call a method from controller in another
I cant see the why don't call a controller method in another controller
I'm doing this way :
class Controller extends BaseController
{
protected $variable;
public function __construct()
{
$this->variable = "Hello";
}
}
and
class ClientController extends Controller
{
public function __construct()
{
parent::__construct();
}
}
The __constructor is a magic method of class. It calls when you trying to create instance of class. So there is no way to use constructor without creating an instance or extendeding from another class. If you have a common code in different classes there a best way to use traits. thats give you an opportunity to include your trait and use methods ,making your code beutiful , flexible , readable following principes DRY,KISS.
you can create a base class with constructor and extend other controller of it
or you can put your code in to Http\Controllers\controller.php ('main controllers constructor')
also you can use trait

Issue in creating REST Service using laravel

We are trying to develop an Android app that required a REST API to show data from web server.
We tried to use Laravel resource to create REST service like below:
Route::resource('list', 'ListController');
namespace App\Http\Controllers;
use mymodel
class ListController extends Controller
{
public function getShow($id)
{
$Jsondata=list($id);
return $JsonData;
}
}
But it's not working as expected need some token key or some other authentication and authorization need to know how to set.
We should utilize the Repository / Gateway design pattern:
For example, when dealing with the User model, first create a User Repository. The only responsibility of the user repository is to communicate with the database (performing CRUD operations). This User Repository extends a common base repository and implements an interface containing all methods we require:
class EloquentUserRepository extends BaseRepository implements UserRepository
{
public function __construct(User $user) {
$this->user = $user;
}
public function all() {
return $this->user->all();
}
public function get($id){}
public function create(array $data){}
public function update(array $data){}
public function delete($id){}
// Any other methods we need go here (getRecent, deleteWhere, etc) }
Then, create a service provider, which binds your user repository interface to your eloquent user repository. Whenever you require the user repository (by resolving it through the IoC container or injecting the dependency in the constructor), Laravel automatically gives you an instance of the Eloquent user repository you just created. This is so that, if you change ORMs to something other than eloquent, you can simply change this service provider and no other changes to your codebase are required:
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider {
public function register() {
$this->app->bind(
'lib\Repositories\UserRepository', // Assuming you used these
'lib\Repositories\EloquentUserRepository' // namespaces
);
}}
Next, create a User Gateway, who's purpose is to talk to any number of repositories and perform any business logic of your application:
use lib\Repositories\UserRepository;
class UserGateway {
protected $userRepository;
public function __construct(UserRepository $userRepository) {
$this->userRepository = $userRepository;
}
public function createUser(array $input)
{
// perform any sort of validation first
return $this->userRepository->create($input);
}}
Finally, create our User web controller. This controller talks to our User Gateway:
class UserController extends BaseController
{
public function __construct(UserGatway $userGateway)
{
$this->userGateway = $userGateway;
}
public function create()
{
$user = $this->userGateway->createUser(Input::all());
}}
By structuring the design of your application in this way, you get several benefits: you achieve a very clear separation of concerns, since your application will be adhering to the Single Responsibility Principle (by separating your business logic from your database logic) . This enables you to perform unit and integration testing in a much easier manner, makes your controllers as slim as possible, as well as allowing you to easily swap out Eloquent for any other database if you desire in the future.
For example, if changing from Eloquent to Mongo, the only things you need to change are the service provider binding as well as creating a MongoUserRepository which implements the UserRepository interface. This is because the repository is the only thing talking to your database - it has no knowledge of anything else. Therefore, the new MongoUserRepository might look something like:
class MongoUserRepository extends BaseRepository implements UserRepository
{
public function __construct(MongoUser $user) {
$this->user = $user;
}
public function all() {
// Retrieve all users from the mongo db
}}
And the service provider will now bind the UserRepository interface to the new MongoUserRepository:
$this->app->bind(
'lib\Repositories\UserRepository',
'lib\Repositories\MongoUserRepository'
);
Throughout all your gateways you have been referencing the UserRepository, so by making this change you're essentially telling Laravel to use the new MongoUserRepository instead of the older Eloquent one. No other changes are required.
Number one is that what is not working? if you mean that the response is not showing then its because your function actually doesn't even seem to be going any where, and number two are you new to Laravel?
Okay if this is what you have:
namespace App\Http\Controllers;
use mymodel;
class ListController extends Controller
{
public function getShow($id)
{
$Jsondata=list($id); return $JsonData;
}
}
Then I can be safe to say a lot of things is wrong.
To my understanding using Route::resource('list', 'ListController'); in your routes file creates show, edit, update and destroy paths, and also expects to see these functions too (I have not proven this to the core though) but thats my understanding.
so you can simply start laravel life by doing having your routes with
Route::get('list', 'ListController#show')
Then change your ListController to something like this:
namespace App\Http\Controllers;
use mymodel;
class ListController extends Controller
{
public function show($id)
{
$jsonData= ['my' => 'json data'];
return $jsonData;
}
}
If this works for you, then cool else so many thing might already be wrong with your setup.
Note: you might need to take your time to learn to use laravel from the documentation page. If API is your interest then try DIngo api. Also try to learn to use markup :)
Hope this helps :)

Injecting Interface on class (Laravel Package)

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.

Resources