Photo by Mein Deal on Unsplash

Laravel Shopr: How to add shipping to your checkout

Laravel Shopr is a package for integrating e-commerce into your Laravel app. It gives you a shopping cart with discount coupons and a full checkout flow, just to mention a few of the useful features included.
In this guide we won’t discuss how to install or get started with the package, since it’s covered in detail in the documentation.

Conceptual overview

Basically, the flow will look like this:

  1. On the checkout page, the customer can select one of the available shipping options.
  2. Before making the request to pay for the cart and convert it to an order, we’ll add the selected shipping option to the cart as a regular item.
  3. In the confirmation templates, we can easily customize how the shipping option is displayed.

That’s it!

Adding shipping options to your checkout

Schema::create('shipping_methods', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('description')->nullable();
$table->integer('sortorder')->default(0);
$table->decimal('price', 9, 2)->default(0);

// This column allows us to add a
// "free for orders worth x or more"-feature.
// More on that further down.
$table->decimal('free_level', 9, 2)->nullable();

$table->timestamps();
$table->softDeletes();
});

And the model, which extends the Shoppable class instead of the default Model class.

<?phpnamespace App\Models;use Happypixels\Shopr\Models\Shoppable;
use Illuminate\Database\Eloquent\SoftDeletes;
class ShippingMethod extends Shoppable
{
use SoftDeletes;
}

Next, we’ll create an endpoint for retrieving the available shipping options on the checkout page. This will be called to present the options to the customer.

<?phpnamespace App\Http\Controllers;use App\Models\ShippingMethod;class ShippingMethodController extends Controller
{
public function index()
{
return ShippingMethod::orderBy('sortorder', 'ASC')->get();
}
}

Don’t forget to also add a route for it.

You then present a few radio buttons or similar which allows the customer to select their desired shipping method.
In this example we’ll use Stripe to process the payments, so we want to add the shipping option to the cart after retrieving the Stripe token but before making the charge request. For more details on the Stripe checkout flow, check out the demo implementation.

methods: {
charge (token) {
window.axios.post('shopr/cart/items', {
shoppable_type: 'App\\Models\\ShippingMethod',
shoppable_id: this.userData.options.shipping.id
}).then(response => {
// Make the charge request to process the payment.
})
}
}

We have now added the selected shipping method to our order. The price is automatically added to the order total and everything should work. However, we want to exclude it from the order items table in the confirmation template. This is done by filtering the order items by their shoppable_type (the model).

// The order-confirmation blade template as configured in config/shopr.php.@foreach($order->items->where('shoppable_type', '!=', 'App\Models\ShippingMethod') as $item)
// Print order row.
@endforeach

To make it more testable and keep the logics away from your template, you might want to use custom models for your order and add a `printableItems` method or something similar to it which filters out the shipping option row. Then, just call the `$order->printableItems` in the confirmation template. To access the shipping method, add another method which does the opposite (only returns the shipping method).
Read more about how to use custom models for your orders in the documentation.

All done!

Bonus: using a dynamic price for a shipping option

<?phpnamespace App\Models;use Happypixels\Shopr\Contracts\Cart;
use Happypixels\Shopr\Models\Shoppable;
use Illuminate\Database\Eloquent\SoftDeletes;
class ShippingMethod extends Shoppable
{
use SoftDeletes;
protected $casts = [
'price' => 'float',
'free_level' => 'float',
];
public function getPrice()
{
$cartValue = app(Cart::class)->total();
if ($this->free_level !== null && $cartValue >= $this->free_level) {
return 0;
}
return $this->price;
}
}

Don’t forget to make sure your frontend displays the correct price for the shipping method as well.

Owner of Happy Pixels. Certified Laravel developer.

Owner of Happy Pixels. Certified Laravel developer.