Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Method Calls from Templates Fail


Go to End
Reply

11 Posts   2286 Views

Avatar
arsenic

14 January 2010 at 3:59pm (Last edited: 14 January 2010 4:17pm), Community Member, 9 Posts

In one of my controllers, a method returns a DataObjectSet of plain objects. Lets say the objects' class has a method called objectMethod that returns a value. In the template, I loop through the DSO with with <% control %> and print the value of objectMethod with $objectMethod. However it doesn't print. The template documentation says that $obj->objectMethod() should have been called. Fields work fine. What's happening?

Avatar
Willr

14 January 2010 at 4:35pm Forum Moderator, 5511 Posts

Might be helpful if you post the affected code :D

Avatar
arsenic

14 January 2010 at 4:41pm (Last edited: 14 January 2010 4:44pm), Community Member, 9 Posts

Cart.php:

class Cart {
var $_items = array(); // array of Cart_Items

...

function getItems() {
return new DataObjectSet($this->_items);
}
}

class Cart_Item {
var $_id;

function getSubtotal() {
return 0; // for testing
}
}

class Cart_Controller extends Controller {

...

function getItems() {
return $this->_cart->getItems(); // $this->_cart is an instance of Cart
}

}

Cart.ss:

<% control getItems %>
$getSubtotal // doesn't work
$_id // works
<% end_control %>

Avatar
CodeGuerrilla

14 January 2010 at 6:59pm (Last edited: 14 January 2010 7:01pm), Community Member, 105 Posts

I think it is because you are inside a control getSubtotal is another control try using $Top to break out of the controls varibles to the controllers top level functions, also it looks like getSubtotal should be in the Cart_Controller and retrieve the value from Cart_Items?

<% control getItems %>
$Top.getSubtotal // should work
$_id // must be a property of getItems ?
<% end_control %>

This is a common confusion with SilverStripe has got me once or twice

Avatar
arsenic

15 January 2010 at 5:09am (Last edited: 15 January 2010 5:27am), Community Member, 9 Posts

_id and getSubtotal are in Cart_Item. getSubtotal multiplies the price of an item with its quantity. getItems returns an array of Cart_Items. Shouldn't <% control getItems %> loop through the array of Cart_Items, in which I can call the properties and methods of each Cart_Item?

Avatar
CodeGuerrilla

15 January 2010 at 11:41am (Last edited: 15 January 2010 11:50am), Community Member, 105 Posts

Hmm I guess you can do that the Cart I have wrote for SilverStripe uses the SessionID in the Cart table and you call the getSubTotal from the Cart object (you could also do this with SQL and have a field to store it in the Cart DataObject)

Cart.php (dataobject)

...

public function getSubTotal()
   {
      $items = self::getBySessionID(session_id());
      $out = array();
      if($items) {
         foreach($items as $item) {
            array_push($out, ($item->Price * $item->Quantity));
         }
         return array_sum($out);
      }
   }

public function getBySessionID($SessionID)
   {
      return DataObject::get("Cart", sprintf("SessionID = '%s'", $SessionID));
   }
...

page.php (want these functions global)
Page_Controller

...

public function CartItems()
{
      $items = Cart::getBySessionID(session_id());
      return $items;
}

public function SubTotal()
{
      return number_format(Cart::getSubTotal(), 2);
}

...

Cart.ss (template include)

<table width="213" cellpadding="2" cellspacing="0">
<% if CartItems %>
<tr>
<th align="left" class="borderleft">Product</th>
<th align="left">Price</th>
<th align="center">Qty</th>
<th align="right">Total</th>
<th align="right">&nbsp;</th>
</tr>
<% end_if %>
<% if CartItems %>
<% control CartItems %>
<tr>
<td class="borderleft"><a href="$Product.URLSegment/">$Product.Title</a></td>
<td>$Product.Price</td>
<td align="center"><form action="$Top.URLSegment/update" method="post"><div><input name="Quantity" class="quantity" value="$Quantity" size="1" maxlength="2" /><input type="hidden" name="CartID" value="$ID" /></div></form></td>
   <td align="right">$Total</td>
<td align="center"><a href="$Top.URLSegment/remove/$ID">x</a></td>
</tr>
<% end_control %>
<% else %>
      <tr class="empty"><td class="noborder" colspan="5">Your cart is currently empty.</td></tr>
<% end_if %>
<% if CartItems %>
<% if UseGST %>
<tr>
<td align="left" valign="bottom" class="noborder">&nbsp;</td>
<td colspan="2" align="right" class="noborder">Sub Total</td>
<td align="right" nowrap="nowrap" class="borderleft">$SubTotal</td>
<td align="right">&nbsp;</td>
</tr>
<tr>
<td align="left" valign="bottom" class="noborder">&nbsp;</td>
<td colspan="2" align="right" class="noborder">GST</td>
<td align="right" class="borderleft">$GST</td>
<td align="right">&nbsp;</td>
</tr>
<% end_if %>
<tr>
<td align="left" valign="bottom" class="noborder">&nbsp;</td>
<td colspan="2" align="right" class="noborder"><strong>Total</strong></td>
<td align="right" class="borderleft"><strong>$$GrandTotal</strong></td>
<td align="right">&nbsp;</td>
</tr>
<% end_if %>
</table>

This seems to work well enough is probally a more pure SS way though hope this helps.

Avatar
arsenic

15 January 2010 at 2:38pm (Last edited: 15 January 2010 2:42pm), Community Member, 9 Posts

Thanks for the code, but I think there is a larger, more serious, problem.

The following test case does not work:

Test.php

class Apple {

   var $_color;

   function __construct($color) {
      $this->_color = $color;
   }

   function getColor() {
      return $this->_color;
   }
}

class Test_Controller extends Controller {
   function init() {
      parent::init();
   }

   function getApples() {
      $a = array();
      $a[] = new Apple('red');
      $a[] = new Apple('green');

      return new DataObjectSet($a);
   }
}

Test.ss:

<% control getApples %>
$_color // prints red and green
$getColor // does not print anything
<% end_control %>

Avatar
CodeGuerrilla

15 January 2010 at 2:52pm (Last edited: 15 January 2010 2:52pm), Community Member, 105 Posts

You might have to use them statically depends on the way SilverStripe initializes the functions if it is statically then __construct may not be called you would have to do the new Apple('red') as this calls the constructor. So I am guessing SS is calling it like Apple::getColor()

Go to Top