Xen:callback tag

AndyB

Well-known member
In Xenforo 1.2 a new tag called <xen:callback> was introduced. This allows calling a php file directly from a template.

Here's an example where banner.php is called.

1) First create an index.php file and put it in the /library/Example/Banner folder
PHP:
<?php

class Example_Banner_index 
{
	public static function getHtml() 
	{
		include '/home/path_to_file/www/banner.php';
		return $output;
	}
}

?>
2) Create a index.php file
PHP:
<?php
$output = 'Hello World';
?>
3) Add this to the ad_above_top_breadcrumb template
Code:
<xen:callback class="Example_Banner_index" method="getHtml"></xen:callback>
 
Last edited by a moderator:

AndyB

Well-known member
This improved tutorial will show how to use the xen:callback so you can easily add PHP to your templates. The PHP code calls a simple query to get the username from the userId.

1) Create two new folders in the library folder like this:

library/Andy/Example

2) Create a file in this new directory called index.php

library/Andy/Example/index.php

3) Copy this to the contents of your index.php file

PHP:
<?php

class Andy_Example_index
{
    public static function getHtml()
    {
        // get database
        $db = XenForo_Application::get('db');
  
        // assign userId
        $userId = '1';
  
        // get username from user_id
        $userName = $db->fetchOne("
        SELECT username
        FROM xf_user
        WHERE user_id = ?
        ", $userId);
  
        // echo result
        echo $userName;
    }
}

?>
4) Add this code to the ad_above_top_breadcrumb template

Code:
<xen:callback class="Andy_Example_index" method="getHtml"></xen:callback>
In this example you should see the user name displayed in the area just below the navigation bar. You can put the template code into any template you like.
 
Last edited:

TBDragon

Active member
wow its something interesting

is it possible to pass a parameter to the method i use ?

for example myMethod($id) ;

and thanks
 

Fuhrmann

Well-known member
wow its something interesting

is it possible to pass a parameter to the method i use ?

for example myMethod($id) ;

and thanks

Yes, you can, just pass the parameter using the "params":

Code:
<xen:callback class="Example_Banner_Index" method="printSomethingBold" params="Hello World!"></xen:callback>
Then in the code, you can get the parameter (there is another ways):

Code:
<?php

class Example_Banner_Index
{
    public static function printSomethingBold()
    {
        $phrase = func_get_arg(1);
        return '<b>' . $phrase . '</b>';
    }
}
Also, you can pass an array using this:

Code:
params="{xen:array 'thread={$thread}'}"
 
Last edited:

TBDragon

Active member
Yes, you can, just pass the parameter using the "param":

Code:
<xen:callback class="Example_Banner_Index" method="printSomethingBold" params="Hello World!"></xen:callback>
Then in the code, you can get the parameter (there is another ways):

Code:
<?php

class Example_Banner_Index
{
    public static function printSomethingBold()
    {
        $phrase = func_get_arg(1);
        return '<b>' . $phrase . '</b>';
    }
}
Also, you can pass an array using this:

Code:
params="{xen:array 'thread={$thread}'}"
wow thats greats now i can do functions and call them in easy way ^_^ great

thanks again
 

wmnitin

