Im currently learning how laravel framework builded and came to service provider section. in class DatabaseServiceProvider which extends ServiceProvider class i see this line of code :
$this->app->singleton('db.factory', function ($app)
{
return new ConnectionFactory($app);
});
im confuse what is app in $this->app, whether app is an object from application class instance and if it does when it is instantiated so it can be used from DatabaseServiceProvider class since i dont see its instantiation process. thnks before for answering this newbie question.
In Laravel, the app variable is a service container. Think of it like a heart of the framework. Everything you use from Facades to DB connections is stored in there.
Moreover, you can store your own objects in the container by using the method you specified ($this->app->singleton()). There are actualy many more ways to interact with the container. The best way to research this is to look into Laravel's documentation (Laravel Service Container)
The app object is being instantiated on Laravel bootstrap so you can't see it in the service provider. Though I was curious enough to dig deep into the framework to find it. The class itself is located in Illuminate\Foundation\Application and is instantiated in bootstrap/app.php.
Related
I am trying to extend the PHPUnit in Laravel, but I’ve faced a problem - application instance is not loaded. I'll do my best to explain my problem.
I want to implement TestListener interface and TestListenerDefaultImplementation trait to use PHPUnit Listener feature. But also I need to use my models in this listener.
As you can guess I cannot do this because Laravel’s CreateApplication trait is used only in a pair with its BasicTest. Thus the listener does not know anything about the application instance. How can I manage to do this with listeners?
My phpunit.xml file:
https://gist.github.com/andrewgorpenko/1a7d472ab4747f081c7da247261e29d1
This is an intended feature of the framework and what I did is a kind of "bad practice".
Have recently starting using UserFrosting to as part of a project and I'm having some problems using Facades within UserFrosting and would appreciate some help if possible.
I am attempting to use the File facade from within a UserFrosting controller to create a folder on the local filesystem using the following code
use Illuminate\Support\Facades\File;
......
$directoryCreated = File::makeDirectory($directoryPath);
However at runtime i get the following error
PHP Fatal error: Call to a member function makeDirectory() on null in /var/www/test-app/userfrosting/vendor/illuminate/support/Facades/Facade.php on line 210
It seems that the UserFrosting app does not recognise the File facade (or any other facacde - i also tried Storage) and it has not been registered with the app.
Is it possible to use the facade classes with UserFrosting?
If so do I have to register them somewhere within the UserFrosting app config?
Any direction pointers would be greatly appreciated.
Thanks in advance!
From the Facade documentation:
Laravel "facades" serve as "static proxies" to underlying classes in the service container...
So, it looks like Laravel's facades depend on Laravel's service container. You can read more about how Laravel sets up the default facades here: https://www.sitepoint.com/how-laravel-facades-work-and-how-to-use-them-elsewhere/#how-laravel-aliases-the-facades
Unfortunately, UserFrosting does not use Laravel's service container. Rather, it uses Slim, which has its own service container. In Slim v2 (which UF 0.3.1 uses), the Slim application itself is the service container.
You can define services for UF in initialize.php. So, you might try something like:
$app->filesystem = new \Illuminate\Filesystem\Filesystem();
Then later, you can use the filesystem service like:
$app->filesystem->makeDirectory($directoryPath);
You could try to use Slim's container to allow the Facade to resolve its accessor (it will use array access on the container to resolve it). You would have to make sure that the binding the facade uses exists. You can take a look at the Service Provider that corresponds to the service you want to use to know how its setting up the binding.
The File facade is accessing the binding 'files' (Illuminate\Filesystem\Filesystem).
\Illuminate\Support\Facades\Facade::setFacadeApplication($container);
\Illuminate\Support\Facades\File::makeDirectory(...);
Its worth a shot, but its mostly the binding that is being resolved that is important.
I am building a Laravel 5.2 App that will connect to a database that I don't have available to me whilst developing (it is a legacy database that I cannot install locally).
What is the cleanest way in Laravel to build my application so that I can develop using one interface, and then switch over to another when I push my project to the live environment?
In the past, I've had 2 classes, both of which have the same functions, and then in a configuration file, I would say which class it uses. Just wandering if there is a better way using Laravel? Or if there is a way of doing this already baked in?
One way I can think of achieving this is to switch the instance of the dependency injection when you're on local and production environment.
class ControllerExample
{
public function index( SomeInterface $data )
{
//...
}
}
So in this example the controller index method needs SomeInterface which would be injected automatically. For local development you can resolve this interface to your stub class and for production you can switch to the real class. You can do this by registering the binding of the interface in the app / Providers / AppServiceProvider.php in the register() method:
if ($this->app->environment() == 'local') {
$this->app->when('App\Your\ControllerExample')
->needs('App\SomeInterface')
->give('App\YourStubbedClass');
} else {
$this->app->when('App\Your\ControllerExample')
->needs('App\SomeInterface')
->give('App\YourRealClassWorkingWithTheRealDatabase');
}
What this basically does is when your env is local the dependency in your controller will be resolved with the stub class, otherwise on other envs it will be the real class.
This question already has an answer here:
How to use DependencyInjection from symfony in stand alone application with commands?
(1 answer)
Closed last year.
A Symfony novice here. After reading some of the Symfony documentation and some answers here at SO, I am now almost completely confused.
I am trying to use the console application component and create a small db-aware console application.
Many people state that in order to use Symfony's DI features it would be enough to inherit my command class not from Symfony\Component\Console\Command\Command but from ContainerAwareCommand.
However when I try this I get a Method Not Found error on an application::getKernel() call.
I have a feeling that DI features are in fact not available in a console application based on the console component. Is there another kind of Symfony console application, for example, based on the full-blown framework?
I very much like the simple framework provided by the console component Symfony\Component\Console\Application. But the question is then - what to do for dependency injection and DBAL? All examples that I find seem to refer to the full Symfony framework and get me just all the more stuck.
Just a quick update on my progress if anybody stumbles upon the same problems.
I incorporated into my project the PHP-DI dependency injection framework, which seems to be working fairly well with no configuration (so far) - it figures out quite a lot by reflection, actually.
The same way, Doctrine\DBAL is included as a standalone library (I opted against the O/RM part of it, as it is really a tiny project and I'm on a much firmer ground with SQL than anything else) and the connection is simply returned by a connection provider which is injected wherever needed by the DI.
One thing I couldn't figure out is how to have the command classes instantiated by the DI library without my help, so I actually had to inject the container itself into my overridden application class and override the getDefaultCommands() where I then pull the instances out of the container manually. Not ideal but will have to do for now.
If your command extends ContainerAwareCommand
...
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
...
class MyCommand extends ContainerAwareCommand
{
The DI container is available with the getContainer() method. (like in a standard controller), ex:
$this->validator = $this->getContainer()->get('validator');
I don't know if your question is still relevant, but I have an answer as I stumbled across the same problem here.
You just have to create the kernel yourself and give it to the \Symfony\Bundle\FrameworkBundle\Console\Application that extends the basic \Symfony\Component\Console\Application.
<?php
// CronRun.php
require __DIR__.'/../../../../vendor/autoload.php';
require_once __DIR__.'/../../../../app/AppKernel.php';
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel);
$application->add(new \KingdomHall\TaskBundle\Command\CronCommand());
$input = new \Symfony\Component\Console\Input\StringInput('k:c:r');
$application->run($input);
You could use a solution I just pushed it to packagist.org. Includes full working symfony/dependency-injection. You're welcome to give it a shot. use composer to create your own project composer create-project coral-media/crune project_dir or just clone the repository.
https://packagist.org/packages/coral-media/crune
You only need to install DBAL dependencies (I don't suggest ORM if you don't really need it). Configure connection parameters in .env and just define a service to handle connection. That service can be injected in your Commands using public setMyService($myService) method with #required annotation. Also you could create a Connection class and bind is as parameter in your command constructor.The crune boilerplate also supports autowire and autoconfiguring features.
is it possible overwrite/extend Symfony\Component\DependencyInjection\Container::get() method? I want automatic creating service, when it is not contain in container, but class of service exists.
For example:
Name of service is My.MyBundle.Model.FooRepository
Service with this name doesnt exists, but when i call:
$container->get('My.MyBundle.Model.FooRepository');
check class_exists for \My\MyBundle\Model\FooRepository and when its exists, add to container and return it. Dependencies of this new services will be resolve by kutny/autowiring-bundle.
This feature can be extended only for some namespaces or interfaces and in production enviroment can be cached, but for developing will be great helper.
Any idea?
This is not directly answering your question but maybe it's answering your need: if you want to have "auto-wiring" inside your Symfony project, you can use PHP-DI inside Symfony. PHP-DI is an alternative container that can do auto-wiring (which Symfony does not).
Have a look at the Symfony 2 integration documentation to see if it can fit your bill.