Given I want to initialize a class.
I can do
$testClass = App::make('TestClass') //of course given its already binded on container
and
$testClass = new TestClass;
What is the difference, does App::make() when its called resolves the container all the time or ?
Yes, App::make resolves the class using Laravel container every time. Using the containter is a great idea since you can create an advanced binding, bind a class to an interface, bind a class as a singleton etc.
new Class syntax will create a new instance of the Class.
App:make() resolves all class constructor dependencies from application container or uses autowiring if dependency is not registered in container.
Related
Laravel 5.6 Documentation says:
There is no need to bind classes into the container if they do not
depend on any interfaces. The container does not need to be instructed
on how to build these objects, since it can automatically resolve
these objects using reflection.
I don't understand it.
Does it mean that I don't have to use any bindigs inside provider's register method if I don't use interfaces?
Then, how can I use dependency injection if I don't use bindigs?
P.S.:
in my understending:
"interface" - is this
"bindings" - is bind() and singelton() inside register
If you have :
class Something {
}
You can do app()->make(Something::class) without needing to bind it before hand. The container knows that it can just call the default constructor.
The same goes for
class SomethingElse {
public function __construct(Something $s) { }
}
In this case the constructor will also go through the dependency injection. This is all handled automatically by the container.
However this obviously cannot work for interfaces since interfaces can't be constructed.
Also if you need something to be bound as a singleton you need to bind it explicitly using app()->singleton(...)
I am getting error:
GitHubApp::__construct() must be an instance of App\Project\Repositories\GitProviderRepository
I thought Laravel does some kind of magic when it come to __construct() so i don't have to inject it into new GitHubApp();?
use App\Project\Repositories\GitProviderRepository;
class GitHubApp
{
private $gitProviderRepository;
public function __construct(GitProviderRepository $gitProviderRepository)
{
$this->gitProviderRepository = $gitProviderRepository;
}
}
In other class:
return new GitHubApp();
When calling new GithubApp(), you relied on yourself to build the GithubApp instance, Laravel does not responsible for building that instance.
You have to let Laravel resolve the dependencies for you. There are numbers of way to achieve this:
Using App facade:
App::make(GithubApp::class);
Using app() helper method:
app(GithubApp::class);
Or using the resolve() helper method:
resolve(GithubApp::class);
Behind the scene, your class type and its dependencies will be resolved and instantiated by the Illuminate\Container\Container class (the parent class of Application). Specifically by the make() and build() methods.
Hope this help! :)
You can try as:
return app(GitHubApp::class);
or
return app()->make(GitHubApp::class)
It is done by the powerful IoC container of Laravel to resolve classes without any configuration.
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.
Docs
Laravel 5 offers automatic dependency resolving if I type-hint the needed class/interface. But how should they be instantiated? Example:
public function __construct(Dependency $dependency) {
$this->dependency = $dependency;
}
And then, in another method, I'd like to create two instances, like this:
$one = new Dependency(1);
$two = new Dependency(2);
What is the most flexible and test-friendly way to do this?
Excuse my poor joke, but it depends.
It looks like you have misunderstood the dependency resolving a little bit.
In your example the property 'dependency' allready contains an instantiated object. If you need two different instances within another method you may instantiate them there, inject a container or use a factory. It depends on your needs.
a very short introduction to laravel dependency resolving
The automatic dependency resolving in laravel is provided by the service container and it is used to deliver an (allready) instantiated object. The resolved object must be binded to service container. The best way to do this is via service providers. Within the register method of a service provider you are able to do your bindings
$this->app->bind('Dependency', function ($app) {
return new Dependency();
});
In this example the container will return a new instance every time it is called.
If you need the same instance every time you may bind a singleton
$this->app->singleton('Dependency', function ($app) {
return new Dependency();
});
I am currently building an MVC application in PHP (not using any frameworks). I am using yadif (https://github.com/beberlei/yadif) for dependency injection.
I would like to build a login module. It should be able to use adapters, for example one might be able to set that logins are authenticated using the MySql database or some LDAP directory. This setting would be done in the admin area and is stored in a database.
I imagine that I would have an abstract adapter:
<?php
abstract AbstractLoginAdapter{
abstract function login($username, $pass){}
}
I would then just implement adapters like so:
<?php
MySQLLoginAdapter extends AbstractLoginAdapter{
public function login($username, $pass){
//do stuff
}
}
That's all nice and well, but how do I create an instance of the adapter? Usually, dependencies would be injected using yadif via the constructor:
<?php
class loginController{
private $_adapter;
public function __construct(AbstractLoginAdapter $adapter){
$this->_adapter = $adapter;
}
}
However, since I don't know which concrete adapter will be injected, I can't set that in a configuration before hand. Yadif allows me to create a configuration which I then need to pass to the container:
$builder = new Yadif_Builder();
$builder->bind("loginController")
->to("loginController")
->args($SelectedLoginAdapter);
Since the application uses a front controller, a DI container is created there. It then creates a routing object etc.
In light of this, should I pass a reference of that container down to the loginController object, and then use that container to instantiate my adapter?
Or should I instantiate a new container within my loginController object and then just load in an instance of the adapter?
I would do the first: pass a reference down to your controller. You'll want to use a single Dependency Injector Container (DIC) in your application. You don't want to create a new DIC whenever you need access to it. That would lead to duplication of objects stored in the DIC.
I know this is how Symfony 2 does it. All controllers (and many other classes) implement the ContainerAware interface. That interface has a single method setContainer() that is used to pass down a reference to the DIC.
I don't know about your specific DI tool but from a DI point of view you would be specifying which type to use. The container itself is responsible for instantiating a new instance (and possibly of all the dependencies of that type as well) of the configured type.
The benefit of DI in your example would be that you could deploy exactly the same code with a different configuration with 1 installation using LDAP and the other using MySQL authentication.
Refactor type hinting ("AbstractLoginAdapter") to ("MySQLLoginAdapter").
If you call abstract class method in the new __CLASS__ // Fatal Error.
how do i get access to a current instance of class that's already running in PHP?
in my one PHP class, I want to call a function from another that's already running as a server. so i cant create a new instance.
thanks.
p a
What you want is called a singleton.
With a Singleton you can have only one instance of your class running on the server.
To do so you must :
store your instance in your class as a static field
have a private constructor so you can't create instances yourself
have a static method which call the constructor once, and return the only instance
Resources :
Wikipedia - Singleton pattern
php.net - singleton
On the same topic :
Creating the Singleton design pattern in PHP5
What is so bad about Singletons