Member
Instead of adding this in template, i am tring to use it in widget framework, I put exact callback class and method but it is loading everything above header :( help
 

wmnitin

Member
Instead of adding this in template, i am tring to use it in widget framework, I put exact callback class and method but it is loading everything above header :( help
Sorted out :) First we have to create template then use template name from widget framework instead of php callback.
 

devRSG

Member
Has anything happened to make this method no longer viable?

I'm receiving "Could not execute callback Example_Banner_index::getHtml() - Not callable." when I attempt using this code.

I've copied the example completely and I have removing the include while setting the $output to "Hello World."
 

AndyB

Well-known member
Has anything happened to make this method no longer viable?

I'm receiving "Could not execute callback Example_Banner_index::getHtml() - Not callable." when I attempt using this code.

I've copied the example completely and I have removing the include while setting the $output to "Hello World."
I just followed the instructions in post #2 and it worked fine.
 

devRSG

Member
Good to know it is still possible, though I have no idea why mine can't seem to find the callback.

Thanks for the reply, appreciate it.

EDIT: Found my pathing issue, thanks again
 

loplo

Active member
Tried with the example and it works like charm.

When trying to add my own code, the forum gets blank :(

The file is located in /library/flyra/metar/ and it is called lrop.php

PHP:
<?php

class flyra_metar_lrop
{
    
$location = "LROP";

get_metar($location);

function get_metar($location) {
$fileName = "http://weather.noaa.gov/pub/data/observations/metar/stations/$location.TXT";
    $metar = '';
    $fileData = @file($fileName) or die('METAR not available');
    if ($fileData != false) {
        list($i, $date) = each($fileData);

        $utc = strtotime(trim($date));
        $time = date("D, F jS Y g:i A",$utc);

        while (list($i, $line) = each($fileData)) {
            $metar .= ' ' . trim($line);
            }
        $metar = trim(str_replace('  ', ' ', $metar));
        }
    echo "$metar";
    }
}

?>
Callback is this:
Code:
<xen:callback class="flyra_metar_lrop" method="getHtml"></xen:callback>
Changing the file as the above, my forum goes blank.

The actual php file looks like this:
PHP:
<?php
$location = "LROP";

get_metar($location);

function get_metar($location) {
$fileName = "http://weather.noaa.gov/pub/data/observations/metar/stations/$location.TXT";
    $metar = '';
    $fileData = @file($fileName) or die('METAR not available');
    if ($fileData != false) {
        list($i, $date) = each($fileData);

        $utc = strtotime(trim($date));
        $time = date("D, F jS Y g:i A",$utc);

        while (list($i, $line) = each($fileData)) {
            $metar .= ' ' . trim($line);
            }
        $metar = trim(str_replace('  ', ' ', $metar));
        }
    echo "$metar";
    }
?>
Any advice is highly appreciated.

PS
coding is not my strength, please bear with me.
 

loplo

Active member
In admin I get the following error
Error info:
Code:
ErrorException: Fatal Error: Call to undefined function get_metar() - library/flyra/metar/lrop.php:11
Stack type:
Code:
#0 [internal function]: XenForo_Application::handleFatalError()
#1 {main}
Request state:
Code:
array(3) {
["url"] => string(24) "http://forum.fly-ra.com/"
["_GET"] => array(0) {
}
["_POST"] => array(0) {
}
}
 

Myke623

Active member
The method you specified in your callback (getHtml) does not match the name of your function (get_metar).

Also, and more importantly, you shouldn't call get_metar from within the class definition itself. Your get_metar function is getting called in your xen:callback (that's the point of the tag!)

Even if coding isn't your strength, you should try to structure and style your code based on the example you're following :) Consider:

/library/Flyra/Metar/Lrop.php:
Code:
<?php

class Flyra_Metar_Lrop
{
    public static function getMetar()
    {
        // Your function code goes here
        // ...
      
        // And you should return something
        return $metar;
    }
}
Then your callback tag becomes:
Code:
<xen:callback class="Flyra_Metar_Lrop" method="getMetar"></xen:callback>
Follow the example(s) in Furhmann's reply if you want to pass arguments to your function (e.g. location of 'LROP').
 

Sap1ent

Member
Could anyone provide me a method of pulling the following PHP into a xenforo template? (it's for an ad management system that rotates adsense code and static banners.)

PHP:
<?php /* Group_Ad_member_view_above_messages */ @readfile('http://www.mydomain.com/mysa2/api/index.php?in&g&i=2&c=1&at=p&r='.$_SERVER['REMOTE_ADDR'].'&h='.urlencode($_SERVER['HTTP_HOST']).'&rf='.urlencode($_SERVER['HTTP_REFERER']).'&ua='.urlencode($_SERVER['HTTP_USER_AGENT'])); ?>
Thanks enormously in advance! :)
 

robart

Member
Yes, you can, just pass the parameter using the "params":

Code:
<xen:callback class="Example_Banner_Index" method="printSomethingBold" params="Hello World!"></xen:callback>
Then in the code, you can get the parameter (there is another ways):

Code:
<?php

class Example_Banner_Index
{
    public static function printSomethingBold()
    {
        $phrase = func_get_arg(1);
        return '<b>' . $phrase . '</b>';
    }
}
Also, you can pass an array using this:

Code:
params="{xen:array 'thread={$thread}'}"

Do you know if it's possible to pass in multiple parameters using {xen:array} ?

I am trying variations of:

params="{xen:array 'thread={$threadId}', 'node={nodeId}'}"

but nothing seems to be working for me.
 

Liam W

Well-known member
Do you know if it's possible to pass in multiple parameters using {xen:array} ?

I am trying variations of:

params="{xen:array 'thread={$threadId}', 'node={nodeId}'}"

but nothing seems to be working for me.
That should work, although don't forget the $ for the node id.

Just of FYI, you can use a self closing tag as well:

HTML:
<xen:callback class="LiamW_Other_Template" method="renderFun" params="{xen:array 'key=value'}" />
The method has to begin with one the following:

Code:
get|is|has|render|view|return|print|show|display
The full PHP signature is:

PHP:
public static function renderFun($contents, array $params, XenForo_Template_Abstract $template) {}
Liam
 
Top