Skip to content

Latest commit

 

History

History
453 lines (321 loc) · 14.4 KB

console.md

File metadata and controls

453 lines (321 loc) · 14.4 KB

Artisan & Console Commands Tips (cd ..)

Laravel Tip 💡: Much Cooler Command Output (⬆️)

It is true that Laravel provides methods like "info()" and "error()" to send output to the console, but since Laravel 9, the core itself started using "termwind", which you can see when seeding your database or in case of an error, and you can leverage that as well by using the "components" attributes.

<?php

/**
 * Execute the console command.
 */
public function handle()
{
    // A standard error message
    $this->error('The old fashioned way.');

    // A much cooler error message
    $this->components->error('What Laravel uses internally.');

    // And more
    $this->components->info('Hello, World!');
    $this->components->warn('Hello, World!');
    $this->components->alert('Hello, World!');
    // choice, confirm, ask, warn, task, line, bulletList ..

    return Command::SUCCESS;
}

Laravel 💡: The Scheduler's "skip" Method

Sometimes, you might want to skip executing a command based on a specific condition. Laravel includes the "skip" method to accomplish exactly that 🚀

<?php

$schedule->command('emails:send')->daily()->skip(function () {
    return Carbon::today()->isHoliday();
});

Laravel Tip 💡: On Command Result (⬆️)

Did you know that Laravel allows you to define callbacks to be executed based on the result of a scheduled task? This helps log failures or execute related actions on success 🚀

<?php

use Illuminate\Console\Scheduling\Schedule;

$schedule->command('emails:send')
            ->daily()
            ->onSuccess(function () {
                // The task succeeded...
               })
            ->onFailure(function () {
                 // The task failed...
            });

Laravel Tip 💡: Command Input Auto-Completion (⬆️)

When building console commands, you can improve the user experience by implementing auto-completion for the user. This can be done using the "anticipate" method provided by Laravel 🚀

<?php

// You can use arrays 
$animal = $this->anticipate("What's your favourite animal?", ['dogs', 'cats']);

// Or run a closure, triggered every time a user types a character
$animal = $this->anticipate("What's your favourite animal?", function (string $input) {
    return Animal::query()
                ->where('name', 'LIKE', "$input%")
                ->pluck('name')
                ->toArray();
});

Laravel Tip 💡: Mail Command Output (⬆️)

Did you know that the Laravel scheduler allows you to email the output of a command to an email address of your choosing? 🚀

<?php

$schedule->command(SendEmailsCommand::class)
    ->daily()
    ->emailOutputTo('[email protected]');

// You can also use `emailOutputOnFailure`.

Laravel Tip 💡: Hide Console Commands (⬆️)

Did you know that you can conditionally hide console commands? This is useful when you are building packages and you want a command to be executed only once 🚀

<?php

namespace Package\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Package\PackageServiceProvider;

class Install extends Command
{
    protected $signature = 'package:install';

    public function __construct()
    {
        parent::__construct();

        if (file_exists(config_path('package-config.php'))) {
            $this->setHidden();
        }
    }

    public function handle()
    {
        Artisan::call('vendor:publish', ['--provider' => PackageServiceProvider::class]);
        
        $this->info('Package was installed successfully 🎉');
    }
}

Laravel Tip 💡: Chain Scheduled Commands (⬆️)

You can chain commands in your scheduler using the then() method, an undocumented feature that I often find myself using 🚀

<?php

$schedule->command('db:backup')
            ->daily()
            ->then(function(){
                $this->command('notify:slack');
            });

Laravel Tip 💡: Schedule Jobs Based On Time Zones (⬆️)

Did you know that you can schedule jobs based on specific time zones? You can do so by chaining the "timezone" method 🚀

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('report:generate')
    ->timezone('Africa/Tunis')
    ->at('9:00')

Laravel Tip 💡: Run Commands In Maintenance Mode (⬆️)

When Laravel's maintenance mode is on, all scheduled commands won't run. If you wish to change this behavior, you can chain the "evenInMaintenanceMode()" method 🚀

<?php

// Command will run even when maintenance mode is on
Schedule::command('emails:send')->evenInMaintenanceMode();

Laravel Tip 💡: Run Commands In the Background (⬆️)

Scheduled commands run sequentially. If you have a long-running task, it could take longer than anticipated and cause a delay for other tasks. Luckily, in such cases, you can use the "runInBackground" method 🚀

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('analytics:report')
        ->daily()
        ->runInBackground();

Laravel Tip 💡: Schedule Shell Commands (⬆️)

Did you know that the Laravel Scheduler allows you to execute commands in the operating system? 🚀

<?php

use Illuminate\Support\Facades\Schedule;
 
Schedule::exec('node /home/forge/script.js')->daily();

Laravel Tip 💡: Ping URLs When Running Commands (⬆️)

Did you know you can ping URLs before and after your command has run? This is really useful if you want to notify an external service or a webhook. 🚀

