XF 2.2 New table - how to get variables for the templates?


Active member
Hey guys, I've recently started making my first proper addon for Xenforo. It's basically adding a new route /account/username-settings where people can change the appearance of their username.
My initial approach was just to extend the User entity with some new columns added to xf_user, and this worked perfectly fine. I realized however that I had dozens of columns I want to add, so making a new table would probably be the way to go - I called it xf_ap_username_styles.
When I was extending the User entity, I had no issue getting values from the DB to display in templates because I could use $xf.visitor.color or something, so long as I added the columns to my Listener then Xenforo would have no issue interacting with them.

Since making my own table however, I'm having trouble creating the variables. Here is the output of dump($xf.visitor) and dump($style). Due to the structure of this output, I thought perhaps $style.Username.color would work, but it didn't. $style.color is a no-go as well.

I'd really love any help here. These are some relevant files:


Well-known member
You need call fetchOne() instead fetch() in your controller. In this case, XF ORM returns an single entity or null, not collection.


Active member
That did it alright, thank you so much for the help Kruzya! Can't believe a small detail like that was the issue.


Active member
Alright so it seemed like it was only a matter of time before I run into more trouble.
Outside of Username effects I also want the addon to be able to handle appearance of a users Postbit. The table name for this is xf_ap_postbit_styles. I can get the values of this on the account/postbit-settings page perfectly thanks to your prior help. However, when it actually comes to displaying them in message_macros I'm stuck yet again.

Output of dump($user) in a thread

In that output I can see Postbit & Username entities showing in User->Structure->Relations, but not User->Relations, but none of the columns appear in the Values section.

Perhaps related, when it comes to displaying Username effects in Templater.php I can only succeed if it's reading from placeholder fields I have in xf_user, it doesn't seem to find my custom table.


namespace apathy\UsernameStyles\XF\Template;

class Templater extends XFCP_Templater
    public function fnUsernameLink($templater, &$escape, $user, $rich = true, $attributes = [])
            $parent = parent::fnUsernameLink($templater, $escape, $user, $rich, $attributes);

            $bold = $user->ap_bold;
            $color = $user->ap_color;
            $glow = $user->ap_glow;
            $sparkle = $user->ap_sparkle;

works because it's calling to placeholder fields in xf_user. How could I get it to call bold, color, glow, sparkle in xf_ap_username_styles instead? I tried querying the information I did the same way in the Controller but I was getting errors.
Last edited:


Well-known member
How could I get it to call bold, color, glow, sparkle in xf_ap_username_styles instead?
Then you need to add those bold, glow etc columns to that postbit table and modify that Postbit entity and include those columns to it.

Then you can do this.

BTW you might have to take a look at the numbers of queries it costs. Because it runs an extra query under the hood, so when a user looking at a page that has bunch of usernames, in each username doubles the number of queries.
So.. You might have to keep catchable values in xf_user table at the same time, and update the both fields.


Active member
I managed to figure out the $user->Postbit thing myself after messing around with it a bit more, but I'm super thankful you posted because I did notice that postbit stuff for instance was being called on the board index, where it wouldn't be needed, but I also didn't know what other way to do it. I'll have a look at caching stuff now, thank you very much for the info.

EDIT: It turns out that postbit stuff wasn't being called because I extended User, it was because I was using $structure->defaultWith[] (i guess it only worked like that at first for some reason). So I've removed that and it's now only usernames being called on the index.
Using defaultWith for the Username entity relation does bring down memory size by like 0.03MB so I guess it's good to use it for that?
Last edited: