1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Page php callback. My first Xenforo coding. Help!

Discussion in 'XenForo Development Discussions' started by Stuart Wright, Nov 5, 2013.

  1. Stuart Wright

    Stuart Wright Well-Known Member

    Hello folks,
    so far I've outsourced all our coding to gurus like Chris Deeming but now I want to have a go myself.

    I'm trying to reproduce a page from our vBulletin site which assigns tokens stored in a table to users who visit the page and then creates a link to a retailer website which applies free delivery to their shopping account. Each user is assigned a token and their userid is written into the table.
    userid int(10) UNSIGNED
    token char(64)
    assigned timestamp

    This is the old code from vBulletin which I wrote:
    = array(6275112425);
        if (
    $vbulletin->userinfo['userid'] == "") {   // guest
    $HTML .= "<p align='center'>In order to qualify for the SCAN & AVForums loyalty programme you need to login to your AVForums account.<br>Please login (and register first if you need to) <a href='http://www.avforums.com/forums/clogin.php' target='_blank'>here</a>.</p>";
        } elseif (!
    in_array($vbulletin->userinfo['usergroupid'],$allowed_usergroups)) {
    $HTML .= "<p align='center'>In order to qualify for the SCAN & AVForums loyalty programme you need to be a member of AVForums and logged in to your activated AVForums account.<br>Please login (and register first if you need to) <a href='http://www.avforums.com' target='_blank'>here</a>.</p>";
        } else {
    $HTML .= "<h3 align='center'>Welcome " $vbulletin->userinfo['username'] . ".</p>";

    $sql "SELECT token FROM scan_tokens WHERE userid = " $vbulletin->userinfo['userid'] . " LIMIT 1";
    $result $db->query_read($sql);
            if (!
    $result) {
    $HTML .= "<p align='center'>There was a problem finding your token.  Please notify AVForums admin.";
            if (
    mysql_num_rows($result) == 1) {
                if (
    strlen($token) >= 60) {
    $HTML .= "<P align='center'>Good news - you qualify for the SCAN & AVForums loyalty programme!<br>Click <a href='https://secure.scan.co.uk/aspnet/myaccount/avfreecarriage.aspx?uid=$token' target='_blank'>here</a> to visit the SCAN website and log in/register to qualify for free delivery on all orders of &pound;50 or over (excluding VAT).</p>";               
            } else {  
    // no token found
    $sql "SELECT token FROM scan_tokens WHERE userid = 0 LIMIT 1 FOR UPDATE";  //get token and lock record for update
    $result $db->query_read($sql);
                if (!
    $result) {
    $HTML .= "<p align='center'>There was a problem assigning the Free Delivery token to your account.  Please notify AVForums admin.";
                if (
    mysql_num_rows($result) == 1) {
                    if (
    strlen($token) >= 60) {
    $sql "UPDATE scan_tokens SET userid = " $vbulletin->userinfo['userid'] . " WHERE token = '$token'";
    $db->query($sql);   // 
    $HTML .= "<P align='center'>Good news - you qualify for the SCAN & AVForums loyalty programme!<br>Click <a href='https://secure.scan.co.uk/aspnet/myaccount/avfreecarriage.aspx?uid=$token' target='_blank'>here</a> to visit the SCAN website and log in/register to qualify for free delivery on all orders over &pound;50 (excluding VAT).</p>";               
    I'm imaginig that this is dead easy to to with a php callback on a page?
    I have looked at a few other examples of Xenforo coding and as you can probably see from my coding above, what I'm used to is very different. Xenforo coding is a bit foreign to me. I have never used classes, for example.
    Where do I start please?
  2. Jeremy

    Jeremy XenForo Moderator Staff Member

    So basically you want something such as:


    Where if user has no token, it creates one and then displays it?
  3. Stuart Wright

    Stuart Wright Well-Known Member

    Well I'm happy to have it as a page as it's not special enough to give a route like that.
    I started work on the page already:
    I already got the hang of conditionals in the page.

    But yes, it assigns new tokens to users if they don't already have one. Or gets their token if they do. And then displays a link to the site which incorporates their token.
    The scan_tokens table is populated with hundreds of tokens from the retailer. The userid in the unassigned records is zero. When a token is assigned to a user, that token record is updated with that user's userid.

    When we run out of tokens the retailer sends us another few thousand to put in the table.
  4. Stuart Wright

    Stuart Wright Well-Known Member

    Is there perhaps a similar example someone can point me to that I can unpick?
  5. arms

    arms Active Member


    There is Waindigo's key generator to read through as a guide. http://xenforo.com/community/resources/random-key-generator-by-waindigo.2145/

    Allows member to generate and store a random key, so not far off retrieving a key from a set list and storing it.
  6. Stuart Wright

    Stuart Wright Well-Known Member

    Thanks arms. I'm more interested in finding an example of a php callback in a normal page.
  7. Marcus

    Marcus Well-Known Member

    My suggestion is to make this addon on your own, then hire @Chris Deeming to make the addon for you. I promise you it will look completely different and you will learn a lot from it.

    I am not sure where you are on a xenforo programmers level. You could start writing a simple "Hello World" addon that just returns "Hello World". You will need to do that in your addon as your addon also returns different text depending on what happens in your addon.

    Then you can add to that page a simple data that you fetch from database, like the users username, or the users latest five posts.

    Here is a short tutorial for the use of xen:callback from @AndyB :


    Unfortunately, the resouce was removed. There was a great explanation to the resource discussion on how to return your data embedded within xenforos template system.
    Last edited: Nov 6, 2013
  8. Lawrence

    Lawrence Well-Known Member

    Here is an example of a php call back. This is obviously not my real call back but I wanted a quick example that contains calling a model and send the data to a page template.

    class IcewindDaleRP_IcewindDale_PageCallback_TrainingHall
        public static function 
    trainingHall(XenForo_ControllerPublic_Abstract $controllerXenForo_ControllerResponse_Abstract $response)
    $charData = array();
    $visitor XenForo_Visitor::getInstance()->toArray();
            if (
    $userCharModel XenForo_Model::create('IcewindDaleRP_IcewindDale_Model_UserCharacter');
    $charData $userCharModel->getAllCharDataById($visitor['user_id']);

    $customData = new XenForo_Phrase('hello_world');

    $response->params['custom_data'] = $customData;
    $response->params['char_data'] = $charData;
    $response->templateName 'iwd_training_hall';
  9. Marcus

    Marcus Well-Known Member

    @Lawrence Do you modify the current $response from the main controller here or do you return a template? I always return a template which is inserted at the point of <xen:callback />. Your use of the callback is interesting.
  10. Liam W

    Liam W Well-Known Member

    I believe that the example in the post by @Lawrence above is for a page PHP callback :)
  11. MattW

    MattW Well-Known Member

    Here is one of mine

    class Garage_ControllerPublic_Garage
            public static function 
    getPowerBoard(XenForo_ControllerPublic_Abstract $controllerXenForo_ControllerResponse_Abstract &$response)
    $db XenForo_Application::getDb();

    $power $db->fetchAll("
                    FROM xf_nflj_showcase_custom_field_value
                    LEFT JOIN xf_nflj_showcase_item ON
                            (xf_nflj_showcase_custom_field_value.item_id = xf_nflj_showcase_item.item_id)
                    LEFT JOIN xf_user ON
                            (xf_nflj_showcase_item.user_id = xf_user.user_id)
                    WHERE xf_nflj_showcase_custom_field_value.field_id =  'bhp'
                    AND xf_nflj_showcase_custom_field_value.field_value !=  ''
                    ORDER BY xf_nflj_showcase_custom_field_value.field_value DESC

    $response->params['power'] = $power;
    Used here: http://z22se.co.uk/pages/powerboard/
  12. Marcus

    Marcus Well-Known Member

    There are different ways of using the callback, here I return a template:

      public static function myCallback($content$params, \XenForo_Template_Abstract $template)
    $templateParams = array();
  13. Liam W

    Liam W Well-Known Member

    Not the page callback. There isn't a template object passed into the page node callback.
  14. Marcus

    Marcus Well-Known Member

    I see. For others, here is the description of the page callback in ACP>Applications>Create New Page:
  15. Stuart Wright

    Stuart Wright Well-Known Member

    Thanks Matt. Can you tell me what you put in the PHP Callback text boxes for Class and Method please?
    And then what did you do template wise? I'm going to copy elements of your code, but I'm not sure what to do with the output.
  16. Jeremy

    Jeremy XenForo Moderator Staff Member

    Class is the class name (so in Matt's case Garage_ControllerPublic_Garage) and the method is the function name (so in Matt's case getPowerBoard).
    MattW likes this.
  17. MattW

    MattW Well-Known Member

    As @Jeremy said for the Class and Method.

    This is the template I'm using:
    <style type="text/css">
    .outercontainer {
    border: 1px solid #ddd;
    border-radius: 4px;
    padding: 10px;
    margin: 0 auto;
    background-color: #f8f8f8 !important;
    <script type='text/javascript' src='https://www.google.com/jsapi'></script>
        <script type='text/javascript'>
          google.load('visualization', '1', {packages:['table']});
          function drawTable() {
            var data = new google.visualization.DataTable();
            data.addColumn('string', 'Member');
            data.addColumn('string', 'Vehicle');
            data.addColumn('string', 'Power');
              <xen:foreach loop="$power" value="$power">
              ['<xen:username user="$power" />', '<a href="{xen:link showcase, $power}">{xen:jsescape {xen:raw $power.item_name}, single}</a>', '{$power.field_value} {$power.field_id}'],
            var table = new google.visualization.Table(document.getElementById('table_div'));
            table.draw(data, {showRowNumber: true, allowHtml: true});
    <div class="outercontainer">
    <div class="baseHtml">
    <div id='table_div'></div>
  18. Stuart Wright

    Stuart Wright Well-Known Member

    Thanks. I'll read through some Xenforo php scripts to try and figure out how to deal with query results.
  19. Daniel Hood

    Daniel Hood Well-Known Member

    $db = XenForo_Application::get('db');
    $results = $db->fetchAllKeyed($sql, 'keyfield');


    If you only want one result, just do $db->fetchRow($sql);
    SneakyDave likes this.
  20. xf_phantom

    xf_phantom Well-Known Member

    fetchAllKeyed is a method in XenForo_Model! ;)

Share This Page