Skip to main content

Overview

Views in S-PHP handle the presentation layer of your application. The View class provides a powerful rendering engine with support for layouts, components, and data passing.

Rendering Views

The View::render() static method is used to display views from your controllers.
View::render
method
$filename
string
required
Path to the view file relative to app/views/ directory
$data
array
default:"[]"
Associative array of data to pass to the view
Sphp/Core/View.php
public static function render($filename, $data = [])
{
    extract($data);

    $viewPath = '../app/views/' . $filename;
    if (file_exists($viewPath)) {
        // Process and render view
    } else {
        require('../app/views/404.html');
    }
}

Basic Usage

use Sphp\Core\View;

// Simple view
View::render('welcome.php');

// View with data
View::render('users/show.php', ['user' => $user]);

// Multiple data variables
View::render('dashboard.php', [
    'users' => $users,
    'stats' => $stats,
    'title' => 'Dashboard'
]);

Accessing Data in Views

Data passed to views is automatically extracted using PHP’s extract() function, making variables directly accessible:
app/views/users/show.php
<!-- Controller passes: ['user' => $user, 'title' => 'User Profile'] -->

<h1><?= $title ?></h1>
<div>
    <p>Name: <?= $user['name'] ?></p>
    <p>Email: <?= $user['email'] ?></p>
</div>

Layout Directive

The @layout directive allows you to include layout files that wrap your content. Layouts are stored in app/views/layout/.

Syntax

@layout('layout-name')
@layout('layout-name', ['variable' => 'value'])
@layout
directive
layout-name
string
required
Name of the layout file (without .php extension) in app/views/layout/
variables
array
Array of variables to pass to the layout

Example

app/views/welcome.php
@layout('main', ['title' => 'Welcome'])

<div class="content">
    <h1>Welcome to S-PHP</h1>
    <p>Start building your application!</p>
</div>
app/views/layout/main.php
<!DOCTYPE html>
<html>
<head>
    <title><?= $title ?? 'S-PHP Application' ?></title>
</head>
<body>
    <header>
        <nav><!-- Navigation --></nav>
    </header>
    
    <main>
        <!-- View content will be rendered here -->
    </main>
    
    <footer>
        <p>&copy; 2026 My Application</p>
    </footer>
</body>
</html>

How @layout Works

Sphp/Core/View.php
$content = preg_replace_callback("/@layout\('([^']+)'(?:\s*,\s*(\[.*?\]))?\)/", function ($matches) {
    $layoutPath = '../app/views/layout/' . $matches[1] . '.php';
    $variables = isset($matches[2]) ? eval ('return ' . $matches[2] . ';') : [];

    if (file_exists($layoutPath)) {
        ob_start();
        extract($variables);
        include $layoutPath;
        return ob_get_clean();
    }
    return "<!-- Layout '{$matches[1]}' not found -->";
}, $content);

Component Directive

The @component directive includes reusable component files. Components are stored in app/views/components/.

Syntax

@component('component-name')
@component('component-name', $variableName)
@component
directive
component-name
string
required
Name of the component file (without .php extension) in app/views/components/
$variableName
variable
Variable name (with $ prefix) containing data to pass to the component

Example

app/views/dashboard.php
<div class="dashboard">
    <h1>Dashboard</h1>
    
    @component('navbar')
    
    <div class="user-list">
        @component('user-card', $user)
    </div>
</div>
app/views/components/navbar.php
<nav class="navbar">
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/dashboard">Dashboard</a></li>
        <li><a href="/logout">Logout</a></li>
    </ul>
</nav>
app/views/components/user-card.php
<!-- Receives $user variable from parent view -->
<div class="card">
    <h3><?= $name ?? 'Unknown' ?></h3>
    <p><?= $email ?? '' ?></p>
    <span class="status <?= $verified ? 'active' : 'inactive' ?>">
        <?= $verified ? 'Verified' : 'Not Verified' ?>
    </span>
</div>

How @component Works

Sphp/Core/View.php
$content = preg_replace_callback("/@component\('([^']+)'(?:\s*,\s*(\$[\w]+))?\)/", function ($matches) use ($data) {
    $componentPath = 'app/views/components/' . $matches[1] . '.php';
    $variables = [];

    if (isset($matches[2]) && isset($data[substr($matches[2], 1)])) {
        $variables = $data[substr($matches[2], 1)];
    }

    if (file_exists($componentPath)) {
        ob_start();
        extract($variables);
        include $componentPath;
        return ob_get_clean();
    }
    return "<!-- Component '{$matches[1]}' not found -->";
}, $content);

View File Organization

Organize your views in a logical directory structure:
app/views/
├── layout/
│   ├── main.php
│   ├── admin.php
│   └── auth.php
├── components/
│   ├── navbar.php
│   ├── footer.php
│   ├── user-card.php
│   └── alert.php
├── users/
│   ├── index.php
│   ├── show.php
│   └── edit.php
├── dashboard.php
├── welcome.php
└── 404.html

Complete Example

app/Controllers/UserController.php
use Sphp\Core\Controller;
use Sphp\Core\View;
use App\Models\Users;

class UserController extends Controller
{
    public function index()
    {
        $userModel = new Users();
        $users = $userModel->select(['*'], ['verified' => 1]);
        
        View::render('users/index.php', [
            'users' => $users,
            'title' => 'All Users',
            'count' => count($users)
        ]);
    }
}
app/views/users/index.php
@layout('main', ['title' => $title])

<div class="users-page">
    @component('navbar')
    
    <h1><?= $title ?></h1>
    <p>Total users: <?= $count ?></p>
    
    <div class="user-grid">
        <?php foreach ($users as $user): ?>
            @component('user-card', $user)
        <?php endforeach; ?>
    </div>
</div>

Error Handling

When a view file is not found, S-PHP automatically renders the 404.html page:
if (file_exists($viewPath)) {
    // Render view
} else {
    require('../app/views/404.html');
}

Best Practices

Separate Concerns

Keep business logic in controllers and models. Views should only handle presentation.

Use Layouts

Create reusable layouts for consistent page structure across your application.

Component Reusability

Extract repeated UI elements into components for easier maintenance.

Escape Output

Use htmlspecialchars() or similar functions to prevent XSS attacks when outputting user data.

Security Considerations

Always escape user-generated content:
<!-- Unsafe -->
<p><?= $user['name'] ?></p>

<!-- Safe -->
<p><?= htmlspecialchars($user['name'], ENT_QUOTES, 'UTF-8') ?></p>

Next Steps

Controllers

Learn how to render views from controllers

Models

Understand how to fetch data for your views

Build docs developers (and LLMs) love