Published on November 16, 2024By DeveloperBreeze

Tutorial: Using the Singleton Pattern to Optimize Shared Data in Laravel

In many Laravel applications, some data is frequently accessed across multiple views, controllers, or middleware. Examples include global configurations, user preferences, or resource limits. Instead of querying the database repeatedly, you can use the singleton pattern to load such data once and make it reusable throughout your application. This tutorial explains how to implement the singleton pattern in Laravel for efficient data sharing.


Scenario: Shared Data via Singleton

For this tutorial, imagine an application where:

  • Application Limits: Data like maximum uploads or API rate limits are shared globally.
  • Feature Toggles: Enable or disable application features dynamically.
  • Global Preferences: Shared preferences such as the preferred user interface theme.

Using the singleton pattern, we’ll make this data globally accessible and reusable.


Step 1: Create a Service Provider for the Singleton

Laravel’s service container provides a simple way to implement the singleton pattern.

  1. Generate a Service Provider:
   php artisan make:provider SharedDataServiceProvider
  1. Register the Singleton:

Open the generated file in app/Providers/SharedDataServiceProvider.php and define a singleton for the shared data:

   namespace App\Providers;

   use Illuminate\Support\ServiceProvider;

   class SharedDataServiceProvider extends ServiceProvider
   {
       public function register()
       {
           $this->app->singleton('sharedData', function () {
               return (object) [
                   'maxUploads' => 20, // Maximum file uploads allowed
                   'apiRateLimit' => 100, // API requests per minute
                   'theme' => 'dark', // Default UI theme
               ];
           });
       }
   }
  1. Register the Provider:

Add the provider to the providers array in config/app.php:

   'providers' => [
       // Other service providers
       App\Providers\SharedDataServiceProvider::class,
   ],

Step 2: Access the Singleton in Controllers

You can access the shared data singleton using the app() helper or dependency injection.

  1. Using the app() Helper:

In any controller, retrieve the shared data:

   namespace App\Http\Controllers;

   class HomeController extends Controller
   {
       public function index()
       {
           $sharedData = app('sharedData');

           return view('home', [
               'maxUploads' => $sharedData->maxUploads,
               'apiRateLimit' => $sharedData->apiRateLimit,
               'theme' => $sharedData->theme,
           ]);
       }
   }
  1. Dependency Injection:

Alternatively, inject the singleton into the controller’s constructor:

   namespace App\Http\Controllers;

   class HomeController extends Controller
   {
       protected $sharedData;

       public function __construct()
       {
           $this->sharedData = app('sharedData');
       }

       public function index()
       {
           return view('home', [
               'maxUploads' => $this->sharedData->maxUploads,
               'apiRateLimit' => $this->sharedData->apiRateLimit,
               'theme' => $this->sharedData->theme,
           ]);
       }
   }

Step 3: Access Singleton Data in Views

You can also share the singleton data globally in views using the View::share method.

  1. Update the boot Method in the Service Provider:

Add the following to share the singleton globally in Blade templates:

   public function boot()
   {
       view()->share('sharedData', app('sharedData'));
   }
  1. Access in Blade Templates:

Now, the shared data is available in all views:

   <h1>Theme: {{ $sharedData->theme }}</h1>
   <p>API Rate Limit: {{ $sharedData->apiRateLimit }}</p>
   <p>Max Uploads: {{ $sharedData->maxUploads }}</p>

Step 4: Refresh Singleton Data Dynamically

If the data in the singleton changes frequently, you can refresh it when needed.

  1. Clear the Singleton Instance:

Use the following code to reset the singleton:

   app()->forgetInstance('sharedData');
  1. Re-register the Singleton:

After resetting, access app('sharedData') to reload the data dynamically.

  1. Trigger Refresh on Data Updates:

Listen to relevant events and refresh the singleton when necessary:

   Event::listen('settings.updated', function () {
       app()->forgetInstance('sharedData');
   });

Step 5: Benefits of the Singleton Pattern

  • Performance Improvement: Avoid redundant database queries by loading shared data once.
  • Centralized Data Logic: Keep shared data in a single location for easy maintenance.
  • Reusability: Access the same data instance anywhere in the application without reloading.

Conclusion

By using the singleton pattern in Laravel, you’ve optimized how shared data is managed and accessed across your application. This approach ensures efficient performance and consistent data usage, making it ideal for managing application-wide settings, preferences, or resource limits.


Comments

Please log in to leave a comment.

Continue Reading:

Upload and Store File in Laravel

Published on January 26, 2024

php

Create Event and Listener in Laravel

Published on January 26, 2024

bash

Querying Data from Database Table in Laravel

Published on January 26, 2024

php

Laravel CSRF-Protected Form

Published on January 26, 2024

html

Create Resource Controller in Laravel

Published on January 26, 2024

bash

Laravel Validation Rules for User Registration

Published on January 26, 2024

php

Blade View in Laravel Extending Layout

Published on January 26, 2024

html