PHP in templates?

Hi,

I'm able to get my php to display in pages by following the steps Boothby described here but can't figure out how to achieve a similar thing for templates.

My knowledge of PHP is practically nothing, but from what I can gather the "callback" you create for pages basically tells the page to look for a specific php file, so you can use it's variables. With a template, there doesn't seem to be call back functionality so I assume you somehow need to pre-register your variable(s).

Is anyone able to give a really basic guide on how to use custom variables in templates? Hopefully, I'll then be able to follow the steps and modify it to suit my needs.

Thanks
 
I think the way you want to do it would pretty much break the point of using MVC. It would just be 'wrong'.

The callback is there to do any changes you want made before the application gets to the view (your template). So you should create a callback method and use it to do all your PHP. Then store in PHP you want to use in the template in the params when using responseView() I think it is.

Watch the videos here to see it in action.
 
Sorry, I think I've worded what I want to do poorly due to my lack of understanding.

I don't want to display raw php in my template, I just want to use something like; {xen:raw $myVariable}, which I've defined in my php file. The problem is that without the php callback feature you have for pages, there doesn't seem to be a way to tell templates where the particular variable is defined. However, there are loads of (default) variables used in templates so the has to be some sort of method of pre-registering variables?

From doing a search through the files I've noticed things like;

XenForo/ViewPublic/ProfilePost/Comment.php said:
<?php

class XenForo_ViewPublic_ProfilePost_Comments extends XenForo_ViewPublic_Base
{
public function renderJson()
{
$comments = array();

if ($this->_params['profilePost']['first_comment_date'] < $this->_params['firstCommentShown']['comment_date'])
{
$comments[] = $this->createTemplateObject(
'profile_post_comments_before', $this->_params
);
}

foreach ($this->_params['comments'] AS $comment)
{
$comments[] = $this->createTemplateObject(
'profile_post_comment', array('comment' => $comment) + $this->_params
);
}

return array(
'comments' => $comments
);
}
}

I don't really understand what this means, but is it defining the variable $comments, and then creating a new template, profile_post_comment in which the variable $comments can be used? If so, can this method be used for custom variables or does anything additional need to be done?
 
To define a variable for use on the index page I did this: (probably not the best way of doing it)

library/whatever/EventListener/Listener.php
Code:
<?php

class Dark_Sidebar_EventListener_Listener
{
    public static function listen($class, array &$extend)
    {
        if ($class == 'XenForo_ControllerPublic_Index')
        {
            $extend[] = 'Dark_Sidebar_ControllerPublic_Index';
        }
    }
}


library/whatever/ControllerPublic/Index.php
Code:
<?php

class Dark_Sidebar_ControllerPublic_Index extends XFCP_Dark_Sidebar_ControllerPublic_Index
{

    public function actionIndex()
    {
        $response = parent::actionIndex();

        if ($response instanceof XenForo_ControllerResponse_View)
        {
            $servers = "my variable";

            $response->params += array(
                'servers' => $servers
            );
        }
        return $response;
    }
}

You can then use {xen:raw $servers} anywhere on the forum index page. :)
 
Thanks for your reply but unfortunately I'm still not there :(.

Perhaps if I go through what you did line by line it'll identify where the gaps or errors in my knowledge are and then hopefully highlight where I'm going wrong.

For the first file, library/whatever/EventListener/Listener.php;
Code:
class Dark_Sidebar_EventListener_Listener

This just gives your action a name so that you can refer to it and it's defined by the location and name of your php file, so in this example it'd be library/Dark/Sidebar/EventListener/Listener.php.

Code:
public static function listen($class, array &$extend)

This is saying, "listen" for when a class (effectively the php file) is called, and when it is, "extend" or bolt onto it my array.

Code:
if ($class == 'XenForo_ControllerPublic_Index')

This is the class we're listening out for....

Code:
$extend[] = 'Dark_Sidebar_ControllerPublic_Index';

