Skip to content

Commit

Permalink
Merge pull request #240 from Naoray/main
Browse files Browse the repository at this point in the history
improve DatabasePlanRepository documentation
  • Loading branch information
Naoray authored Apr 22, 2024
2 parents bfceb95 + 4fc4d6c commit 857c635
Showing 1 changed file with 79 additions and 26 deletions.
105 changes: 79 additions & 26 deletions docs/12-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand All @@ -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
<?php

namespace App;
namespace App\Models;

use Laravel\Cashier\Plan\Plan as CashierPlan;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Cashier\Cashier;
use Laravel\Cashier\Plan\Plan as CashierPlan;
use Money\Currency;
use Money\Money;
use Laravel\Cashier\Order\OrderItemPreprocessorCollection as Preprocessors;

class Plan extends Model
{
use HasFactory;

/**
* Builds a Cashier plan from the current model.
*
Expand All @@ -112,25 +115,64 @@ class Plan extends Model
public function buildCashierPlan(): CashierPlan
{
$plan = new CashierPlan($this->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<string, mixed>
*/
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
Expand All @@ -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.

0 comments on commit 857c635

Please sign in to comment.