Lightpack Utility Functions

Lightpack provides few handy utility functions to simplify common usage scenarios in your application.

csrf_input()

What it does: Outputs a hidden HTML input containing the current CSRF token (named _token).

When to use:

Example:

<form method="POST">
  <?= csrf_input() ?>
  <!-- other fields -->
</form>

csrf_token()

What it does: Returns the current CSRF token as a string.

When to use:

Example:

$token = csrf_token();
// Use $token in an AJAX request header

spoof_input()

spoof_input(string $method)

What it does: Outputs a hidden input to spoof HTTP methods (like PUT, PATCH, DELETE) in HTML forms.

When to use:

Example:

<form method="POST" action="/resource/123">
  <?= csrf_input() ?>
  <?= spoof_input('DELETE') ?>
  <button type="submit">Delete</button>
</form>

hidden_input()

hidden_input(string $name, string $value = '')

What it does: Outputs a hidden HTML input field with automatic XSS protection. Both the name and value are automatically escaped using htmlspecialchars().

When to use:

Example:

<form method="POST" action="/profile/update">
  <?= csrf_input() ?>
  <?= hidden_input('user_id', $user->id) ?>
  <?= hidden_input('redirect_to', '/dashboard') ?>
  <button type="submit">Update</button>
</form>
// Automatically escapes malicious content
<?= hidden_input('data', '"><script>alert("XSS")</script>') ?>
// Output: <input type="hidden" name="data" value="&quot;&gt;&lt;script&gt;...">

form_open()

form_open(string $action = '', string $method = 'POST', array $attributes = [], bool $csrf = true)

What it does: Opens an HTML form tag with automatic CSRF token injection and HTTP method spoofing support. Automatically escapes all attribute values for security.

When to use:

Parameters:

Example:

// Basic POST form with CSRF
<?= form_open('/profile/update') ?>
  <input type="text" name="name" value="<?= _e($user->name) ?>">
  <button type="submit">Update</button>
<?= form_close() ?>
// GET form (no CSRF token)
<?= form_open('/search', 'GET') ?>
  <input type="text" name="q" placeholder="Search...">
  <button type="submit">Search</button>
<?= form_close() ?>
// DELETE with method spoofing
<?= form_open('/posts/123', 'DELETE') ?>
  <button type="submit">Delete Post</button>
<?= form_close() ?>
// Outputs: method="POST" with hidden _method=DELETE and CSRF token
// With custom attributes
<?= form_open('/profile', 'POST', [
    'class' => 'profile-form',
    'id' => 'user-form',
    'enctype' => 'multipart/form-data'
]) ?>
  <!-- form fields -->
<?= form_close() ?>
// Disable CSRF for webhooks or public endpoints
<?= form_open('/webhook/stripe', 'POST', [], false) ?>
  <!-- webhook payload -->
<?= form_close() ?>

Important:

form_close()

form_close()

What it does: Outputs a closing </form> tag.

When to use:

Example:

<?= form_open('/profile/update') ?>
  <!-- form fields -->
<?= form_close() ?>

dd()

dd(...$args)

What it does: “Dump and Die”—outputs the contents of variables (like var_dump) and stops the script.

When to use:

Example:

dd($user, $posts);

pp()

pp(...$args)

What it does: “Pretty Print”—outputs variables using print_r and stops the script. This function is useful for debugging purposes, especially when working with arrays and objects.

When to use:

Example:

pp($myArray);
pp($var1, $var2, $var3)

halt()

halt(int $code, string $message = '', array $headers = [])

What it does: Immediately halts execution and throws an HTTP exception with the specified status code. If no message is provided, uses the standard HTTP status message (e.g., "Not Found" for 404).

When to use:

Example:

// Simple halt with standard message
halt(404);  // Throws "Not Found"
halt(403);  // Throws "Forbidden"

// With custom message
halt(404, 'User not found');
halt(403, 'You need admin access');

// With custom headers
halt(503, 'Service Unavailable', ['Retry-After' => '3600']);

// In conditional logic
if (!$user) {
    halt(404, 'User not found');
}

// One-liner
if (!$user) halt(404);

once()

once(callable $callback)

What it does: Executes a callback only once and caches the result. Subsequent calls with the same callback return the cached result without re-executing the callback.

When to use:

Example:

// In a model - expensive query runs only once
class User
{
    public function permissions()
    {
        return once(function() {
            // This query only runs once per request
            return Permission::where('user_id', $this->id)->all();
        });
    }
}

$user->permissions(); // Executes query
$user->permissions(); // Returns cached result
$user->permissions(); // Returns cached result
// Prevent duplicate API calls
$callback = function() {
    return $httpClient->get('https://api.example.com/data');
};

$data1 = once($callback); // Makes API call
$data2 = once($callback); // Returns cached response
$data3 = once($callback); // Returns cached response
// Expensive computation
class Report
{
    private $calculateStats;

    public function __construct()
    {
        $this->calculateStats = function() {
            // Heavy computation
            return $this->processLargeDataset();
        };
    }

    public function getStats()
    {
        return once($this->calculateStats);
    }
}

$report = new Report();
$stats = $report->getStats(); // Computes
$stats = $report->getStats(); // Cached

Important:

optional()

optional($value, ?callable $callback = null)

What it does: Safely access properties and methods on a potentially null value without causing errors. Returns a null-safe object that allows chaining.

When to use:

Example:

// Basic usage - no error even if $user is null
$name = optional($user)->name;
$email = optional($user)->profile->email;

// Without optional (verbose)
$name = $user !== null ? $user->name : null;
$email = $user !== null && $user->profile !== null ? $user->profile->email : null;

// With optional (clean)
$name = optional($user)->name;
$email = optional($user)->profile->email;
// Real-world: fetching user from database
$user = User::find($id); // Might return null

// Safe access
$userName = optional($user)->name;
$userCity = optional($user)->address->city;
$userEmail = optional($user)->getEmail();

// All work without errors, even if $user is null
// With callback transformation
$user = User::find($id);

$displayName = optional($user, function($u) {
    return strtoupper($u->firstName . ' ' . $u->lastName);
});

// If $user is null, $displayName is the null object
// If $user exists, $displayName is the transformed string
// In views - prevent errors from missing data
<h1><?= optional($post->author)->name ?></h1>
<p><?= optional($order->customer->address)->city ?></p>

// In controllers
public function show($id)
{
    $user = User::find($id);

    return response()->json([
        'name' => optional($user)->name,
        'email' => optional($user)->profile->email,
        'city' => optional($user)->address->city,
    ]);
}
// Chaining with method calls
$user = User::find($id);

// No error even if getProfile() returns null
$email = optional($user->getProfile())->email;
$phone = optional($user->getProfile())->getContactInfo()->phone;

Important: