Alex
Alex

Reputation: 3855

Options for persisting static data in Laravel

I'm learning Stripe API through Cashier with a small Laravel app. My goal is to store subscription plans in a local data source other than a DB. Ideally, I would like to end up with a Collection of static (i.e. permanent) data, possibly in the form of Plan objects. Each plan would contain name, description, and price which will hardly ever be modified, so the data could simply be hardcoded in PHP. I envision to treat this data just like any Eloquent model:

class MembershipController extends Controller
{
    public function index() // dependency injection here? hmm..
    {
        return view('membership')->with('plans', Plan::all());
    }

Here are my considerations for the data source / structure so far:

  1. Eloquent Model. First, I could simply create a Plan model and persist the three plans in a plans table. However, because my plans will rarely ever change, I would have to fetch the same data from the DB over and over again on each HTTP request. Even worse, if I do happen to change my plans in the future, I would need to update them at two places -- Stripe dashboard and local database, which is cumbersome and counter-intuitive. What if I or any other person simply forget to? I feel that there needs to be a single data source.
  2. Stripe Plan Model. In this case, I would have to fetch Plans using Stripe API. Again, this operation would be (even more) expensive, since every time a request is made to the server, a syncronous request will be made to Stripe to fetch the plans, and the app will be idle untill the API responds back with the data. This, to me, is very slow and inefficient.
  3. Service Provider. After some research, I ended up with the idea of storing my plans in a Service Provider in the form of a singleton containing the collection of my hardcoded plans. This approach is mentioned on Laracasts (at around 1:20), but not really explained much. If I get it right, the provider will allow to cache data and quickly serve it only when needed.

Question

Can you suggest any other design patterns or data structures that will be useful in this case? If Service Provider would be the best-recommended approach, can you give a simple example of how to use it? I read the docs and although the given example was vague, I ended up with the following:

class PlanProvider extends ServiceProvider
{
    protected $defer = true;

    public function boot() { }

    public function register()
    {
        $this->app->singleton(Collection::class, function ($app) {
            return new Collection([ // that's probably not right...
                'basic' => [
                    new Plan([
                        'name' => 'basic',
                        'description' => 'Basic Plan',
                        'price' => 999
                    ])
                ]
            ]);
        });
    }

    public function provides()
    {
        return [Collection::class];
    }
}

I feel it's not right. And how would I inject this collection into a controller anyways?

Thanks

Upvotes: 4

Views: 2832

Answers (2)

Playnox
Playnox

Reputation: 1124

I found this one the other day... Might help with what you're looking for: https://github.com/WebLogin/laravel-lookup

Allows you to create static Elaquent compatible models.

And there's also this one: https://github.com/squirephp/squire#creating-your-own-models

Upvotes: 0

AddWeb Solution Pvt Ltd
AddWeb Solution Pvt Ltd

Reputation: 21681

From the stack answer, you can use view()->share() to share data across all controller globally.

Just follows the given three steps and done.

UPDATE

You can also use Repository approach to use global data at other controller. This is something like below:

Create PlanRepository.php under app/Http/Repository/:

<?php
namespace App\Http\Repository;
/**
* Plan Repository class
*/
class PlanRepository
{
  /**
   * Get a list of all plans
   *
   * @return array  Array containing list of all plans
   */
  public function getPlanData()
  {
    return [
        'name' => 'basic',
        'description' => 'Basic Plan',
        'price' => 999
    ];
  }
}

And use into respective controller by injecting above repository like:

public $planList; 
public function __construct(PlanRepository $plan)
{
   $this->planList = $plan->getPlanData();
}

Even you can pass these data to view like:

public function index(PlanRepository $plan)
{
    $planList = $plan->getPlanData();

    return view('welcome', compact('planList'));
}

Upvotes: 1

Related Questions