use of middleware in custom package devlopment in laravel - php

I want to build packages in which I want to make middleware which validate data from different services(different project) by just installing that package.
what is a step to making this type of command and publish in any project?
I read the document. I understand that how to make view(loadViewFrom), route(loadRouteFrom) but didn't find any methods for middleware like loadViewFrom, loadRouteFrom. and how to publish that packages.

In your service provider file you add a variation of the following:
use Illuminate\Routing\Router;
use yourpackageauthor\YourPackageName\App\Http\Middleware\YourMiddlwareClass;
...
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot(Router $router)
{
$router->middlewareGroup('yourMiddlwareName', [YourMiddlewareClass::class]);
}
For reference see:
https://github.com/jeremykenedy/laravel-blocker/blob/master/src/LaravelBlockerServiceProvider.php

Related

Laravel does not recognize the PHP class of Blade components

I develop my Laravel applications using Windows with Laravel Homestead. In Laravel Homestead I am using PHP 8.0.21 and Laravel 9.23.
I deployed my project to a host without any errors. However, Laravel does not recognize the PHP class of Blade components, making it impossible to use the application.
It is as if the component were anonymous. I put a dd('hi') in the class construct and nothing happens.
I cleared all Laravel caches using artisan optimize:clear. I cleared all server caches. I checked access permissions. Nothing solved, still not being able to use the application.
In my local environment the application works, but in hosting it doesn't. I don't know what else to check as there is no error log.
The hosting PHP version is 8.0.20, I don't believe that's the reason for the problem.
Can you help me?
Component call
<x-admin.sidebar.sidebar-main />
Component
<div>
The only way to do great work is to love what you do. - Steve Jobs
</div>
Class Component
<?php
namespace App\View\Components\admin\sidebar;
use App\Models\Menu;
use Illuminate\View\Component;
class SidebarMain extends Component
{
/**
* Menus da área administrativa.
*
* #var array
*/
public array $menus;
/**
* Create a new component instance.
*
* #return void
*/
public function __construct()
{
dd('xxxxxxxxxxx');
}
/**
* Get the view / contents that represent the component.
*
* #return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.admin.sidebar.sidebar-main');
}
}

How to load another Console/Kernel.php in Laravel project?

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();
});

How to update composer.json from Laravel controller

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()
{
}
}

Override Singleton in Laravel Container

I'm wondering if there's a simple way to override a singleton service set in the core of the Laravel framework?
e.g. I'm trying to rewrite the app:name command service '' with the following provider:
use Hexavel\Console\AppNameCommand;
use Illuminate\Console\Events\ArtisanStarting;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\ServiceProvider;
class NameCommandProvider extends ServiceProvider
{
/**
* Register any other events for your application.
*
* #param \Illuminate\Contracts\Events\Dispatcher $events
* #return void
*/
public function boot(Dispatcher $events)
{
$events->listen(ArtisanStarting::class, function ($event) {
$event->artisan->resolve('command.app.name');
}, -1);
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->singleton('command.app.name', function ($app) {
return new AppNameCommand($app['composer'], $app['files']);
});
}
}
I'm 100% everything is working due to extensive checks put no matter what order I put my service provider (above or below ConsoleSupportServiceProvider) it still loads the original AppNameCommand over my custom one.
I've already got a work around BUT it would be nice to know about the behaviour of singleton services for the future if this is at all possible? (This is using Laravel 5.2 if that makes any difference.)
There's actually a cleaner way to do this. You basically want to extend a core binding, which can be achieved by using the extend method:
$this->app->extend('command.app.name', function ($command, $app) {
return new AppNameCommand($app['composer'], $app['files']);
});
Jason Lewis has a really nice article regarding Laravel's IoC on Tutsplus. Make sure to check it out ;)
I looked at this case and it seems it not the easy one. If you use singleton in your custom Provider it will be finally overridden by default provider (deferred one) so it seems it won't be the way.
After checking that simple approach doesn't work, what you need to do in such case is analysing what is happening when Laravel registers this command.
So in your case you search first for command.app.name - you see it's in Illuminate\Foundation\Providers\ArtisanServiceProvider and there is method registerAppNameCommand you would like to probably override.
So now you look for occurences of ArtisanServiceProvider to see where it's launched - you see it's in Illuminate\Foundation\Providers\ConsoleSupportServiceProvider in $providers property (which you would like probably to change).
So finally you should look for occurrences of ConsoleSupportServiceProvider and you see it's in config/app.php.
So what you need to do in this case:
Change in config/app.php - change Illuminate\Foundation\Providers\ConsoleSupportServiceProvider into your custom one ConsoleSupportServiceProvider
In your custom one you should extend from \Illuminate\Foundation\Providers\ConsoleSupportServiceProvider but change in $providers from Illuminate\Foundation\Providers\ArtisanServiceProvider into your custom ArtisanServiceProvider
finally create custom ArtisanServiceProvider which will extend from \Illuminate\Foundation\Providers\ArtisanServiceProvider where you override registerAppNameCommand using custom class in singleton
Using this way you will achieve your goal (I've verified it that custom class will be used running command php artisan app:name).
Alternatively you might want in your custom ArtisanServiceProvider remove 'AppName' => 'command.app.name', from $devCommands and use your custom service provider as you showed where you register your singleton but I haven't tried this approach.

Laravel 5, can't share data with view using boot in AppServiceProvider

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.

Categories