vvmalko / subscriptions
laravel 5 应用程序的订阅处理包
Requires
- php: >=5.5.9
- laracasts/commander: ~1.0
- nesbot/carbon: ~1.14
This package is not auto-updated.
Last update: 2024-09-20 17:33:49 UTC
README
从laravel 4包迁移而来。原始地址: ipunkt/subscriptions
Laravel 5.x 应用程序的订阅包
安装
在 composer.json 中添加以下行
"require": { "vvmalko/subscriptions": "dev-master" }
运行 php artisan vendor:publish
然后编辑 config/vvmalko/plans.php
和 config/vvmalko/defaults.php
以满足您的需求。所有已知计划都在那里。
将 vvMalko\Subscriptions\SubscriptionsServiceProvider::class,
添加到 config/app.php
的 providers
中。
将 'Subscription' => vvMalko\Subscriptions\SubscriptionsFacade::class,
添加到 config/app.php
的 aliases
中。
运行 php artisan migrate
以迁移必要的数据库表。
配置
计划配置
// @see src/config/plans.php return [ 'PLAN-ID' => [ 'name' => 'TRIAL', 'description' => 'Trial subscription.', 'subscription_break' => 0, // optional for preventing a subscription for X days after last subscription ends ], ];
可选属性 'subscription_break'
可以用来防止订阅者在配置的天数过去之前订阅此计划。例如,为了有一个一年只能订阅一次的试用计划。
计划的福利配置
// @see src/config/plans.php return [ 'PLAN-ID' => [ // [..] 'benefits' => [ 'feature-1' => [], // feature is present 'feature-2-countable' => [ 'min' => 10, // feature is present and has margins/countable range ], 'feature-3-countable' => [ 'min' => 10, 'max' => 50, ], 'feature-4-countable' => [ 'max' => 50, // min is automatically 0 (zero) ], ], ], ];
计划的支付选项
// @see src/config/plans.php return [ 'PLAN-ID' => [ // [..] 'payments' => [ [ 'price' => 1, // for 1.00 'quantity' => 12, // in 12-times 'days' => 30, // of 30-days 'methods' => ['paypal'], // allowed payment methods ], [ 'price' => 2, // for 2.00 'quantity' => 12, // in 12-times 'days' => 30, // of 30-days 'methods' => ['paypal', 'invoice'], ], ], ], ];
为所有订阅者选择默认计划
要为所有订阅者设置默认计划,您可以使用 src/config/defaults.php
并设置默认计划的id。这样,当订阅者还没有计划时,基于计划的任何功能调用都将解析此默认计划。
客户模型设置(例如 User
)
use vvMalko\Subscriptions\Subscription\Contracts\SubscriptionSubscriber; class User extends Model implements SubscriptionSubscriber { ... ... ... public function getSubscriberId() { return $this->id; } public function getSubscriberModel() { return $this->table; //model_class set us `User` } }
控制器设置(例如 SubscriptionsController
)
use vvMalko\Subscriptions\SubscriptionsFacade as Subscription; class SubscriptionsController extends Controller { ... ... ... private $subscriber; public function __construct() { $this->subscriber = Auth::user(); } //get user(subscriber) plans public function plans() { $plan = Subscription::current($this->subscriber); return view('plans'); } }
要为所有订阅者设置默认计划,您可以使用 src/config/defaults.php
并设置默认计划的id。这样,当订阅者还没有计划时,基于计划的任何功能调用都将解析此默认计划。
用法
获取所有计划
/** @var Plan[] $plans */ $plans = Subscription::plans();
如果您在计划配置中使用订阅中断,请使用 selectablePlans
方法获取所有计划。这将检查每个中断计划的最后订阅。
/** @var Plan[] $plans */ $plans = Subscription::selectablePlans($this->user);
获取订阅者的当前计划
/** @var Plan|null $plan */ $plan = Subscription::plan($subscriber);
订阅者是否已经存在订阅
Subscription::exists($subscriber); // returns true when a subscription exists
订阅是否已过期?比较周期时间和当前时间
Subscription::expired($subscriber); // returns true|false or null when a subscription not exists
每个计划都可以有福利(功能)
$plan->can('feature'); // returns true or false $plan->can('countable-feature', 14); // returns true or false
或者使用 Subscription
门面来检查订阅者的当前订阅计划。这是推荐的
Subscription::can($subscriber, 'feature'); // returns true or false Subscription::can($subscriber, 'countable-feature', 14); // returns true or false
获取计划的所有可能的支付选项
/** @var PaymentOption[] $paymentOptions */ $paymentOptions = $plan->paymentOptions();
创建新的订阅
/** creating a subscription for a subscriber, maybe the current authenticated user */ $subscription = Subscription::create($plan, $paymentOption, SubscriptionSubscriber $subscriber);
要创建订阅,您必须提供 Plan
或计划的id以及选定的 PaymentOption
或支付选项的标识符。 $subscriber
是订阅所属的实体。这可以是任何可变型的 eloquent 对象。
订阅成功创建后,将触发类型为 vvMalko\Subscriptions\Subscription\Events\SubscriptionWasCreated
的事件。
底层仓库自行控制重复项。因此,对于现有订阅,它将更新当前订阅并触发类型为 vvMalko\Subscriptions\Subscription\Events\SubscriptionWasUpdated
的事件。
您可以将订阅升级到任何其他计划。相同的 Subscription::create()
方法处理此升级。
触发的事件都具有当前订阅、所选计划和支付选项作为属性。因此,您可以监听这些事件并执行自己的操作。
获取订阅者的当前订阅
/** @var Subscription|null $subscription */ $subscription = Subscription::current($subscriber);
检查试用订阅
/** be careful because current() can return null when no subscription existing */ $onTrial = Subscription::current($subscriber)->onTrial();
检查订阅是否已付款
$subscription = Subscription::current($subscriber); $isPaid = $subscription->paid(); // or Subscription::paid($subscriber);
获取订阅的所有周期
/** @var Period[] $periods */ $periods = $subscription->periods;
用户代码
适应您的控制器
我们使用 laracasts/commander
包来处理业务命令和事件。
class SubscriptionsController extends \Controller { /** * use commandbus to execute commands */ use Laracasts\Commander\CommanderTrait; // display an overview of all subscriptions public function index() { $subscribed = Subscription::exists($this->user);// $this->user represents a SubscriptionSubscriber interface if ( ! $subscribed) { $plans = Subscription::selectablePlans($this->user); // unselectable plans filtered out already $defaultPlan = Subscription::plan($this->user); return View::make('subscriptions.create', compact('plans', 'defaultPlan')); } $plan = Subscription::plan($this->user); $subscription = Subscription::current($this->user); $paid = $subscription->paid(); $subscriptions = Subscription::all($this->user); return View::make('subscriptions.index', compact('subscribed', 'plan', 'subscription', 'subscriptions', 'paid')); } // create a plan (form) public function create($plan) { $plan = Subscription::findPlan($plan); $subscription = Subscription::all($this->user)->last(); if (null !== $subscription && $subscription->subscription_ends_at->isPast()) $subscription = null; $startDate = (null === $subscription) ? Carbon::now() : $subscription->subscription_ends_at->addSeconds(1); return View::make('subscriptions.create_plan', compact('plan', 'startDate')); } // store the plan as subscription for user public function store() { try { $this->validate(Input::all()); } catch (FormValidationException $e) { return Redirect::back()->withInput()->withErrors($e->getErrors()); } $plan = Subscription::findPlan(Input::get('plan')); if (null === $plan) throw (new ModelNotFoundException('No plan ' . Input::get('plan') . ' found.'))->setModel(Plan::class); $this->execute(CreateSubscriptionCommand::class, Input::all()); Flash::success('subscriptions.subscription_created'); return Redirect::route('subscriptions.index'); } }
相应的命令 CreateSubscriptionCommandHandler
在这里(CreateSubscriptionCommand
仅是输入值的 DTO)
class CreateSubscriptionCommandHandler implements Laracasts\Commander\CommandHandler { use Laracasts\Commander\Events\DispatchableTrait; /** * authenticated user * * @var \Illuminate\Auth\Guard */ private $auth; /** * @param AuthManager $auth */ public function __construct(\Illuminate\Auth\AuthManager $auth) { $this->auth = $auth; } /** * Handle the command * * @param CreateSubscriptionCommand $command * @return mixed */ public function handle($command) { /** @var User|SubscriptionSubscriber $user */ $user = $this->auth->user(); // store invoice data // create subscription $subscription = Subscription::create($command->plan, $command->payment_option, $user); // fire event for "subscription created" or "subscription updated" $this->dispatchEventsFor($subscription); } }
与扩展或升级计划相关的操作几乎相同。您可以使用相同的命令、处理程序和控制器动作。订阅仓库会自动处理订阅计划的更新或创建。
注册监听器
# in your app/listeners.php for example Event::listen('vvMalko.Subscriptions.Subscription.Events.*', 'App\Subscriptions\Listeners\EmailNotifier'); // we use the laracasts/commander package, so you can inform you about a listener too class EmailNotifier extends Laracasts\Commander\Events\EventListener { /** * will be called when event SubscriptionWasCreated was fired * * @param SubscriptionWasCreated $event */ public function whenSubscriptionWasCreated(SubscriptionWasCreated $event) { // do something when a subscription was created (a new plan was set up and no plan exists before // or every plan subscription before was in the past) } /** * will be called when event SubscriptionWasUpdated was fired * * @param SubscriptionWasUpdated $event */ public function whenSubscriptionWasUpdated(SubscriptionWasUpdated $event) { // do something when a subscription was updated (e.g. smaller plan before gets upgraded to a more-featured // plan or a subscription was extended to get longer running) } }