End-to-End Flow

  1. Action Registration

    In PHP, call:

    register_ajax('action', 'my_handler', [...]);
    
  2. Expose Nonce to Frontend

    In head.php:

    <script>
      window.App = window.App || {};
      window.App.nonces = <?= json_encode($g['user_nonces']) ?>;
    </script>
    

    Each registered action becomes available in window.App.nonces.

  3. Frontend Sends AJAX

    Using ajaxJSON or ajax(...), send:

  4. Router /ajax.php


How to Create a New AJAX Action

1. Backend (PHP)

In a functions file (e.g., /functions/demo.php):

<?php if (!defined('APP_INIT')) { http_response_code(403); exit('Forbidden'); }

function demo_echo_ajax() {
  global $g;
  $in = get_input(); // gets JSON body or $_POST
  $name = trim($in['name'] ?? '');
  if ($name === '') {
    return ['ok'=>false,'error'=>'missing_name','code'=>400];
  }
  return ['ok'=>true,'data'=>['greeting'=>"Hello, $name"]];
}

register_ajax(
  'demo_echo',
  'demo_echo_ajax',
  ['auth'=>'login','csrf'=>true,'methods'=>['POST']]
);

⚠️ You only need to register the action. The nonce is auto-generated and added to window.App.nonces.demo_echo.


2. Frontend (JS)

<form id="demoForm">
  <input name="name" placeholder="Your name">
  <button>Send</button>
</form>

<pre class="result" style="display:none"></pre>
document.querySelector('#demoForm')?.addEventListener('submit', async e => {
  e.preventDefault();
  const name = e.currentTarget.querySelector('[name="name"]').value.trim();

  const res = await ajaxJSON(
    'ajax.php?action=demo_echo',
    { name },
    { action: 'demo_echo', method: 'POST' }
  );

  if (res.ok) {
    document.querySelector('.result').style.display = 'block';
    document.querySelector('.result').textContent = JSON.stringify(res.data, null, 2);
  } else {
    alert("Error: " + (res.error || "unknown"));
  }
});

Standard Responses