...and this is the class (library/Dark/Sidebar/ControllerPublic/Index.php) we're also going to include whenever XenForo_ControllerPublic_Index is called.

----------------

For the second file, library/whatever/ControllerPublic/Listener.php (I assume Listener is a typo and it should actually be Index.php, as given by the class name below?)

Code:
class Dark_Sidebar_ControllerPublic_Index extends XFCP_Dark_Sidebar_ControllerPublic_Index

I don't understand the latter part of this, where does XFCP_Dark_Sidebar_ControllerPublic_Index come from? Why it isn't simply XenForo_ControllerPublic_Index (as this is what we said we were looking out for in the previous "listener")?.

Code:
   public function actionIndex()

$response = parent::actionIndex();

Don't understand this bit at all.

Code:
if ($response instanceof XenForo_ControllerResponse_View)

I assume library/XenForo/ControllerResponse/View.php is used when someone is viewing the forum list, a thread, someone's user profile etc. (basically anywhere a user can view on your site), and this is why this is here?

Code:
$servers = "my variable";

Here we're defining our variable, the physical output on the template should be my variable.

Code:
$response->params += array(

Is this saying if the "listen" parameters (or conditions) are true, then I want to add on (ie. my response is) the following defined arrays...

Code:
'servers' => $servers

...I don't really know why this step is necessary, just that it is. Each variable that you want to use has to be defined in this way, it's name in single quotations which you say is equivalent to it's name with the $ (and is is this $name you use in your templates).

Code:
return $response;

This is just saying execute (return) what I have defined as my response, if the listen conditions are met.

---------------

I'm also not entirely sure what you mean by forum index, is this the fourm_list template (and if it is, why does it not appear anywhere in the above code)?

Thanks again for your help and hopefully it's just something simple that I'm not quite grasping to be able to get this to work for me.
 
For the second file, library/whatever/ControllerPublic/Listener.php (I assume Listener is a typo and it should actually be Index.php, as given by the class name below?)

One vital part is missing there. :)

You have to add a new code event listener (in the admin center, when you forums are in debug mode).
This listener listens to load_class_controller.
There are two input fields, separated with '::'

The first one defines the class, the second one the method inside that class.
In the provided example that is 'Dark_Sidebar_EventListener_Listener' and 'listen'.



Code:
class Dark_Sidebar_ControllerPublic_Index extends XFCP_Dark_Sidebar_ControllerPublic_Index

I don't understand the latter part of this, where does XFCP_Dark_Sidebar_ControllerPublic_Index come from? Why it isn't simply XenForo_ControllerPublic_Index (as this is what we said we were looking out for in the previous "listener")?.
This file has to be named 'Index.php' and you must put it into /library/Dark/Sidebar/ControllerPublic
The 'XFCP_' thing has to be in there because of the way XenForo works.


Code:
   public function actionIndex()

$response = parent::actionIndex();

Don't understand this bit at all.

You are overwriting/replacing the function actionIndex() in the default controller, this function contains vital things and the would be missing if you don't do this.
This tells XenForo to execute the function actionIndex() from the original class (XenForo_ControllerPublic_Index).
The function has a return value that you need to extend, therefore it is stored in a variable.


Code:
if ($response instanceof XenForo_ControllerResponse_View)

I assume library/XenForo/ControllerResponse/View.php is used when someone is viewing the forum list, a thread, someone's user profile etc. (basically anywhere a user can view on your site), and this is why this is here?

XenForo_ControllerResponse_View is responsible for the rendering of the page.
$response is filled with the return value of the default actionIndex() method and this value must be an object of 'XenForo_ControllerResponse_View'.
instanceof: http://php.net/manual/en/language.operators.type.php

Code:
$servers = "my variable";

Here we're defining our variable, the physical output on the template should be my variable.

