From a11dd499a79bdd4de7a2af434376142caed03690 Mon Sep 17 00:00:00 2001 From: Krishan Koenig Date: Mon, 22 Apr 2024 10:16:30 +0200 Subject: [PATCH] improve PlanRepository documentation --- docs/12-faq.md | 105 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 26 deletions(-) diff --git a/docs/12-faq.md b/docs/12-faq.md index 4e2dface..86995bd3 100644 --- a/docs/12-faq.md +++ b/docs/12-faq.md @@ -29,9 +29,9 @@ If required for your billable model, modify the cashier migrations for UUIDs: ```php // Replace this: $table->unsignedInteger('owner_id'); - + // By this: -$table->uuid('owner_id'); +$table->uuid('owner_id'); ``` And in your `Billable` model add ```php @@ -62,19 +62,17 @@ Firstly you create your own implementation of the plan repository and implement Implement the methods according to your needs and make sure you'll return a `Laravel\Cashier\Plan\Contracts\Plan`. ```php -use App\Plan; +use App\Models\Plan; use Laravel\Cashier\Exceptions\PlanNotFoundException; +use Laravel\Cashier\Plan\Contracts\Plan as PlanContract; use Laravel\Cashier\Plan\Contracts\PlanRepository; class DatabasePlanRepository implements PlanRepository { - public static function find(string $name) + public static function find(string $name): PlanContract { - $plan = Plan::where('name', $name)->first(); - - if (is_null($plan)) { - return null; - } + /** @var Plan $plan */ + $plan = Plan::where('name', $name)->firstOrFail(); // Return a \Laravel\Cashier\Plan\Plan by creating one from the database values return $plan->buildCashierPlan(); @@ -83,7 +81,7 @@ class DatabasePlanRepository implements PlanRepository return $plan; } - public static function findOrFail(string $name) + public static function findOrFail(string $name): PlanContract { if (($result = self::find($name)) === null) { throw new PlanNotFoundException; @@ -95,15 +93,20 @@ class DatabasePlanRepository implements PlanRepository ``` ::: details Example Plan model (app/Plan.php) with buildCashierPlan and returns a \Laravel\Cashier\Plan\Plan ```php -name); - - return $plan->setAmount(mollie_array_to_money($this->amount)) + + return $plan->setAmount($this->getAmount()) ->setInterval($this->interval) ->setDescription($this->description) - ->setFirstPaymentMethod($this->first_payment_method) - ->setFirstPaymentAmount(mollie_array_to_money($this->first_payment_amount)) - ->setFirstPaymentDescription($this->first_payment_description) - ->setFirstPaymentRedirectUrl($this->first_payment_redirect_url) - ->setFirstPaymentWebhookUrl($this->first_payment_webhook_url) - ->setOrderItemPreprocessors(Preprocessors::fromArray($this->order_item_preprocessors)); + ->setFirstPaymentMethod(config('cashier.first_payment.method')) + ->setFirstPaymentAmount($this->getAmount()) + ->setFirstPaymentDescription($this->description) + ->setFirstPaymentRedirectUrl(route('plans-payment.success', ['plan' => $this->id])) + ->setFirstPaymentWebhookUrl(Cashier::firstPaymentWebhookUrl()) + ->setOrderItemPreprocessors(Preprocessors::fromArray(config('cashier_plans.defaults.order_item_preprocessors'))); + } + + private function getAmount(): Money + { + return new Money($this->price, new Currency($this->currency)); } } ``` -Note: In this case you'll need to add accessors for all the values (like amount, interval, fist_payment_method etc.) -to make sure you'll use the values from your defaults (config/cashier_plans.php > defaults). +The DB-schema for the above Model could look like the following. + +```php +Schema::create('plans', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->string('description'); + $table->string('price'); + $table->string('currency'); + $table->string('interval'); + $table->timestamps(); +}); +``` + +You can also create a `PlanFactory`. + +```php +class PlanFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => $this->faker->name, + 'description' => $this->faker->sentence, + 'price' => '10.00', + 'currency' => $this->faker->currencyCode, + 'interval' => $this->faker->randomElement(['month', 'year']), + ]; + } +} +``` ::: -Then you just have to bind your implementation to the Laravel/Illuminate container by registering the binding in a service provider +Then you have to bind your implementation to the Laravel/Illuminate container by registering the binding in a service provider ```php class AppServiceProvider extends ServiceProvider @@ -142,5 +184,16 @@ class AppServiceProvider extends ServiceProvider } ``` +In order to test if your implementation is setup correctly, you can run the following code snippet. +```php +use Laravel\Cashier\Plan\Contracts\PlanRepository; +use App\Models\Plan; + +Plan::factory()->create(["name" => "test"]); +resolve(PlanRepository::class)->find("test"); +``` + +--- + Cashier Mollie will now use your implementation of the PlanRepository. For coupons this is basically the same, -just make sure you implement the CouponRepository contract and bind the contract to your own implementation. +make sure you implement the CouponRepository contract and bind the contract to your own implementation.