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?
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.
- Page 11(current)
- 2
- Next 10 entries
Might be helpful if you post the affected code :D
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 %>
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
_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?
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"> </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"> </td>
<td colspan="2" align="right" class="noborder">Sub Total</td>
<td align="right" nowrap="nowrap" class="borderleft">$SubTotal</td>
<td align="right"> </td>
</tr>
<tr>
<td align="left" valign="bottom" class="noborder"> </td>
<td colspan="2" align="right" class="noborder">GST</td>
<td align="right" class="borderleft">$GST</td>
<td align="right"> </td>
</tr>
<% end_if %>
<tr>
<td align="left" valign="bottom" class="noborder"> </td>
<td colspan="2" align="right" class="noborder"><strong>Total</strong></td>
<td align="right" class="borderleft"><strong>$$GrandTotal</strong></td>
<td align="right"> </td>
</tr>
<% end_if %>
</table>
This seems to work well enough is probally a more pure SS way though hope this helps.
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 %>
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()
- Page 11(current)
- 2
- Next 10 entries