About Zenserve

Zenserve Web Development Blog

Silverstripe 2.4.* running on PHP5.4

If your website is still powered by Silverstripe 2.4.* but your hosting server already upgrades PHP from 5.3 to 5.4, you will have this error in a couple of places

[Notice] Array to string conversion

Line 386 in ...../sapphire/core/control/Controller.php

377 /**
378 * Returns true if the member is allowed to do the given action.
379 * @param perm The permission to be checked, such as 'View'.
380 * @param member The member whose permissions need checking. Defaults to the currently logged
381 * in user.
382 * @return boolean
383 */
384 function can($perm, $member = null) {
385 if(!$member) $member = Member::currentUser();
386 if($this->hasMethod($methodName = 'can' . $perm)) {

Just change line 386 to

386 if(is_string($perm) && $this->hasMethod($methodName = 'can' . $perm)) {

Also, in the core/SSViewer.php#L162
update it to:

if(is_string($templateList) && substr($templateList,-3) == '.ss') {

Ideally, SS should be upgraded to 3 or above.

Posted in PHP Programming, Silverstripe |

Junior PHP programmer Required

We are looking for a bright, young, dynamic junior or trainee PHP programmer who loves coding in our Shrewsbury office. If you are just out of college fresh with no commercial PHP or Java programming experience we are interested as well. However, You need to know the basic of programming (in whatever programming language), such as some basic algorithms (Loop, Recursive, Search a tree) and data structure (Queue, Stacks, Tree etc), the concept of Object Oriented and MVC structure.

As a junior programmer, we expect you to have a strong passion to learn to achieve new skills and experience. You will be working in a young, fun and talented team, therefore we would like you equipped with good communication skills.

We will be using PHP, Javascript, Jquery, CSS, Compass on Linux/Apache/MySQL platform. We use some PHP frameworks like Yii, Silverstripe or Codeignitor depending on customer requirements. We also sometimes use OpenCart, Magento, WordPress if customer strongly requires.

If you are interested, please email us [email protected]

Posted in PHP Programming |

VAT price wrong for grouped products

There is a serious bug in Magento for grouped products and it has been there for a couple years but Magento still has not issued a fixed. It was originally reported here


To fix the problem is actually relatively easy. Just loop through the products, get the minimal price of the associated products and display it at the right place.

$_product = $this->getProduct();

$aProductIds = $_product->getTypeInstance()->getChildrenIds($_product->getId());
$minprice = 99999999999999;
$_finalPriceIncTax = '';
$_finalPriceExclTax = '';
foreach ($aProductIds as $ids)
foreach ($ids as $id)
$aProduct = Mage::getModel('catalog/product')->load($id);
//get the smallest price for a product
if ($minprice > $aProduct->getPriceModel()->getPrice($aProduct))
$minprice = $aProduct->getPriceModel()->getPrice($aProduct);
$_finalPriceIncTax = $_taxHelper->getPrice($aProduct, $aProduct->getFinalPrice(), true);
$_finalPriceExclTax = $_taxHelper->getPrice($aProduct, $aProduct->getFinalPrice(), false);

and then display the prices:

From currency($_finalPriceIncTax, true, false);

(ex VAT currency( $_finalPriceExclTax, true, false);

Posted in Magento |

GridField return ‘No Items Found’

First thing you need to check is the related object of the data source of the Gridfield is viewable or not. For example, if you need to manage the has_one Profile object of class Member, you need to define this method in your profile

class Profile extends DataObject {

static $has_one = array('owner'=>'Member');

public function canView($member=null){
if($member ==null ) $member = Member::currentUser();
if($member ==null | $member->ID < 1 ) return false; if($member->ID == $this->OwnerID ) return true;

if(Permission::check('ADMIN')) return true;

return false;


Then in your Member extension class

class MemberExtension extends DataExtension {
function updateCMSFields(FieldList $fields) {
$config = GridFieldConfig::create();
$config->addComponent(new GridFieldToolbarHeader());
$config->addComponent(new GridFieldDetailForm());
$profileFd = new GridField("Profile", "Profile",$this->owner->Profile(), $config);
$fields->addFieldToTab('Root.Profile', $profileFd);


Posted in Silverstripe |

Siteconfig for content authors

In Silversripe 2.4.7, if you need to allow content authors to edit your site config settings, you need to click on the permission tab and give ‘Manage site settings’ to the right user. However, this doesn’t work on SS3.0. Here is our work around:

In your mysite/codes folder, create a new file called SiteConfigAdmin.php with the following content:

class SiteConfigAdmin extends CMSSettingsController {

static $url_segment = 'settings';
static $url_rule = '/$Action/$ID/$OtherID';
static $menu_priority = -1;
static $menu_title = 'Site configs';
static $tree_class = 'SiteConfig';

function canView($member = null) {
if($member==null) $member = Member::currentUser();
//only for content editor
if($member && $member->ID && $member->inGroup(MemberExtension::$contentEditor))
return true;
else return false;


and then run /dev/build, login the site as a content authors, you will see the ‘Site Configs’ menu on the left which points to the same page as ‘Settings’ when you login as the super admin.

Posted in Silverstripe | Tagged , , , , |

Saving POINT() geometries in SilverStripe DataObjects

I encountered an issue while trying to set up a POINT field with a spatial index.

A spatial index in MySQL allows us to do some very fast searches based on locations of ‘objects’ in the database. However, the requirement is that Geometry fields on the table are ‘not null,’ so to save a record we must also include a valid Geometry – in this case a POINT field.

The problem then comes when a new record is created.

In the write() method in SilverStripe’s DataObject class, after a few checks, it’ll try to create a new record if it doesn’t exist (around line 990). This is so that the record ID can be retrieved, then other data is saved to that record.

Since this initial record creation does not include any values other than a ‘Created’ field, the constraint on the Geometry field fails and MySQL returns an error. Therefore, nothing is saved to the database.

The resolution is fairly simple; we need to save the initial record in a valid way and assign the new ID to the object, thus overriding the default record creation.

To do this we use the onBeforeWrite() method on the object. Note that my field name is called ‘Location.’

public function onBeforeWrite () {
// Is this a new record?
if(!$this->ID) {
// If we want a proper geo field with spatial index, the record must always have some value for location
// We need to save some default values else MySQL returns an error and nothing gets saved
// See around DataObject.php:984-994 for this bit
$baseTable = $this->baseTable();
DB::query("INSERT INTO \"".$baseTable."\" (\"Created\", \"Location\") VALUES (" . DB::getConn()->now() . ", GeomFromText('POINT(0 0)'))");
$this->record['ID'] = DB::getGeneratedID($baseTable);
return parent::onBeforeWrite();

That’s it! We save the initial record with the required value for Location and get back the ID.

Posted in Silverstripe | Tagged |

How to read Access database file
(mdb) using PHP

Microsoft Access support in PHP can be done via PECL’s ext/mdbtools extension, which is maintained by Hartmut Holzgraefe. This extension is itself a wrapper around the MDBTools package (https://github.com/brianb/mdbtools), which provides a set of tools to read Access database schema and records.

1. Install mdbtools
If you are running your server on Centos, it is easy to install mdbtools
yum install mdbtools
yum install mdbtools-devel

2. Install pecl mdbtools extension
login as root and run
pecl install mdbtools

If you like manual install, please download the latest from http://pecl.php.net/package/mdbtools, untar it, cd to the source folder then run the following:
make install

If you are running a cpanel server, you can install the pecl package via the WHM interface.

3. To use it
-. upload a mdb test file. You can get a sample mdb file from your Microsoft Access installation folder. We found Nwin.mdb

-. Here is a sample script to list all tables in the mdb and find out the number of records of each table:

// initialize database handle
$mdb = mdb_open('Nwind.mdb');
if ($mdb === false) {
die('ERROR: Cannot initialize database handle');

// get table listing
$tables = mdb_tables($mdb) or die('ERROR: Cannot get table listing');
if (sizeof($tables) > 0) {

echo '<h2>Table found: </h2>';

foreach ($tables as $t) {
echo 'opening table '. $t . '<br/>';

$tbl = mdb_table_open($mdb, $t) or die('ERROR: Cannot open table ' . $t);

// find and print number of records in table
$rows = mdb_num_rows($tbl);
echo "$t has ($rows) records <br/>\n";

// close table

// destroy database handle

Posted in PHP Programming |

How to extract all frames from
a gif image

If you would like to update an animated gif image and you don’t have the source file (PSD probably), you need to extract all frames from the gif image, update each frame and then assemble it back using Photoshop or other GIF animation software.

There are a couple of ways to extract frames from a GIF image:

1. Adobe flash
Use Adobe flash to open the gif file, all the frames will appear in the library.
Place the item from the library onto the main timeline, and do File->Export->Export Image

2. GIF Frame Extractor
GIF Frame Extractor is a free tool for Windows that lets you extract frames from any animated GIF and save them to JPG or PNG image formats instantly.

Run the tool, click Open and select the GIF animation whose frames you want to extract. You will see the number of frames on the left sidebar.

Select any frame that you want to extract and click Save. You can choose whether to save them in JPG or PNG format.

Posted in IT support |

New Zenserve Blog

We’ve now set-up our new blog section in which we plan to regularly post technical articles about web development, software, support and emerging technologies. Visit regularly to get the latest articles that you may find useful as a design and web agency.

We’ll also be posting about developments at Zenserve, details of new services and status updates regarding web servers you may have with us, regarding scheduled maintenance.

See you again soon.

Posted in IT support, PHP Programming, Web Hosting |

Zenserve I.T. Ltd
Claremont House, Claremont Bank
Shrewsbury, Shropshire

Telephone: 0845 0132289

© Zenserve IT Limited 2014 | All Rights Reserved