Guest blogger Ryan Wachtl is an independent US-based web developer and experienced designer with a passion for the art of programming and the science of design. He has been building sites with SilverStripe since the early 2.2 release and organizes the SilverStripe user group in Madison, WI. You can stay in touch by following @ryanwachtl on Twitter.
There comes a time for just about every web designer when the requirements for a project call for some type of e-commerce functionality. The world of online commerce is full of extra considerations like: SSL certificates, PCI compliance, merchant accounts, payment gateways and charging the appropriate taxes, to name a few. Understanding your needs and constraints is the first step to getting a hold on e-commerce.
If you have the time and budget to fully integrate an e-commerce solution into your SilverStripe site you can start with the E-Commerce module or SilverCart, which will both bring order management, customer accounts, and on-site payment processing with them. Perhaps you need a hybrid solution like FoxyStripe, which offers a lot customization opportunities and takes the hassle out of handling credit cards and customer data on your site. If you're in the mood to really flex your skills, you can also leverage the power and flexibility of the SilverStripe Framework and roll your own solution.
Sometimes all these options are over-kill and all that's required is a quick and simple way to sell items. Basically, you just need a cart to place items into and a way for customers to pay for them. I've found the PayPal Mini Cart to be a near perfect fit for this situation. The Mini Cart allows you to run your own shopping cart on your website and then forwards the order to PayPal where your customer can complete the purchase. The cart requires javascript, but will fallback to using PayPal's hosted cart in the event that javascript is not available. Essentially, it's an enhancement to the standard PayPal buttons that you can add to a website. Follow along with me as we build a portable and light-weight e-commerce solution for SilverStripe. We'll be covering some key SilverStripe development topics like modules, extensions, and shortcodes.
Here's a preview of what we're going to build.
To start off I've a clean install of SilverStripe 2.4.5 using the Black Candy theme. We could just start plugging things into our site until we've got a working cart, but we want something that we can drop into any SilverStripe project and get up and running with just a little configuration. We're going to build a module, so let's start by building out our structure.
Module File Structure
Our module will reside in a folder called module_minicart. We need _config.php so SilverStripe will register our module and then we add folders to house our code, templates and thirdparty code. The Mini Cart project is located on PayPal Labs and the source code is hosted on GitHub. We're going to grab the latest version of Mini Cart on GitHub (2.0.6 at the time of this writing) and drop it into our thirdparty folder.
_Config.php
Let's open up some php tags and get _config.php laid out.
define('MODULE_MINICART_DIR', 'module_minicart');
DataObject::add_extension('SiteTree', 'MiniCart');
ShortcodeParser::get()->register('mini_cart_item', array('MiniCart', 'MiniCartItemShortcodeHandler'));
MiniCart::set_business_email("me@example.com");
MiniCart::set_currency_code("USD");
MiniCart::set_return_url("https://example.com/page?success");
MiniCart::set_cancel_return_url("https://example.com/page?cancel");
config.php
First we define a constant for our module directory, in the event that we want to rename our folder we can just update it here and all file path references will remain intact. We then add an extension to SiteTree which allows us to add methods and make our functionality available to our Page class, any descendants of Page, or any new classes that directly extend SiteTree. The next line registers our shortcode, which we'll use to insert an 'add to cart' button into the content area of pages in the cms. And finally we allow for some settings that will be used in our code. Allowing a user to set their PayPal email address, currency, and the web pages that a customer should be directed to after a completed or canceled transaction, respectively.
MiniCart.php
We'll create a class called MiniCart to add our needed methods to SiteTree.
class MiniCart extends DataObjectDecorator {
protected static $business_email = "labs-feedback-minicart@paypal.com";
protected static $currency_code = "USD";
protected static $return_url = "https://minicart.paypal-labs.com/?success";
protected static $cancel_return_url = "https://minicart.paypal-labs.com/?cancel";
public static function set_business_email($email) {
self::$business_email = $email;
}
public static function set_currency_code($code) {
self::$currency_code = $code;
}
public static function set_return_url($url) {
self::$return_url = $url;
}
public static function set_cancel_return_url($url) {
self::$cancel_return_url = $url;
}
}
MiniCart.php
Here we create some default values for our settings and a way to set them in _config.php
Now we need to make sure the Mini Cart and its resources are loaded on all our pages.
class MiniCart extends DataObjectDecorator {
...
function contentcontrollerInit($controller) {
Requirements::javascript(
MODULE_MINICART_DIR . '/thirdparty/minicart/minicart.js'
);
Requirements::customScript('PAYPAL.apps.MiniCart.render();', 'minicart');
}
}
MiniCart.php
Although we aren't directly extending the ContentController we can still add our script requirements by using contentcontrollerInit, allowing us to include the Mini Cart javascript in our pages and initialize the Mini Cart.
Shortcode
We registered our shortcode in _config.php but SilverStripe does not know what we want to do with it yet. A method we define as MiniCartItemShortcodeHandler will process our shortcode and return the markup for our template.
class MiniCart extends DataObjectDecorator {
...
public static function MiniCartItemShortcodeHandler($attributes, $content = null, $parser = null) {
if(empty($attributes['name']) || empty($attributes['price'])) {
return;
}
$item_name = $attributes['name'];
$item_price = $attributes['price'];
$button = (!empty($content)) ? $content : "Add to cart";
$data = new ArrayData(
array(
'ItemName' => $item_name,
'Amount' => $item_price,
'Button' => $button,
'Business' => self::$business_email,
'CurrencyCode' => self::$currency_code,
'Return' => self::$return_url,
'Cancel' => self::$cancel_return_url
)
);
return $data->renderWith('MiniCartItem');
}
...
}
MiniCart.php
MiniCartItemShortcodeHandler takes the attributes entered by the user in the shortcode, builds a ViewableData object with them, and then renders them with a template that we'll create called MiniCartItem.ss.
<fieldset>
<input type="hidden" name="cmd" value="_cart" />
<input type="hidden" name="add" value="1" />
<input type="hidden" name="business" value="$Business" />
<input type="hidden" name="item_name" value="$ItemName" />
<input type="hidden" name="amount" value="$Amount" />
<input type="hidden" name="currency_code" value="$CurrencyCode" />
<input type="hidden" name="return" value="$Return" />
<input type="hidden" name="cancel_return" value="$Cancel" />
<p><strong>$ItemName</strong><br />${$Amount}</p>
<input type="submit" name="submit" value="$Button" class="button" />
</fieldset>
</form>
MiniCartItem.ss
Wrapping it up
Finally, we need a way to add a 'view cart' button to our site. We'll accomplish this by creating a method that can be used as a placeholder in our template and inserts our button.
class MiniCart extends DataObjectDecorator {
...
public function ViewCart($button = "View your cart") {
$data = new ArrayData(
array(
'Business' => self::$business_email,
'Button' => $button
)
);
return $data->renderWith('ViewCart');
}
...
}
MiniCart.php
and ViewCart.ss to render our code.
<fieldset>
<input type="hidden" name="business" value="$Business" />
<input type="hidden" name="cmd" value="_cart" />
<input type="hidden" name="display" value="1" />
<input type="submit" name="submit" value="$Button" class="button" />
</fieldset>
</form>
ViewCart.ss
We now have a functional and portable module that we can drop into our projects or share with others. To use our Mini Cart module we place our shortcode in the content area of any page in the cms that we want to add an "add to cart" button to.
[mini_cart_item name="ITEM NAME" price="0.00"]
and then place our ViewCart placeholder into our template wherever we want the 'view cart' button. This could be in the sidebar, header or another site-wide region.
Taking our module further
With our module we are able to give an item a name and price that can be added to our cart. We could expand this to except selectable options for an item (see the PayPal button designer for ideas on what features you can use). The Mini Cart itself is also customizable and comes with a rich javascript API.
Get the code
We've covered building a basic SilverStripe module by extending the core and giving users some powerful tools in the way of shortcodes. I hope the topics and techniques discussed here will help you in integrating your own e-commerce solution or building your own modules for SilverStripe. You can download the completed SilverStripe Mini Cart module on GitHub.