Code:
$response->params += array(

Is this saying if the "listen" parameters (or conditions) are true, then I want to add on (ie. my response is) the following defined arrays...

Code:
'servers' => $servers

...I don't really know why this step is necessary, just that it is. Each variable that you want to use has to be defined in this way, it's name in single quotations which you say is equivalent to it's name with the $ (and is is this $name you use in your templates).

Code:
return $response;

This is just saying execute (return) what I have defined as my response, if the listen conditions are met.

$response->params is an array, it contains all parameters that you would like to return to the view (= the template). You must extend that array to pass your own paramater to the view
In this example 'servers' is the key and '$servers' is the value, you can use {$servers} in your template and you will get 'my variable'.

The return makes sure that the view is rendered properly. It takes the return value of the original method (see above) and you extension of the parameters.


I hope this helps. I suggest you pick an available add-on and take a closer look at it. :)
 
Ah, school boy error on my part.

I'd looked at code event listeners before but then totally forgot about them and that's why I couldn't understand how xF knew where to look for my php file.

As a side note, my php is pulling HTML from an external source and using {$variable} in my template resulted in unprocessed/raw (if that's the right term) HTML, where as {xen:raw $variable} processed it so that the HTML rendered normally.

Anyway, I've managed to get it working now, thanks a lot for your help and explanations :).

----------

EDIT:

I suspect it isn't possible, but if you never ask you never know. Is there anyway to allow an addon option to be used within in your PHP file itself?

For example, a line in my php is;

$source = file_get_contents('http://website.com/mylink');

is there anyway to make it along the lines of;

$source = file_get_contents('http://website.com/{$xenOptions.Addon_option}');

?
 
Is there a reason you are not using XenForo for 'your' PHP script?

If you mean why $source = file_get_contents is external, it's because I'm pulling data from an external website (steam) to give me something like;

example.webp

I can currently get it to work fine by "hard coding" the source, but if I'm able to get it to work via an Addon Option then I was planning on releasing it on here so others could use it without having to go into the PHP file to edit their desired source.


EDIT:

I've managed to get it working with;

$custom = "customURL";
$source = file_get_contents("http://website.com/$custom");

I then tried changing "customURL" to "\{\$xenOptions.Addon_option\}" (my understanding is that the backslashes "escape" the character that follows them, which is needed for any characters that would otherwise be processed by PHP), however my output then appears blank.

I'm guessing this is because it doesn't process {$xenOptions.Addon_option} to it's inputted value in the Admin CP, effectively making the source http://website.com/{$xenOptions.Addon_option}? Is there a way I can first tell it to look at an Admin CP option and then process further?
 
Where did you put this in:
PHP:
$source = file_get_contents('http://website.com/mylink');
?
The reason I am asking is that I don't know if it's even possible to use the XenForo configuration when you are not using XenForo as a framework.

Inside a controller you can do something like this:
PHP:
$myoption = XenForo_Application::get('options')->myaddon_option;
 
Brilliant! That works perfectly, thanks a lot :D.

This is what I'm using;

PHP:
<?php

class GP_Steam_ControllerPublic_Index extends XFCP_GP_Steam_ControllerPublic_Index
{

    public function actionIndex()
    {
        $response = parent::actionIndex();

        if ($response instanceof XenForo_ControllerResponse_View)
        {
            $gp_steam_start = "<!-- stats section -->";
            $gp_steam_end = "<!-- /stats section -->";
 
            $gp_steam_group_name = XenForo_Application::get('options')->GP_Steam_Group_Name;
            $gp_steam_source = file_get_contents("http://steamcommunity.com/groups/$gp_steam_group_name");

            $gp_steam_start_pos = strpos($gp_steam_source, $gp_steam_start);
            $gp_steam_end_pos = strpos($gp_steam_source, $gp_steam_end) - $gp_steam_start_pos;

            $gp_steam = substr($gp_steam_source, $gp_steam_start_pos, $gp_steam_end_pos);

            $response->params += array(
                'gp_steam' => $gp_steam
            );
        }
        return $response;
    }
}

Thanks for all your help :).
 
No problem. :)

Depending on what type of data the 'file_get_contents' gets, you might want to use urlencode() :)
 
Back
Top Bottom