I have a running Laravel application which has the default Console/Kernel.php where all my scheduled commands are defined as usual.
But now I have another Laravel application that I am trying to merge with this existing application, and I have created a folder inside the existing Laravel application and I am using a Service Provider to load all the things. This way I can keep the code of the two projects separate but at the same time all features under the same repository.
<?php
namespace SecondApp;
use Illuminate\Support\ServiceProvider;
class SecondAppServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register()
{
include __DIR__ . '/routes/web.php';
include __DIR__ . '/routes/api.php';
$this->app->register('SecondApp\App\Providers\AppServiceProvider');
$this->app->register('SecondApp\App\Providers\AuthServiceProvider');
$this->app->register('SecondApp\App\Providers\BroadcastServiceProvider');
$this->app->register('SecondApp\App\Providers\EventServiceProvider');
$this->app->register('SecondApp\App\Providers\JobServiceProvider');
$this->app->register('SecondApp\App\Providers\MailerServiceProvider');
$this->app->register('SecondApp\App\Providers\RouteServiceProvider');
$this->app->register('SecondApp\App\Providers\StorageServiceProvider');
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
$this->loadMigrationsFrom(__DIR__ . '/database/migrations/');
$this->publishes([
__DIR__ . '/config/' => config_path()
], 'second-app-config');
$this->publishes([
__DIR__ . '/resources/' => base_path('resources')
], 'second-app-resources');
}
}
This is what my service somewhat looks like. Everything else seems to work well, roues, migrations, registering service providers and so on, but this second project now also has Console/Kernel.php file. And those commands are not being called yet, obviously because laravel doesn't know about it. So I am wondering how can I tell Laravel to look at that as well? Is this possible, or will I have merge the code into one main Kernel.php?
I have the same question about Http/Kernel.php as well, but I am sure if someone can suggest how to make one work, I can make the other work as well.
To load commands, need to add them like this in the register method of service provider
$this->commands([
App\Console\Commands\CommandOne::class,
App\Console\Commands\CommandTwo::class,
]);
and so on, keep adding commands to the array.
And to schedule these commands refer to this answer -> How to schedule Artisan commands in a package?
So add something like this to the boot method of your service provider:
$this->callAfterResolving(Schedule::class, function (Schedule $schedule) {
$schedule->command('some:command')->everyMinute();
});
Related
I just created a simple Laravel CLI package in Laravel 8. My custom command doesn't appear in php artisan list and the provider needs to register manually into config/app.php to make it work. As far as I know, we don't need to register the provider manually in Laravel 5.5+.
Here is my provider source code:
<?php
namespace Robyfirnandoyusuf\BadOmen;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\ServiceProvider;
use Robyfirnandoyusuf\BadOmen\Commands\Migrate;
class BadOmenServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
if ($this->app->runningInConsole()) {
$this->commands([
Migrate::class
]);
}
}
public function register()
{
}
}
and this is the structure of the directories:
Anyone have solution for this problem?
Solved, by adding providers property in the package's composer.json file, with a value of [Robyfirnandoyusuf\BadOmen\BadOmenServiceProvider::class]
So I'm building a Laravel package and there is a special features that requires updating composer by adding a psr-4 namespace which points to a directory in Laravel base path.
I have tried this so far but doesn't work.
$loader = include(base_path('vendor/autoload.php'));
$loader->add('Classes\Weather', base_path('modules'));
Later:
$weather = new Classes\Weather\WeatherSite();
You might check this thread, which gives some solutions:
https://github.com/composer/composer/issues/1906#issuecomment-51632453
After several trials and going through Composer documentation, I was able to come up with this which works:
NB: The reason why I needed this solution is to enable me add a Psr4 path automatically from a Laravel package without manually adding a specific path required in the package manually in composer.json
Add this in the boot method of your package service provider , mine is DigitlimitModuleServiceProvider
use Illuminate\Support\ServiceProvider;
class DigitlimitModuleServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$autoload = require base_path('vendor/autoload.php');
$autoload->addPsr4('Digitlimit\\Module\\', base_path('modules'));
$autoload->register();
if(!file_exists(base_path('modules'))){
\File::makeDirectory(base_path('modules'));
//works as long as there is permission
}
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
}
}
so I have created my own blog package in a structure of Packages/Sitemanager/Blog I have a service provider that looks like the following:
namespace Sitemanager\Blog;
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
class BlogServiceProvider extends LaravelServiceProvider {
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = false;
/**
* Bootstrap the application events.
*
* #return void
*/
public function boot() {
$this->handleConfigs();
$this->handleMigrations();
$this->handleViews();
$this->handleRoutes();
}
/**
* Register the service provider.
*
* #return void
*/
public function register() {
// Bind any implementations.
$this->app->make('Sitemanager\Blog\Controllers\BlogController');
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides() {
return [];
}
private function handleConfigs() {
$configPath = __DIR__ . '/config/blog.php';
$this->publishes([$configPath => config_path('blog.php')]);
$this->mergeConfigFrom($configPath, 'blog');
}
private function handleTranslations() {
$this->loadTranslationsFrom(__DIR__.'/lang', 'blog');
}
private function handleViews() {
$this->loadViewsFrom(__DIR__.'/views', 'blog');
$this->publishes([__DIR__.'/views' => base_path('resources/views/vendor/blog')]);
}
private function handleMigrations() {
$this->publishes([__DIR__ . '/migrations' => base_path('database/migrations')]);
}
private function handleRoutes() {
include __DIR__.'/routes.php';
}
}
Now, what i would like to do is run the migrations dynamically if they have never been run before or within an installation process i suppose. I've seen in older documentation you could so something like this:
Artisan::call('migrate', array('--path' => 'app/migrations'));
However, this is invalid in laravel 5, how can I approach this?
Artisan::call('migrate', array('--path' => 'app/migrations'));
will work in Laravel 5, but you'll likely need to make a couple tweaks.
First, you need a use Artisan; line at the top of your file (where use Illuminate\Support\ServiceProvider... is), because of Laravel 5's namespacing. (You can alternatively do \Artisan::call - the \ is important).
You likely also need to do this:
Artisan::call('migrate', array('--path' => 'app/migrations', '--force' => true));
The --force is necessary because Laravel will, by default, prompt you for a yes/no in production, as it's a potentially destructive command. Without --force, your code will just sit there spinning its wheels (Laravel's waiting for a response from the CLI, but you're not in the CLI).
I'd encourage you to do this stuff somewhere other than the boot method of a service provider. These can be heavy calls (relying on both filesystem and database calls you don't want to make on every pageview). Consider an explicit installation console command or route instead.
After publishing the package:
php artisan vendor:publish --provider="Packages\Namespace\ServiceProvider"
You can execute the migration using:
php artisan migrate
Laravel automatically keeps track of which migrations have been executed and runs new ones accordingly.
If you want to execute the migration from outside of the CLI, for example in a route, you can do so using the Artisan facade:
Artisan::call('migrate')
You can pass optional parameters such as force and path as an array to the second argument in Artisan::call.
Further reading:
https://laravel.com/docs/5.1/artisan
https://laravel.com/docs/5.2/migrations#running-migrations
For the Laravel 7(and probably 6):
use Illuminate\Support\Facades\Artisan;
Artisan::call('migrate');
will greatly work.
I just read the Laravel 5 doc on configuration based on your environment http://laravel.com/docs/5.0/configuration#environment-configuration
I understand how the .env files can be used to configure some variables but how do I configure what service providers get loaded based on the environment?
For example in my ''local'' environment I use this debugbar plugin which needs a service provider but I don't want to define it in config/app.php for production.
In Laravel 4.2 I could just create config/local/app.php but that doesn't seem to work anymore, what is the alternative?
This article was helpful for me:
https://mattstauffer.co/blog/conditionally-loading-service-providers-in-laravel-5
And this is what I've done and it works:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
if ($this->app->environment('local')) {
$this->app->register('Barryvdh\Debugbar\ServiceProvider');
}
}
}
I believe if you set APP_DEBUG to false in your .env file the debugbar will go away automatically.
Also I wrote a middleware class to take care of that.
The handle method could look like this in your case:
public function handle($request, Closure $next)
{
if (app()->environment('production'))
\Debugbar::disable();
else
\Debugbar::enable();
return $next($request);
}
Then you just add it to the list of middleware in app/Http/kernel.php and you're good to go.
I have some additional conditions and more environments so this exact code is not tested but it should work and you should get the idea.
Take care.
Just done a fresh install of L5 and, as per the documentation, i'm trying to share data with all views using a simple share method in the AppServiceProvider class.
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use View;
class AppServiceProvider extends ServiceProvider {
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
View::share('website', 'test');
}
/**
* Register any application services.
*
* This service provider is a great spot to register your various container
* bindings with the application. As you can see, we are registering our
* "Registrar" implementation here. You can add your own bindings too!
*
* #return void
*/
public function register()
{
$this->app->bind(
'Illuminate\Contracts\Auth\Registrar',
'App\Services\Registrar'
);
}
}
route file:
Route::get('/', function(){
return view('test');
});
blade file:
<h1>Test</h1>
{{ $website }}
This should be really easy, so i'm wondering if i've made a very obvious mistake at the installation stage.
Thanks
Most probably you should clear the compiled.php file by running:
php artisan clear-compiled
or by manual deleting vendor/compiled.php (in previous L5 versions it's storage/framework/compiled.php).
Here's the explanation. Laravel pre-compiles certain classes that are used on basically every request. This serves the purpose of performance optimization. Files to compile can be specified in config/compile.php under files. The default one looks like this:
'files' => [
realpath(__DIR__.'/../app/Providers/AppServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/BusServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/ConfigServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/EventServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/RouteServiceProvider.php'),
],
That means if you change one of those precompiled files, changes won't be applied immediately (if compiled.php exists) but only after you run php artisan optimize again or after you run php artisan clear-compiled to clear the compiled.php file.