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.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

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

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

Method Calls from Templates Fail


Go to End


11 Posts   4305 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, 5523 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