XenForo 2 Development Q&A — Custom Add-ons, Template Modifications, Performance Optimization & Security Hardening

Blacksec

Administrator
Staff member
❓ XENFORO 2 DEVELOPMENT Q&A ❓Custom Add-ons • Template Modifications • Performance • Security • Best Practices

⚡ WELCOME: This thread is for XenForo 2 development questions — custom add-on development, template modifications, performance optimization, and security hardening. Ask your questions and share your solutions.

FREQUENTLY ASKED QUESTIONS
Code:
Option 1 — Route + Controller:
  1. Create a route class extending \XF\Mvc\Router
  2. Create a controller class extending \XF\Pub\Controller
  3. Register in _metadata.json:
     "routes": {
       "public": {
         "myroute": ["Controller","MyCustom"]
       }
     }
  4. Access: /myroute

Option 2 — Node-Based:
  1. Create a new node type (add-on required)
  2. Or use existing "Page" node type
  3. Admin CP → Nodes → Create Page
  4. Enter HTML content, callback PHP class for dynamic content

Option 3 — Template Modification:
  1. Create template modification in ACP → Appearance → Template Modifications
  2. Target: PAGE_CONTAINER or specific templates
  3. Add: <xf:if is="$customCondition">Your content</xf:if>
  4. Controlled: hook system (e.g., <xf:hook name="my_hook" />)
Code:
1. Setup structure:
   src/addons/VendorName/AddonName/
   ├── _metadata.json
   ├── Entity/
   ├── Repository/
   ├── Service/
   ├── Controller/
   ├── Admin/
   ├── Pub/
   ├── View/
   ├── Template/
   └── Setup.php

2. _metadata.json format:
{
  "title": "My Add-on",
  "version_string": "1.0.0",
  "version_id": 100,
  "developer": "MyVendor",
  "require": [],
  "json_hash": ""
}

3. Setup.php:
<?php
namespace MyVendor\MyAddon;
class Setup extends \XF\Addon\AbstractSetup
{
    public function install(array $stepParams = []) {
        // Create tables, add permissions, etc.
        $this->schemaManager()->createTable('xf_my_table', function(\Laminas\Dd\Sql\Ddl\CreateTable $table) {
            $table->addColumn('item_id', 'int')->autoIncrement();
            $table->addColumn('title', 'varchar', 150);
            $table->addPrimaryKey('item_id');
        });
    }
    public function uninstall(array $stepParams = []) {}
    public function upgrade(array $stepParams = []) {}
}

4. Development mode:
   - Set $config['development']['enabled'] = true; in src/config.php
   - ACP → Development → Code Event Listeners / Content Types
   - Regenerate: XF development output → Rebuild add-on JSON
Code:
1. Caching:
   - Enable Redis/Memcached: $config['cache']['enabled'] = true;
   - $config['cache']['provider'] = 'Redis';
   - $config['cache']['config'] = ['server' => '127.0.0.1', 'port' => 6379];
   - Cache templates, entities, route matches

2. MySQL optimization:
   - Query log: identify slow queries
   - Add indexes for frequently queried columns
   - Use EXPLAIN on complex queries
   - Enable MySQL query cache (if not MariaDB with query cache removed)
   - Consider read replicas for large forums

3. PHP optimization:
   - PHP 8.2+ (JIT enabled: opcache.jit=1255)
   - Enable OPcache: opcache.enable=1, opcache.memory_consumption=256
   - Increase memory_limit for media processing
   - Use FastCGI (php-fpm) over mod_php/mod_cgi

4. Template optimization:
   - Minimize template modifications (use hooks efficiently)
   - Combine CSS/JS assets
   - Enable template caching
   - Use sprite sheets for icons

5. CDN:
   - Offload static assets to CDN
   - Use Cloudflare (APO for caching HTML)
   - Serve images via Cloudflare Images or Imgix
   
General: For 50K+ posts, invest in dedicated server (not shared hosting). Vultr HF $48/mo or Hetzner $35/mo handle 200K posts comfortably.
Code:
1. File permissions:
   chmod 755 /var/www/html
   chmod 644 /var/www/html/*.php
   chmod 700 /var/www/html/src/config.php
   chmod 777 /var/www/html/data
   chmod 777 /var/www/html/internal_data

2. .htaccess hardening:
   <FilesMatch "config\.php|.*\.json|.*\.lock">
     Deny from all
   </FilesMatch>
   Options -Indexes
   ServerSignature Off

3. Admin CP security:
   - Change admin path: $config['adminPath'] = 'hidden_admin';
   - Two-factor auth (enforced for staff)
   - IP whitelist for admin access
   - Session timeout: 15 min

4. SQL injection prevention:
   - Always use prepared statements (XF does this)
   - Never use raw SQL with string concatenation
   - Sanitize user input with XF validation ($input->filter())

5. XSS prevention:
   - Use XF's template escaping: {$var} auto-escapes
   - For raw HTML: {{ $var|raw }} (careful!)
   - Content Security Policy header

6. CSRF:
   - All forms include _xfToken
   - Never disable CSRF checks
   - Use POST for state-changing operations

7. Regular updates:
   - Keep XF updated (security patches)
   - Monitor xenforo.com/community for security announcements
   - Subscribe to XF security mailing list

COMMON ISSUES & SOLUTIONS
IssueSymptomSolution
White screen on installPHP 8.2+ incompatibilityCheck PHP error log, enable XF debugging mode
Add-on not showingInvalid _metadata.jsonVerify JSON format, rebuild add-on JSON in dev mode
Template not renderingTemplate modification syntax errorDisable modification, check regex pattern
Slow page loadsMySQL queries unoptimizedEnable query log, add missing indexes
Can't login to ACPSession issues or IP changeClear cookies, check admin IP whitelist, rebuild session
Asset load failureBroken file permissionschmod -R 777 data/ internal_data/, rebuild
Email not sendingMail config missingConfigure SMTP in ACP, test with debug mode
Search not indexingSearch engine needs rebuildACP → Tools → Rebuild Search Index

ASK YOUR QUESTIONS
Code:
Post your XenForo 2 development questions below. Include:
  - XenForo version
  - PHP version
  - What you're trying to achieve
  - What you've tried
  - Error messages (if any)

Community members and experienced devs will help you out.
Check the archives for previously answered questions.

❓ Ask smart. Share solutions. Build the community knowledge base. ❓
 
Top