Skip to content

Instantly share code, notes, and snippets.

@MuhammadQuran17
Last active November 24, 2025 14:42
Show Gist options
  • Select an option

  • Save MuhammadQuran17/63fa0e32803cd1a4d4278ec6b618017d to your computer and use it in GitHub Desktop.

Select an option

Save MuhammadQuran17/63fa0e32803cd1a4d4278ec6b618017d to your computer and use it in GitHub Desktop.
Helper for Laravel

Best practises from here

https://webdevetc.com/blog/laravel-naming-conventions/#section_naming-controllers https://github.com/alexeymezenin/laravel-best-practices/tree/master?tab=readme-ov-file#follow-laravel-naming-conventions

Sail

docker run --rm \
    -u "$(id -u):$(id -g)" \
    -v $(pwd):/var/www/html \
    -w /var/www/html \
    laravelsail/php82-composer:latest \
    composer install

to install composer with sail on fresh pulled repository\

  1. configure .env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=sail
DB_PASSWORD=password
  1. start sail up
  2. migartions, key generation
  3. sail npm install, then run dev

Folders permission

sudo chown -R www-data:www-data storage bootstrap/cache

# Safe permissions: dirs 775, files 664
sudo find storage -type d -exec chmod 775 {} \;
sudo find storage -type f -exec chmod 664 {} \;
sudo find bootstrap/cache -type d -exec chmod 775 {} \;
sudo find bootstrap/cache -type f -exec chmod 664 {} \;

Laravel Sail is designed as a development tool and is not recommended for use in production environments.

Jobs & Queues

Serialization

  1. You can not send the request object to Job, you should do $request->toArray(). But inside of Job if you need to send request to Service you can use like: new AwesomeRequest($requestArray). In ideal you should create a DTO, but it depends on the complexity you want.

Get Job Id

  1. To get job id in Controller in Laravel12, but in Laravel9 Job dispatch worked and returned job id. You must use Bus like: $jobId = Bus::dispatch(new ProcessAiChatMessage($request->toArray(), Auth::user()->id));

Ordering

ASC

  • 1,2,3,4

DESC

  • 4,3,2,1

Date

  • latest() -> orderBy('created_at', 'desc') (latest / newest first)
  • oldest() -> orderBy('created_at', 'asc') (oldest first)
  1. Post::latest('updated_at')->get();

SSE

When PHP-FPM is fine for SSE

Use Laravel streaming if:

  • You expect < 50 concurrent streams

  • Streaming duration is short (5–30 sec)

  • Mainly token-by-token AI output

  • You accept occasional worker spikes

  • You don’t run huge traffic

🟦 When PHP-FPM becomes a problem

Switch to a Go (or Node, FastAPI) SSE server when you expect:

  • 100 concurrent active streams

  • Streams last 1–5 minutes

  • You want high throughput

  • You don’t want to block your Laravel traffic

  • You plan to scale to thousands of users

Go handles SSE by:

1 goroutine per connection (cheap)

non-blocking I/O

millions of open connections possible

VS Code Laravelintleisense error SAIL

/var/www/html/ - in both paths

sail php -r "{code}" 
  • PHP command

ServiceProviders

Specific for Muhammadumar, may be not understood by person who don't know the core, client context.\

loadConfigs() method didn't work for Fortify and this kinda 3rd party packages is that it runs too late. The Laravel\Fortify\FortifyServiceProvider reads the config values inside its register() method to bind services (like the FortifyGuard). It grabs the configuration at that exact moment. To loadConfigs to work for system-level configs (like fortify), we must call a variation of it inside register(), not boot(). In core currently all configs are in boot(), that will work on core itself, but not work for clients (onboardings) that extends the core

So I conclude that external 3rd party packages configs should be in register, not on boot().

Sail add service (pgsql) to working docker-compose

> sail artisan sail:install pgsql

will add into docker-compose.yml additional postgresql service, but it can be outdated, so modify to new one manually and don't afraid to change docker-compose

Save to file logs

\Illuminate\Support\Facades\Storage::put('test.txt', print_r($paymentsResponse->isAuthorised(), true));

but this approach saves telescope sql queries also. So in this case it is better to use:

 DB::listen(fn ($query) =>
            file_put_contents(
                storage_path().'/logs/backbone_sync_products_sql.log',
                "\n $query->sql. Bindings: ". implode(',', $query->bindings),
                FILE_APPEND | LOCK_EX)
        );

Configure MCP Laravel Boost for windsurf

  1. You should use windsurf's built in add raw MCP and json file should be
{
    "mcpServers": {
      "laravel-boost": {
        "command": "bash",
        "args": [
          "-c",
          "cd /home/xmsi/documents/ai_double_check_laravel && ./vendor/bin/sail php artisan boost:mcp"
        ]
      }
    }
  }

id binding to Model in method parameters Work in

Controllers β†’ yes
Requests β†’ yes
Middleware β†’ yes
Service classes β†’ no
Jobs β†’ no
Commands β†’ no
Event listeners β†’ no\

Delete by chunks example:

$deleted = app(TestCategory::class)
                ->where('id', '>', 750)
                ->whereNotIn('name', ['a', 'b'])->chunkById(10, function ($categories) {
                    $ids = $categories->pluck('id')->toArray();
                    TestCategory::whereIn('id', $ids)->delete();
                    
                    // sleep for 0.3 seconds. In microseconds.
                    usleep(300000);
                    return true;
                });

