I created an event and listener in Laravel, but the listener doesn't fire. It does actually fire on my colleague's machine. That makes me think that the actual code works and that the configuration is in order.
Listener:
<?php
namespace App\Listeners\Consensus;
use App\Events\Consensus\ManualGroupChannelNotificationEvent;
use Illuminate\Support\Facades\Log;
/**
* Class ManualGroupChannelNotificationListener
* #package App\Listeners\Consensus
*/
class ManualGroupChannelNotificationListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param ManualGroupChannelNotificationEvent $event
* #return void
*/
public function handle(ManualGroupChannelNotificationEvent $event)
{
Log::debug('Listener');
}
}
Event:
<?php
namespace App\Events\Consensus;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Support\Facades\Log;
/**
* Class ManualGroupChannelNotificationEvent
* #package App\Events\Consensus
*/
class ManualGroupChannelNotificationEvent
{
use Dispatchable;
/*
* ExternalComment constructor.
*
* #param Comment $comment
* #param User $currentUser
*/
public function __construct()
{
Log::debug('Event');
}
}
EventServiceProvider:
protected $listen = [
'App\Events\Consensus\ManualGroupChannelNotificationEvent' => [
'App\Listeners\Consensus\ManualGroupChannelNotificationListener',
],
];
Firing the event:
event(new ManualGroupChannelNotificationEvent());
I ran all commands to clear cache etc., but still it doesn't work.
php artisan clear-compiled
php artisan config:clear
php artisan cache:clear
composer dump-autoload
php artisan queue:restart
If this code works on another machine, what else can I do to make it work on mine?
Other info:
My logging does work; the Event-message is logged.
Other, similar events do work.
First thing, try to apply chmod -R 777 storage/logs it might be just an authorisation issue.
Maybe the registering of your events failed, you can try to add this to your EventServiceProvider
/**
* Determine if events and listeners should be automatically discovered.
*
* #return bool
*/
public function shouldDiscoverEvents()
{
return true;
}
Is your second working machine the same as the first one ?
Ok. I tested your setup in Laravel 5.8 by manually creating your classes and both the event and listener are logged correctly.
I will suggest you avoid manually creating your event and listener classes. Instead, first specify them in EventServiceProvider.php as you have done:
protected $listen = [
'App\Events\Consensus\ManualGroupChannelNotificationEvent' => [
'App\Listeners\Consensus\ManualGroupChannelNotificationListener',
],
];
Then generate the necessary class files automatically using this artisan command
php artisan event:generate
You can now modify the generated classes by including the use Illuminate\Support\Facades\Log; directive line and then use the Log::debug() method call in your event constructor and listener handler methods.
Try this suggested method and see if it works. I don't think it is a case of storage access permission since the event logs successfully in your case.
I deleted the repo and cloned again, it works now.
Related
I am developing a Laravel application for a client company of mine. That company has a server guy. In the middle of the development process, I asked him to set up a server for the application. But he set up a server without any kind of automated deployments procedure instead he gave me a C-Pannel to deploy the changes manually. The application became so complex and now manual deployments became a very tedious task. I am manually building js and css and uploading them to the server. After a heated argument with him, I finally made him work on automated deployments. Instead of properly putting deployments he has put it this way.
<?php
//app/Console/Commands/GitPull.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class GitPull extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'git:pull';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Get updates from git server';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
exec('git pull origin master');
}
}
<?php
app/Console/Kernel.php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
Commands\GitPull::class,
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('git:pull')
->everyMinute();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Basically he has put a scheduler to execute git pull every minute. Is this the correct way to put deployments? What are the drawbacks in this way? Do the deployments have to be dependent on the application? Is it possible to add automated deployments without the help of the laravel framework? I am not very familiar with dev-ops.
Also, my source code is in bitbucket. I am ready to answer any questions regarding this. Thanks in advance.
I certainly would not use a Laravel command to run deployments. Automated deployments can be as simple or complex as needed, but here are some things I expect a build agent to do:
Listen to changes to master to do a production deploy
Run tests (and alert and stop deployment if they fail)
Build my static assets (js/css/etc)
Copy code to server (several ways to do this)
Run migrations
Restart queues so they are running with latest code
Since you're on bitbucket you could look into pipelines to do your ci/cd.
I'm developing the app for the customer and he wants to start some jobs in special time
I must run it in jobs, that's right?
for example, he wants to publish a post have 2 status published or waiting
and in send page, he can set time for publish post
how I can develop this in jobs?
ScanJob::dispatch($property->Name, $property->Owner, $Scan->id)->delay(Carbon::now()->addHour(Carbon::now()->diffInHours($Time)));
it's my first try
get diff time in hours and add it from delay
There are basically two ways via which you can solve your problem:
Create a Laravel Artisan command(you can use other methods also that Laravel provides, but I found Artisan to be fun and more flexible, helps avoid the rework) and schedule it accordingly.
Create a Queued Job and dispatch it for some later time, but it has some limitation like, the Amazon SQS queue service has a maximum delay time of 15 minutes.
Now, what is to be done:
In my opinion, you should use Solution 1 as it is more flexible and gives you more control.
Queues are used for 2 things. First, ideally, the task you want to perform should be done in the next 30-45 minutes. Second, the task is time intensive and you don't want to block the thread because of that.
Now the FUN part.
Note: You need not worry, Laravel will perform the majority of the steps for you. I am mentioning each and every step for the sake of not skipping the knowledge.
Step 1: Run the following command to create an Artisan Console Command(Remember to be in your project's root path.):
php artisan make:command PublishSomething
The command will now be available for further development at app/Console/Commands.
Step 2: You will see a handle method inside the Class like following, this is where all of your logic will exist.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class PublishSomething extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'something:publish';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Publishes something amazing!';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
//
}
}
Step 3: Let's add some logic inside our handle method
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$this->info('Publishing something cool!');
// you can add your own custom logic here.
}
Step 4: After you have added your logic, now we need to test it, you can do so like:
php artisan something:publish
Step 5: Our function is running all fine. Now we will schedule the command. Inside app/Console you will find a file Console.php, this class is responsible for all task scheduling registration, in our case.
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* #var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*
* #return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
Notice the schedule function here, this is where we will add the schedule logic.
Step 6: Now we will schedule our command to run every 5 minutes. You can change the time period very easily, Laravel provides some pre-made frequency options, and you have your own custom schedule also.
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('something:publish')->everyFiveMinutes(); // our schedule
}
Step 7: Now, Laravel's task scheduler itself is dependent on Cron. So to start the schedule, we will add the following file to our crontab.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
That's it! We are done. You have created your own custom command and scheduled it for every 5 minutes.
You can learn more about Laravel Artisan Command & Laravel Task Scheduling.
Hope it helps!
I have this this class that is a ServiceProvider
namespace Package\Avatar;
use Illuminate\Support\ServiceProvider;
class AvatarServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
include __DIR__.'/routes.php';
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
try{
$this->app->make('Package\Avatar\AvatarController');
} catch (\Exception $e){
dd($e);
}
}
}
But when I try to access to some url of AvatarCotroller class the screen is Blank, and no show neither error. But whenever I comment this line
$this->app->make('Package\Avatar\AvatarController');
I can get the normal errors of Laravel.
You can get rid of including the routes.php in the boot method of the service provider. Simply use $this->app->call('Package\Avatar\AvatarController#method') to call the method on the controller
try
php artisan optimize : to reuse all frequently used classes php will make an cached class in cache/service.php. So we if add new service we need to run it. We need to use it whenever we add new dependency without using composer.
php artisan cache:clear : clear all the above cache and remap everything
I'm using Redis in combination with laravel to cache some heavy queries in my application like this:
return Cache::remember('projects.wip', $this->cacheDuration(), function () {
...
});
private function cacheDuration()
{
return Carbon::now()->endOfDay()->diffInSeconds(Carbon::now());
}
At this moment, the cache expires as midnight, but the first person that passes this method in the morning will be the unlucky one that has to execute the query, so i would like to cache all these queries at midnight again. Is there an easy solution to this? Or will i have to manually mimic http calls to the server at night?
A good approach to achieve what you're looking for is to use a scheduler that executes at midnight to warm the cache.
https://laravel.com/docs/5.4/scheduling
First, use php artisan to create the command:
php artisan make:command WarmCache
You should edit it so it looks something like this:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class WarmCache extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'warmcache';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Warms Cache';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
// >>>> INSERT YOUR CACHE CODE HERE <<<<
}
}
You should add the code that warms your cache in the handle() function, depending on what you're trying to cache you may not need to make a http request. However, you can always use something like curl or guzzle to query the page as a http request if you need to.
Then add this to app/Console/Kernel -> $commands:
protected $commands = [
// ...
\App\Console\Commands\WarmCache::class,
// ...
];
Also, add this to app/Console\Kernel schedule() function so that it executes at mignight:
$schedule->command('warmcache')->daily();
Finally, make sure you have set up the crontask that will execute the laravel scheduler:
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
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.