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.

Template Questions /

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

[SOLVED] Method only called once


Go to End


3 Posts   1597 Views

Avatar
Eurisko

Community Member, 27 Posts

22 October 2015 at 2:54am

Edited: 22/10/2015 4:16am

Hi

I have a method in my page class which we can call test. If it returns a value, it seems to be only called once, regardless of how many $test are in the .ss file.

e.g.

If I have a page with 5 lots of $test <br> in:

public function test()
{
    print "test printing";
    return "test";
}

Will return 1 Test printing and 5 tests

public function test()
{
    print "Test printing";
}

Will return 5 "Test printing"

If the function returns a value, why does it only get called once? Is there any way I can prevent this? I would like the function to return a different value with each call as it cycles over a list.

Thanks.

Edit: The problem appears to be this "feature" https://docs.silverstripe.org/en/3.2/developer_guides/templates/caching/

Avatar
Devlin

Community Member, 344 Posts

22 October 2015 at 4:28am

Yep. This is caching. To avoid this, you could add parameters to invalidate the caching.

public function test($templateCacheKey = null) {
	return rand(1, 10);
}

$test(1)
$test(2)
$test(3)

Avatar
Eurisko

Community Member, 27 Posts

22 October 2015 at 5:14am

Edited: 22/10/2015 9:24pm

Thanks for your reply Devlin. I literally just solved it as you posted :)

Your solution wouldn't work in my case as I don't want to have to remember what the last number I used was. I'm using it to rotate between static content servers.

It would appear that if you return an object it doesn't get cached. So I just returned the instance of my singleton class and then added the function XML_val (which is required of you want to use the dot notation in the .ss file) and Robert's your mothers brother.

For those out there having a similar problem, my code is below.

.ss file

<img src="$staticSites().nextServer()/themes/default/img1.png">
<img src="$staticSites().nextServer()/themes/default/img2.png">
<img src="$staticSites().nextServer()/themes/default/img3.png">

My static server class

<?php
    final class StaticServers {
        private $servers = array();
        private static $inst = null;
        private $pos = 0;

        public static function instance()
        {
            if ( self::$inst === null ) self::$inst = new StaticServers();
            return self::$inst;
        }

        public function nextServer()
        {
            return $this->servers[ $this->nextPos() ];
        }

        public function XML_val( $field, $arguments = null, $cache = false )
        {
            switch( $field )
            {
                case "nextServer":
                    return $this->nextServer();
                    break;
            }

        }

        private function nextPos()
        {
            $currentPos = $this->pos;
            $this->pos = $this->pos < sizeof( $this->servers ) - 1 ? $this->pos + 1 : 0;
            return $currentPos;
        }

        private function __construct()
        {
            // TODO: Pull these from the database
            $this->servers = array(
                'static01.mySite.co.uk',
                'static02.mySite.co.uk',
                'static03.mySite.co.uk',
                'static04.mySite.co.uk',
                'static05.mySite.co.uk'
            );
        }
    }

And in my Page_Controller class

public function staticSites()
{
    $inst = StaticServers::instance();
    return $inst;
}

Edit: I then added an override for the content so I could put ##static## in the html through the CMS and it would be replaced with the static servers.

public function Content()
{
    return preg_replace_callback(
        '/##STATIC##/siU',
        'self::nextServer',
        $this->Content
    );
}

public function nextServer($matches)
{
    return StaticServers::instance()->nextServer();
}