<?php

Schedule::command('emails:send')
    ->daily()
    ->pingBefore($webhookUrl)
    ->thenPing($webhookUrl);

Laravel Tip 💡: Schedule Commands on Specific Environments (⬆️)

Did you know that you can schedule your commands for specific environments? If you frequently use "schedule:work", you'll find this helpful for excluding commands from the dev environment 🚀

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('newsletter:send')
    ->environments('production') // You can also pass an array of environments
    ->weekends();

Laravel Tip 💡: Connect to Your DB via Artisan (⬆️)

Ever needed to quickly connect to your database via the CLI? There’s an Artisan command to do exactly that! 🚀

// This will connect you directly to the database
php artisan db

// Have multiple connections? No worries you can specify which one to use
php artisan db mysql

Laravel Tip 💡: Ensure Proper Table Name in Migrations (⬆️)

When creating migrations, we sometimes don't format the name in a way that Laravel can understand to fill in the table name. However, you can always specify it manually 🚀

<?php

/**
 * If you want Laravel to fill in the Schema::table() for you,
 * use the --table argument when generating the migration.
 */
php artisan make:migration "tweak_users_table" --table=users

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }

    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }
};

Laravel Tip 💡: Cool Artisan DB Commands (⬆️)

Have you ever needed to check if your db connection is working as expected? Or wondered how many open connections you have? Maybe you want to know the total size of a db? Well, Artisan comes with some cool commands to do exactly that 🚀

# This command allows you to inspect a table
php artisan db:table

# This command checks if your db connections are working
php artisan db:monitor

# This command displays the db version, total size, open connections, and more
php artisan db:show

Laravel Tip 💡: Ask for Confirmation in Commands (⬆️)

Did you know that you can request confirmation for risky commands before executing them? You can do this using the "confirm" method 🚀

<?php

// Displays the old Laravel prompt view
$this->confirm('Do you want to continue?');

// With "components", it displays the modern Laravel prompt view
$this->components->confirm('Do you want to continue?');

// In your terminal, you should see
/*
 * Do you want to continue? (yes/no) [no]
 *
 */

Laravel Tip 💡: Show Model Infos (⬆️)

When a model grows, it can be hard to check all the relationships, including those from third-party packages, the registered events, and the observers. When that's the case, you can use the "model:show" command instead 🚀

php artisan model:show User

# This will list: The table, attributes, relationships, events and observers.

Laravel Tip 💡: Define Command Aliases (⬆️)

We've all created custom Artisan commands for different purposes. While it's great to have an expressive signature, if you're using the command often, you can define an alias for it 🚀

<?php

class BillReminder extends Command
{
    protected $signature = 'reminder:bill';

    protected $aliases = ['rb']; // Alias here

    // ...
}

// You can run the command with:
// php artisan reminder:bill

// But now you can also use the alias
// php artisan rb

Laravel Tip 💡: Email Command Failures Automatically (⬆️)

Did you know that Laravel ships with the "emailOutputOnFailure" method which automatically sends the output of a failed command to your email? 🚀

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('report:generate')
         ->daily()
         ->emailOutputOnFailure(config('contact.support'));

Laravel Tip 💡: The Prohibitable Trait (⬆️)

Most Laravel apps often have local-only or environment-dependent commands that shouldn't run elsewhere. To prevent accidents, use the "Prohibitable" trait and call the "prohibit" method 🚀

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Console\Prohibitable;

class CleanLogs extends Command
{
    use Prohibitable;
}

// Now in the boot method of the AppServiceProvider
CleanLogs::prohibit(app()->isProduction());

Laravel Tip 💡: Prohibit DB Destructive Commands (⬆️)

Running migrations or wiping the DB in production can be, well, disastrous. Since Laravel v11, you can prohibit all DB destructive commands by calling "prohibitDestructiveCommands" method 🚀

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Prevents 'migrate:fresh', 'migrate:refresh', 'migrate:reset', and 'db:wipe'
        DB::prohibitDestructiveCommands(
            $this->app->isProduction()
        );
    }
}

Laravel Tip 💡: Conditionally Hide Console Commands (⬆️)

Sometimes, you may want to hide console commands, such as legacy commands, from being listed. While you can manually hide them using the setHidden(), you can do this with the isHidden() method 🚀

<?php
 
namespace App\Console\Commands;
 
use Illuminate\Console\Command;
 
class LegacyCommand extends Command
{
    // ...

    public function isHidden(): bool
    {
        // This could check a configuration flag
        return true;
    }
}

Laravel Tip 💡: Run Scheduled Commands on a Single Server (⬆️)

Running your app on multiple servers? By default, scheduled commands will execute on all servers, which is unnecessary and can cause issues. You can prevent this by using the "onOneServer" 🚀

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('report:generate')
    ->fridays()
    ->at('17:00')
    ->onOneServer(); // the command will run on a single server