You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[Handling Other Stripe Webhooks](#handling-other-stripe-webhooks)
13
14
-[Invoices](#invoices)
14
15
15
16
<aname="introduction"></a>
16
17
## Introduction
17
18
18
-
Laravel Cashier provides an expressive, fluent interface to [Stripe's](https://stripe.com) subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. In addition to basic subscription management, Cashier can handle coupons, swapping subscription, subscription "quantites", cancellation grace periods, and even generate invoice PDFs.
19
+
Laravel Cashier provides an expressive, fluent interface to [Stripe's](https://stripe.com) subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. In addition to basic subscription management, Cashier can handle coupons, swapping subscription, subscription "quantities", cancellation grace periods, and even generate invoice PDFs.
19
20
20
21
<aname="configuration"></a>
21
22
## Configuration
@@ -32,7 +33,7 @@ Next, register the `Laravel\Cashier\CashierServiceProvider` in your `app` config
32
33
33
34
#### Migration
34
35
35
-
Before using Cashier, we'll need to add several columns to your database. Don't worry, you can use the `cashier:table` Artisan command to create a migration to add the necessary column. Once the migration has been created, simply run the `migrate` command.
36
+
Before using Cashier, we'll need to add several columns to your database. Don't worry, you can use the `cashier:table` Artisan command to create a migration to add the necessary column. For example, to add the column to the users table use `php artisan cashier:table users`. Once the migration has been created, simply run the `migrate` command.
36
37
37
38
#### Model Setup
38
39
@@ -70,14 +71,24 @@ If you would like to apply a coupon when creating the subscription, you may use
70
71
->withCoupon('code')
71
72
->create($creditCardToken);
72
73
73
-
The `subscription` method will automatically create the Stripe subscription, as well as update your database with Stripe customer ID and other relevant billing information.
74
+
The `subscription` method will automatically create the Stripe subscription, as well as update your database with Stripe customer ID and other relevant billing information. If your plan has a trial configured in Stripe, the trial end date will also automatically be set on the user record.
74
75
75
-
If your plan has a trial period, make sure to set the trial end date on your model after subscribing:
76
+
If your plan has a trial period that is **not** configured in Stripe, you must set the trial end date manually after subscribing:
'email' => $email, 'description' => 'Our First Customer'
88
+
]);
89
+
90
+
To learn more about the additional fields supported by Stripe, check out Stripe's [documentation on customer creation](https://stripe.com/docs/api#create_customer).
91
+
81
92
<aname="no-card-up-front"></a>
82
93
## No Card Up Front
83
94
@@ -110,12 +121,12 @@ Sometimes subscriptions are affected by "quantity". For example, your applicatio
110
121
$user->subscription()->increment();
111
122
112
123
// Add five to the subscription's current quantity...
113
-
$user->subscription()->increment(5)
124
+
$user->subscription()->increment(5);
114
125
115
126
$user->subscription->decrement();
116
127
117
128
// Subtract five to the subscription's current quantity...
118
-
$user->subscription()->decrement(5)
129
+
$user->subscription()->decrement(5);
119
130
120
131
<aname="cancelling-a-subscription"></a>
121
132
## Cancelling A Subscription
@@ -183,6 +194,13 @@ The `everSubscribed` method may be used to determine if the user has ever subscr
183
194
//
184
195
}
185
196
197
+
The `onPlan` method may be used to determine if the user is subscribed to a given plan based on its ID:
198
+
199
+
if ($user->onPlan('monthly'))
200
+
{
201
+
//
202
+
}
203
+
186
204
<aname="handling-failed-payments"></a>
187
205
## Handling Failed Payments
188
206
@@ -192,16 +210,16 @@ What if a customer's credit card expires? No worries - Cashier includes a Webhoo
192
210
193
211
That's it! Failed payments will be captured and handled by the controller. The controller will cancel the customer's subscription after three failed payment attempts. The `stripe/webhook` URI in this example is just for example. You will need to configure the URI in your Stripe settings.
194
212
195
-
If you have additional Stripe webhook events you would like to handle, simply extend the Webhook controller:
213
+
<aname="handling-other-stripe-webhooks"></a>
214
+
## Handling Other Stripe Webhooks
215
+
216
+
If you have additional Stripe webhook events you would like to handle, simply extend the Webhook controller. Your method names should correspond to Cashier's expected convention, specifically, methods should be prefixed with `handle` and the name of the Stripe webhook you wish to handle. For example, if you wish to handle the `invoice.payment_succeeded` webhook, you should add a `handleInvoicePaymentSucceeded` method to the controller.
196
217
197
218
class WebhookController extends Laravel\Cashier\WebhookController {
198
219
199
-
public function handleWebhook()
220
+
public function handleInvoicePaymentSucceeded($payload)
Copy file name to clipboardExpand all lines: cn/upgrade.md
+10
Original file line number
Diff line number
Diff line change
@@ -20,6 +20,8 @@ Laravel 4.2需要PHP 5.4.0或更高版本。
20
20
21
21
这个设置可以用来控制Laravel加密功能使用默认密钥。
22
22
23
+
> **Note:** In Laravel 4.2, the default cipher is `MCRYPT_RIJNDAEL_128` (AES), which is considered to be the most secure cipher. Changing the cipher back to `MCRYPT_RIJNDAEL_256` is required to decrypt cookies/values that were encrypted in Laravel <= 4.1
Copy file name to clipboardExpand all lines: commands.md
+9
Original file line number
Diff line number
Diff line change
@@ -129,6 +129,15 @@ If your command is registered in the application [IoC container](/docs/ioc), you
129
129
130
130
Artisan::resolve('binding.name');
131
131
132
+
#### Registering Commands In A Service Provider
133
+
134
+
If you need to register commands from within a service provider, you should call the `commands` method from the provider's `boot` method, passing the [IoC container](/docs/ioc) binding for the command:
If you are submitting documentation for the **current stable release**, submit it to the corresponding branch. For example, documentation for Laravel 4.1 would be submitted to the `4.1` branch. Documentation intended for the next release of Laravel should be submitted to the `master` branch.
3
+
If you are submitting documentation for the **current stable release**, submit it to the corresponding branch. For example, documentation for Laravel 4.2 would be submitted to the `4.2` branch. Documentation intended for the next release of Laravel should be submitted to the `master` branch.
This route will register a "nested" resource that may be accessed with URLs like the following: `photos/{photoResource}/comments/{commentResource}`.
210
+
211
+
class PhotoCommentController extends BaseController {
212
+
213
+
public function show($photoId, $commentId)
214
+
{
215
+
//
216
+
}
217
+
218
+
}
219
+
198
220
#### Adding Additional Routes To Resource Controllers
199
221
200
222
If it becomes necessary for you to add additional routes to a resource controller beyond the default resource routes, you should define those routes before your call to `Route::resource`:
Copy file name to clipboardExpand all lines: eloquent.md
+78-1
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,7 @@
7
7
-[Soft Deleting](#soft-deleting)
8
8
-[Timestamps](#timestamps)
9
9
-[Query Scopes](#query-scopes)
10
+
-[Global Scopes](#global-scopes)
10
11
-[Relationships](#relationships)
11
12
-[Querying Relations](#querying-relations)
12
13
-[Eager Loading](#eager-loading)
@@ -373,6 +374,70 @@ Then pass the parameter into the scope call:
373
374
374
375
$users = User::ofType('member')->get();
375
376
377
+
<aname="global-scopes"></a>
378
+
## Global Scopes
379
+
380
+
Sometimes you may wish to define a scope that applies to all queries performed on a model. In essence, this is how Eloquent's own "soft delete" feature works. Global scopes are defined using a combination of PHP traits and an implementation of `Illuminate\Database\Eloquent\ScopeInterface`.
381
+
382
+
First, let's define a trait. For this example, we'll use the `SoftDeletingTrait` that ships with Laravel:
383
+
384
+
trait SoftDeletingTrait {
385
+
386
+
/**
387
+
* Boot the soft deleting trait for a model.
388
+
*
389
+
* @return void
390
+
*/
391
+
public static function bootSoftDeletingTrait()
392
+
{
393
+
static::addGlobalScope(new SoftDeletingScope);
394
+
}
395
+
396
+
}
397
+
398
+
If an Eloquent model uses a trait that has a method matching the `bootNameOfTrait` naming convention, that trait method will be called when the Eloquent model is booted, giving you an opportunity to register a global scope, or do anything else you want. A scope must implement `ScopeInterface`, which specifies two methods: `apply` and `remove`.
399
+
400
+
The `apply` method receives an `Illuminate\Database\Eloquent\Builder` query builder object, and is responsible for adding any additional `where` clauses that the scope wishes to add. The `remove` method also receives a `Builder` object and is responsible for reversing the action taken by `apply`. In other words, `remove` should remove the `where` clause (or any other clause) that was added. So, for our `SoftDeletingScope`, the methods look something like this:
401
+
402
+
/**
403
+
* Apply the scope to a given Eloquent query builder.
foreach ((array) $query->wheres as $key => $where)
428
+
{
429
+
// If the where clause is a soft delete date constraint, we will remove it from
430
+
// the query and reset the keys on the wheres. This allows this developer to
431
+
// include deleted model in a relationship result set that is lazy loaded.
432
+
if ($this->isSoftDeleteConstraint($where, $column))
433
+
{
434
+
unset($query->wheres[$key]);
435
+
436
+
$query->wheres = array_values($query->wheres);
437
+
}
438
+
}
439
+
}
440
+
376
441
<aname="relationships"></a>
377
442
## Relationships
378
443
@@ -835,6 +900,18 @@ You will often need to insert new related models. For example, you may wish to i
835
900
836
901
In this example, the `post_id` field will automatically be set on the inserted comment.
837
902
903
+
If you need to save multiple related models:
904
+
905
+
$comments = array(
906
+
new Comment(array('message' => 'A new comment.')),
907
+
new Comment(array('message' => 'Another comment.')),
908
+
new Comment(array('message' => 'The latest comment.'))
909
+
);
910
+
911
+
$post = Post::find(1);
912
+
913
+
$post->comments()->saveMany($comments);
914
+
838
915
### Associating Models (Belongs To)
839
916
840
917
When updating a `belongsTo` relationship, you may use the `associate` method. This method will set the foreign key on the child model:
@@ -1069,7 +1146,7 @@ Mutators are declared in a similar fashion:
1069
1146
<aname="date-mutators"></a>
1070
1147
## Date Mutators
1071
1148
1072
-
By default, Eloquent will convert the `created_at`, `updated_at`, and `deleted_at` columns to instances of [Carbon](https://github.com/briannesbitt/Carbon), which provides an assortment of helpful methods, and extends the native PHP `DateTime` class.
1149
+
By default, Eloquent will convert the `created_at`and `updated_at` columns to instances of [Carbon](https://github.com/briannesbitt/Carbon), which provides an assortment of helpful methods, and extends the native PHP `DateTime` class.
1073
1150
1074
1151
You may customize which fields are automatically mutated, and even completely disable this mutation, by overriding the `getDates` method of the model:
Copy file name to clipboardExpand all lines: extending.md
+7-1
Original file line number
Diff line number
Diff line change
@@ -85,7 +85,7 @@ Extending Laravel with a custom session driver is just as easy as extending the
85
85
86
86
### Where To Extend The Session
87
87
88
-
Session extensions need to be registered differently than other extensions like Cache and Auth. Since sessions are started very early in the request-lifecycle, registering the extensions in a `start` file will happen be too late. Instead, a [service provider](/docs/ioc#service-providers) will be needed. You should place your session extension code in the `register` method of your service provider, and the provider should be placed **below** the default `Illuminate\Session\SessionServiceProvider` in the `providers` configuration array.
88
+
Session extensions need to be registered differently than other extensions like Cache and Auth. Since sessions are started very early in the request-lifecycle, registering the extensions in a `start` file will happen too late. Instead, a [service provider](/docs/ioc#service-providers) will be needed. You should place your session extension code in the `register` method of your service provider, and the provider should be placed **below** the default `Illuminate\Session\SessionServiceProvider` in the `providers` configuration array.
89
89
90
90
### Writing The Session Extension
91
91
@@ -139,13 +139,19 @@ Let's take a look at the `UserProviderInterface`:
139
139
interface UserProviderInterface {
140
140
141
141
public function retrieveById($identifier);
142
+
public function retrieveByToken($identifier, $token);
143
+
public function updateRememberToken(UserInterface $user, $token);
142
144
public function retrieveByCredentials(array $credentials);
143
145
public function validateCredentials(UserInterface $user, array $credentials);
144
146
145
147
}
146
148
147
149
The `retrieveById` function typically receives a numeric key representing the user, such as an auto-incrementing ID from a MySQL database. The `UserInterface` implementation matching the ID should be retrieved and returned by the method.
148
150
151
+
The `retrieveByToken` function retrieves a user by their unique `$identifier` and "remember me" `$token`, stored in a field `remember_token`. As with with previous method, the `UserInterface` implementation should be returned.
152
+
153
+
The `updateRememberToken` method updates the `$user` field `remember_token` with the new `$token`. The new token can be either a fresh token, assigned on successfull "remember me" login attempt, or a null when user is logged out.
154
+
149
155
The `retrieveByCredentials` method receives the array of credentials passed to the `Auth::attempt` method when attempting to sign into an application. The method should then "query" the underlying persistent storage for the user matching those credentials. Typically, this method will run a query with a "where" condition on `$credentials['username']`. **This method should not attempt to do any password validation or authentication.**
150
156
151
157
The `validateCredentials` method should compare the given `$user` with the `$credentials` to authenticate the user. For example, this method might compare the `$user->getAuthPassword()` string to a `Hash::make` of `$credentials['password']`.
Copy file name to clipboardExpand all lines: mail.md
+1-1
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,7 @@ To use the Mailgun driver, set the `driver` option to `mailgun` in your `app/con
28
28
29
29
#### Mandrill Driver
30
30
31
-
To use the Mailgun driver, set the `driver` option to `mandrill` in your `app/config/mail.php` configuration file. Next, create an `app/config/services.php` configuration file if one does not already exist for your project. Verify that it contains the following options:
31
+
To use the Mandrill driver, set the `driver` option to `mandrill` in your `app/config/mail.php` configuration file. Next, create an `app/config/services.php` configuration file if one does not already exist for your project. Verify that it contains the following options:
Copy file name to clipboardExpand all lines: pagination.md
+3-1
Original file line number
Diff line number
Diff line change
@@ -22,6 +22,8 @@ There are several ways to paginate items. The simplest is by using the `paginate
22
22
23
23
$users = DB::table('users')->paginate(15);
24
24
25
+
> **Note:** Currently, pagination operations that use a `groupBy` statement cannot be executed efficiently by Laravel. If you need to use a `groupBy` with a paginated result set, it is recommended that you query the database manually and use `Paginator::make`.
26
+
25
27
#### Paginating An Eloquent Model
26
28
27
29
You may also paginate [Eloquent](/docs/eloquent) models:
@@ -101,7 +103,7 @@ This method call will generate URLs that look something like this:
101
103
<aname="converting-to-json"></a>
102
104
## Converting To JSON
103
105
104
-
The `Paginator` class implements the `Illuminate\Support\Contracts\JsonableInterface` contract and exposes the `toJson` method. You can may also convert a `Paginator` instance to JSON by returning it from a route. The JSON'd form of the instance will include some "meta" information such as `total`, `current_page`, `last_page`, `from`, and `to`. The instance's data will be available via the `data` key in the JSON array.
106
+
The `Paginator` class implements the `Illuminate\Support\Contracts\JsonableInterface` contract and exposes the `toJson` method. You may also convert a `Paginator` instance to JSON by returning it from a route. The JSON'd form of the instance will include some "meta" information such as `total`, `current_page`, `last_page`, `from`, and `to`. The instance's data will be available via the `data` key in the JSON array.
0 commit comments