vvmalko/subscriptions

laravel 5 应用程序的订阅处理包

dev-master 2016-02-08 03:36 UTC

This package is not auto-updated.

Last update: 2024-09-20 17:33:49 UTC


README

从laravel 4包迁移而来。原始地址: ipunkt/subscriptions

Laravel 5.x 应用程序的订阅包

Latest Stable Version Latest Unstable Version License Total Downloads

安装

在 composer.json 中添加以下行

	"require": {
		"vvmalko/subscriptions": "dev-master"
	}

运行 php artisan vendor:publish

然后编辑 config/vvmalko/plans.phpconfig/vvmalko/defaults.php 以满足您的需求。所有已知计划都在那里。

vvMalko\Subscriptions\SubscriptionsServiceProvider::class, 添加到 config/app.phpproviders 中。

'Subscription' => vvMalko\Subscriptions\SubscriptionsFacade::class, 添加到 config/app.phpaliases 中。

运行 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)
        }
    }