How to add ordering to a custom module list with LemonStand.

It took me a long time to figure out how to add sorting to a LemonStand list view.

Honestly, adding a simple M2M relationship in LS took me many many hours and modification of 4 partials. It takes me about 30 seconds with Django. The documentation is hard to read (but a part of the problem is just low volume / lack of search results) and mostly you just have to read the source.

Working with LS or Magento gives me a newfound appreciation for my frameworks of choice: Django or Flask + SQLAlchemy. It’s truly like magic in comparison. To be fair, those are tool for building web apps and nothing comes “in the box”. It’s just what I prefer.

Anyways, please forgive the quality of the post; I would have killed for somebody to write even half of the below. Hope it helps you guys!

Mostly we are going to copy functionality from the “manage top products”. I am not even going to bother with renaming things. Surprisingly, no new assets are required, and there is no hacking of core LS required.

Follow along.

Copy from the shop_categories.php controller

Copy the “top products” action code from the Category controller into your own controller, copying templates and modifying code as needed.


Make sure you are $implementing (subclassing)

public $implement = 'Db_ListBehavior, Db_FilterBehavior, Db_FormBehavior';

Take the relevant pieces from the __construct function in shop_categories.php

if (Phpr::$router->action == 'manage_top_products')
	$this->list_no_pagination = true;
	$this->list_render_as_tree = false;
	$this->list_render_as_sliding_list = false;
	$this->list_model_class = 'Shop_Product';

	$this->list_custom_body_cells = PATH_APP.'/modules/shop/controllers/shop_categories/_top_product_body_cells.htm';
	$this->list_custom_head_cells = PATH_APP.'/modules/shop/controllers/shop_categories/_top_product_head_cells.htm';
	$this->list_custom_prepare_func = 'prepare_top_product_list';
	$this->list_record_url = null;
	$this->list_search_enabled = false;
	$this->list_no_setup_link = false;
	$this->list_no_setup_link = false;
	$this->list_no_data_message = 'There are no top products in this category';
	$this->list_name = 'top_products_list';
	$this->list_no_sorting = true;

I ended up copying these, but it turns out you don’t need to modify anything so it’s not a strict requirement.

Remove list_record_url / add your own, to make sure edit links work.

– ‘/modules/shop/controllers/shop_categories/_top_product_body_cells.htm’;
– ‘/modules/shop/controllers/shop_categories/_top_product_head_cells.htm’;

Override sorting

The page has no default sorting, so nothing will appear to work without this sort override. Paste this function into your controller, and supply the appropriate sort field (sort_field)

	public function listOverrideSortingColumn($sorting_column)
		if (Phpr::$router->action == 'reorder_categories')
			$result = array('field'=>'front_end_sort_order', 'direction'=>'asc');
			return (object)$result;

		return $sorting_column;

The AJAX set order function

Modify the class Shop_Category with your class. Make sure your class $implements Db_Sortable to get access to the set_orders function.

	protected function reorder_categories_onSetOrders()
			Shop_Category::set_orders(post('item_ids'), post('sort_orders'));
		catch (Exception $ex)
			Phpr::$response->ajaxReportException($ex, true, true);

The Sort field getter function

Copy the function that takes an ID and returns the sort field. This was done because the sort field is not even on the product model directly.

Note that since I only have access to an ID, I am doing a very inefficient one query per sort field lookup. Oh well.

	protected function get_top_product_sort_order($id)
		// return sort order for our model, given its ID.
		$ambassador = new Raen_Ambassador();
		$ambassador_sort_order = $ambassador->find_by_id($id)->sort_order;
		return $ambassador_sort_order;

Copy sorting javascript

Copy the sorting javascript header block from manage_top_products.htm

In my case, I injected the followingn block into my module index.html file.

<? Phpr_View::beginBlock("head") ?>
	<script type="text/javascript" src="modules/shop/resources/javascript/top_category_products.js"></script>
	<link rel="stylesheet" href="modules/shop/resources/css/shop.css" type="text/css"/>
<? Phpr_View::endBlock() ?>

Modify your Models

Add sort field

Make sure your model has a sort_order field. It must be named sort_order, as the DB_Sortable has hard coded values.

Add Db_Sortable to your $implement.

Add after_create default sort order

Make sure a default sort order is applied to new elements, or sorting likes to blow up.

	public static function create()
		return new self();

	public function after_create()
		Db_DbHelper::query("UPDATE {$this->table_name} set sort_order=:sort_order where id=:id", array(


Surprisingly, this works now w/o any modification to method names🙂

Completed controller for reference:
Completed model for reference: (sans fields)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s