XF 2.0 xf:foreach not iterating through PHP callback array

Jonah Madsen

New member
I'm having trouble iterating through an array given by a PHP callback.

I've set up an HTML widget above my nodes to display one thread in my forum. There's not much to it but it's not iterating through any metadata I put in the array through the callback

Here is the thread I'm trying to get ahold of:
Screenshot_2.png

PHP Setup:

PHP:
<?php

namespace Madsen;

class News {

    public static function getHtml($content, $params) {

        // I will find a use for $params later

        $finder = \XF::finder('XF:Thread');
        $threads = $finder->limit(3)->where('node_id', 4)->fetchOne();

        // For now I just need one, but three will come to functionality later.

        $post = \XF::finder('XF:Post')->where('post_id', $threads->first_post_id)->fetchOne();

        $threadlib = array(
            $post->user_id,
            $post->message,
            $threads->title,
            $threads->discussion_open,
            $threads->reply_count,
            $threads->first_post_likes
        );

        return $threadlib;
    }
}

HTML Setup:

XML:
<xf:set var="$threadmeta">
    <xf:callback class="\Madsen\News" method="getHtml" params="['testparam']"></xf:callback>
</xf:set>

{$threadmeta}

<xf:foreach loop="$threadmeta" value="$data" >
    <p><b>{$data}</b></p>
</xf:foreach>

It doesn't iterate.
Result:
support1.png
Dumped:
Screenshot_5.png

As a workaround/alternative, I tried to run this setup:

PHP:

PHP:
<?php

namespace Madsen;

class News {

    public static function getHtml($content, $params) {

        // I will find a use for $params later

        $finder = \XF::finder('XF:Thread');
        $threads = $finder->limit(3)->where('node_id', 4)->fetchOne();

        // For now I just need one, but three will come to functionality later.

        $post = \XF::finder('XF:Post')->where('post_id', $threads->first_post_id)->fetchOne();

        $threadlib = self::compressArray(array(
            $post->user_id,
            $post->message,
            $threads->title,
            $threads->discussion_open,
            $threads->reply_count,
            $threads->first_post_likes
        ), false);

        return $threadlib;
    }

    private static function compressArray($array, bool $hasKeys) {

        $strng = '{{[';

        if ($hasKeys === false) {

            $i = 0;

            foreach($array as $element) {
                $strng .= '\'' . $element . '\'';
                if ($i != (count($array) - 1)) {
                    $strng .= ',';
                }
                $i++;
            }
        } else {
            // Functionality will arrive later
        }

        $strng .= "]}}";

        return $strng;

    }
}
[compressArray] is a simple function that parses it in a way I thought XenForo would recognize from straight string

HTML:

XML:
<xf:set var="$threadmeta">
    <xf:callback class="\Madsen\News" method="getHtml" params="['testparam']"></xf:callback>
</xf:set>

<p>This prints just fine</p>
<b>{$threadmeta}</b>

<xf:set var="$threadmeta2" value="{$threadmeta}" />

<p>This also prints just fine, so "value" field accepts variables enclosed in var brackets</p>
<b>{$threadmeta2}</b>


<xf:set var="$names" value="{{ ['Patrick', 'Theresa', 'Kimball', 'Wayne', 'Grace'] }}" />
<p>XenForo provided example for iteration ({$names})</p>
<xf:foreach loop="$names" key="$key" value="$name" i="$i">
    <p><b>Hello there, {$name}. This is name number {$i}. Array key of this element: {$key}</b></p>
</xf:foreach>

<p>My iteration of threadmeta2 ({$threadmeta2})</p>
<xf:foreach loop="{$threadmeta2}" value="$data" >
    <p><b>Unkeyed info {$data}</b></p>
</xf:foreach>

Result:
Screenshot_1.png

Is it a possible XenForo bug that upgrading my XenForo version would fix? Or is there some miniscule syntax problem that's preventing iteration? I'm about lost at solutions
 
Last edited:

Chris D

XenForo developer
Staff member
What you're trying to do just simply isn't within the scope of what template callbacks allow.

They are designed to return the HTML content which is returned when the template is rendered. It is a literal string and it cannot be processed as an array or template code.
 

Jonah Madsen

New member
What you're trying to do just simply isn't within the scope of what template callbacks allow.

They are designed to return the HTML content which is returned when the template is rendered. It is a literal string and it cannot be processed as an array or template code.
Thank you for such an incredibly quick response. Does this mean i'm best just hardcoding the HTML in the PHP?
 
Top