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   2472 Views

Avatar
arsenic

Community Member, 9 Posts

14 January 2010 at 3:59pm

Edited: 14/01/2010 4:17pm

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

Forum Moderator, 5513 Posts

14 January 2010 at 4:35pm

Might be helpful if you post the affected code :D

Avatar
arsenic

Community Member, 9 Posts

14 January 2010 at 4:41pm

Edited: 14/01/2010 4:44pm

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

Community Member, 105 Posts

14 January 2010 at 6:59pm

Edited: 14/01/2010 7:01pm

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

Community Member, 9 Posts

15 January 2010 at 5:09am

Edited: 15/01/2010 5:27am

_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

Community Member, 105 Posts

15 January 2010 at 11:41am

Edited: 15/01/2010 11:50am

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

Community Member, 9 Posts

15 January 2010 at 2:38pm

Edited: 15/01/2010 2:42pm

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

Community Member, 105 Posts

15 January 2010 at 2:52pm

Edited: 15/01/2010 2:52pm

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