Alternative the same result

        do {
            $deleted = app(TestCategory::class)
                ->whereNotIn('id', $this->activeCategories)
                ->whereNotIn('name', [
                    'a',
                    'b'
                ])->limit(25)->delete();

            // sleep for 0.3 seconds. In microseconds
            usleep(300000);
        } while ($deleted > 0);

Seed custom class

php artisan db:seed "\Figma\Core\Modules\Newport\Database\Seeders\NewportFileStatusesTableSeeder"

Laravel Tinker IntellijIdea install

  1. Make sure your CLI interpreter is configured
  2. Plugin's: Project Settings
  3. Make sure to select right interpreter

DB runtime logging mechanism

New Laravel Way. Should be before SQL query

DB::listen(fn ($query) => file_put_contents(storage_path() . '/logs/db.log', "\n{$query->sql}", FILE_APPEND | LOCK_EX));

Old Laravel way.

\DB::enableQueryLog();

// Here lives SQL queries. 

foreach (DB::getQueryLog() as $queryArray) {
     file_put_contents(storage_path() . '/logs/db2.log', "\n".$queryArray['query'], FILE_APPEND | LOCK_EX);
}
        
dd(\DB::getQueryLog());

Events

Laravel offers automatic event and listener discovery, simplifying the process of registering events and their corresponding listeners. This feature, available from v 5.8.9 and 6, and especially in Laravel 10–11, event discovery is enabled by default. It eliminates the need for manual registration within the $listen array of the EventServiceProvider.

Foreign Keys

Nullable FK

$table->foreignId('type_id')->nullable()->default(null)->constrained('folder_types');

Deleted migration is still visible

If you have installed 3rd pary oackage, then it has migrations. Even if you will publish them, and then delete from your root, they still be available from vendor. Php artisan migrate will look up vendor also. But if you have owerriten it in root, then your root migration will be run. But if you delete, then vendor's migration will still be available.

Spatie

  1. If you are using UUId then you need to implement: only the first of these
  2. Create permissions in seeder using: Permission::firstOrCreate(['name' => 'can edit post']);
  3. Create Role in seeder: Role::firstOrCreate(['name' => 'user']);
  4. Assign Permission to Role in the same seeder: $admin->givePermissionTo(['can edit post', 'can delete a post']);
  5. Assign role to user using $user->assignRole('user') in Listener. Fire these Event on registartion: Illuminate\Auth\Events\Registered event
  6. Check using middleware: Route::group(['middleware' => ['can:publish articles']])->....

Tests

Models event hooks

class MyModel extends Model
{
    protected $fillable = [
        'name'
    ];

    protected static function booted(): void
    {
        static::created(function ($model) {
            $model->dumpEvent('CREATED');
        });

        static::updated(function ($model) {
            $model->dumpEvent('UPDATED');
        });

        static::saved(function ($model) {
            $model->dumpEvent('SAVED');
        });
    }

    public function dumpEvent(string $event): void
    {
        dump([
            'event' => $event,
            'wasChanged()' => $this->wasChanged(),
            'wasRecentlyCreated' => $this->wasRecentlyCreated
        ]);
    }
}

Definitions

  1. public $bindings prop in a ServiceProvider , connect interface (key of an array) with a concreate class (value of an array)
  2. Observers are classes that allow you to listen for certain events that happen to your models, such as creating, updating, deleting, or saving records
  3. Listeners: Usually, a listener is a class that handles a single event. You register the listener for a specific event in the EventServiceProvider.
    Subscribers: A subscriber, on the other hand, is a class that can subscribe to multiple events and define the corresponding event handling methods. It allows you to group related event handling logic together in a single class.
  4. Route->middleware('can:smthing.create') - can is a default Laravel middleware

Laravel versions

https://laravelversions.com/en

DataTable

  1. Transformers are used to format, transform, or modify the data before it is sent to the frontend. Transformers allow you to customize how the data is presented in the DataTable, making it more user-friendly or specific to the needs of your application.
  2. Mappers refer to functions or methods that map data from your model or database to the format or structure required by your DataTable

StateMachine

Why Use a State Machine?
  • Controlled Transitions: A state machine ensures that an entity can only move from one state to another in a predefined way, preventing invalid state changes.
  • Business Logic Enforcement: It helps enforce business rules by allowing transitions only when certain conditions are met.
  • Simplified Management: It simplifies the management of complex workflows, where an entity might need to go through multiple states in a sequence.
Example Scenario: Order Processing

Let's say you have an e-commerce platform, and you need to manage the different states of an order:

  1. States:

    • pending
    • processing
    • shipped
    • delivered
    • canceled
  2. Allowed Transitions:

    • pending β†’ processing
    • processing β†’ shipped
    • shipped β†’ delivered
    • Any state β†’ canceled (except delivered)

Useful links

@todo: https://laravel-news.com/php-codesniffer-with-laravel
https://laravel-news.com/spatie-image-v3
https://dev.to/etienneleba/test-all-your-business-logic-in-less-than-1-second-2n84
https://dev.to/adnanbabakan/implement-uuid-primary-key-in-laravel-and-its-benefits-55o3 \

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment