PHP code example of paigejulianne / nanomvc

1. Go to this page and download the library: Download paigejulianne/nanomvc library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

paigejulianne / nanomvc example snippets





PaigeJulianne\NanoMVC\App;

App::run(__DIR__);


use PaigeJulianne\NanoMVC\Router;

Router::get('/', [HomeController::class, 'index']);
Router::get('/users/{id}', [UsersController::class, 'show']);
Router::post('/users', [UsersController::class, 'store']);


use PaigeJulianne\NanoMVC\Controller;
use PaigeJulianne\NanoMVC\Request;
use PaigeJulianne\NanoMVC\Response;

class HomeController extends Controller
{
    public function index(Request $request): Response
    {
        return $this->view('home', [
            'title' => 'Welcome',
            'message' => 'Hello, World!',
        ]);
    }
}

<!DOCTYPE html>
<html>
<head>
    <title><?= htmlspecialchars($title) 

use PaigeJulianne\NanoMVC\App;
use PaigeJulianne\NanoMVC\View;

App::setDebug(true);
App::setConfig('app.name', 'My App');
View::configure('/path/to/views', '/path/to/cache', 'blade');

use PaigeJulianne\NanoMVC\Router;

Router::get('/path', $handler);
Router::post('/path', $handler);
Router::put('/path', $handler);
Router::patch('/path', $handler);
Router::delete('/path', $handler);
Router::any('/path', $handler);      // Matches any method

// Required parameter
Router::get('/users/{id}', function (Request $request) {
    $id = $request->param('id');
    return "User ID: $id";
});

// Multiple parameters
Router::get('/posts/{year}/{month}/{slug}', function (Request $request) {
    return $request->params(); // ['year' => '2024', 'month' => '12', 'slug' => 'hello']
});

Router::group(['prefix' => 'api'], function () {
    Router::get('/users', [ApiController::class, 'users']);
    Router::get('/posts', [ApiController::class, 'posts']);
});
// Creates: /api/users and /api/posts

Router::group(['prefix' => 'api'], function () {
    Router::group(['prefix' => 'v1'], function () {
        Router::get('/users', [ApiV1Controller::class, 'users']);
    });
});
// Creates: /api/v1/users

// Closure
Router::get('/hello', function (Request $request) {
    return 'Hello, World!';
});

// Controller method [ClassName, 'methodName']
Router::get('/users', [UsersController::class, 'index']);

// Inline middleware
Router::get('/admin', [AdminController::class, 'index'], [
    function (Request $request) {
        if (!isLoggedIn()) {
            return Response::redirect('/login');
        }
        return null; // Continue to handler
    }
]);

// Middleware class
Router::get('/dashboard', [DashboardController::class, 'index'], [
    AuthMiddleware::class
]);

// Custom 404 handler
Router::setNotFoundHandler(function (Request $request) {
    return View::make('errors.404', [], 404);
});

// Custom error handler
Router::setErrorHandler(function (\Throwable $e, Request $request) {
    return View::make('errors.500', ['error' => $e->getMessage()], 500);
});

// Generate route cache (run during deployment)
);

// Load cached routes in production
if (file_exists('/path/to/cache/routes.php')) {
    Router::loadCachedRoutes('/path/to/cache/routes.php');
} else {
    

$stats = Router::getStats();
// Returns: [
//   'total_routes' => 150,
//   'static_routes' => 80,
//   'dynamic_routes' => 70,
//   'by_method' => ['GET' => 100, 'POST' => 50],
//   'cached_middleware' => 5,
//   'routes_cached' => true
// ]

use PaigeJulianne\NanoMVC\Controller;
use PaigeJulianne\NanoMVC\Request;
use PaigeJulianne\NanoMVC\Response;

class UsersController extends Controller
{
    public function index(Request $request): Response
    {
        $users = Users::getAllObjects();
        return $this->view('users.index', ['users' => $users]);
    }

    public function show(Request $request): Response
    {
        $id = $request->param('id');
        $user = new Users($id);
        return $this->view('users.show', ['user' => $user]);
    }

    public function store(Request $request): Response
    {
        $data = $this->validate([
            'name' => '

// Render a view
$this->view('template', ['data' => 'value'], 200);

// JSON response
$this->json(['key' => 'value'], 200);

// Redirect
$this->redirect('/path', 302);

// Plain text
$this->text('Plain text', 200);

// HTML
$this->html('<h1>HTML</h1>', 200);

$data = $this->validate([
    'name' => 'e' => 'numeric|min:1',
    'role' => 'in:admin,user,guest',
]);

// Query parameters (?foo=bar)
$request->query('foo');
$request->query('foo', 'default');
$request->allQuery();

// POST data
$request->input('field');
$request->input('field', 'default');

// All input (POST + GET)
$request->all();
$request->only(['field1', 'field2']);
$request->except(['password']);

// Check if exists
$request->has('field');

$request->param('id');
$request->param('id', 'default');
$request->params(); // All route params

$request->method();      // GET, POST, etc.
$request->path();        // /users/123
$request->header('Accept');
$request->cookie('session');
$request->isAjax();
$request->expectsJson();
$request->getContent();  // Raw body
$request->json();        // JSON decoded body

use PaigeJulianne\NanoMVC\Response;

// JSON
$response = Response::json(['data' => 'value'], 200);

// Redirect
$response = Response::redirect('/path', 302);

// Plain text
$response = Response::text('Content', 200);

// HTML
$response = Response::html('<h1>Hello</h1>', 200);

$response = new Response();
$response->setContent('Hello')
         ->setStatusCode(200)
         ->header('X-Custom', 'value')
         ->withHeaders(['X-A' => '1', 'X-B' => '2']);

// Configure compression (optional)
Response::configureCompression(
    threshold: 1024,  // Min bytes to compress (default 1KB)
    level: 6          // Compression level 0-9 (default 6)
);

// Disable compression for specific response
return Response::json($data)->withoutCompression();

// Re-enable compression
return Response::html($content)->withCompression();

View::configure('/path/to/views', '/path/to/cache', 'php');

View::configure('/path/to/views', '/path/to/cache', 'blade');

View::configure('/path/to/views', '/path/to/cache', 'smarty');

View::configure('/path/to/views', '/path/to/cache', 'twig');

// In controller
return $this->view('users.index', ['users' => $users]);

// Directly
$html = View::render('template', ['data' => 'value']);

// As response
$response = View::make('template', ['data' => 'value'], 200);

// Share with all views
View::share('appName', 'My App');
View::share(['key1' => 'value1', 'key2' => 'value2']);

<h1><?= htmlspecialchars($title) 

use PaigeJulianne\NanoORM;

class Users extends NanoORM
{
    // Maps to 'users' table automatically
}

class BlogPost extends NanoORM
{
    const TABLE_OVERRIDE = 'blog_posts';
}

class UsersController extends Controller
{
    public function index(Request $request): Response
    {
        $users = Users::getAllObjects();
        return $this->view('users.index', ['users' => $users]);
    }

    public function show(Request $request): Response
    {
        $user = new Users($request->param('id'));
        return $this->view('users.show', ['user' => $user]);
    }

    public function store(Request $request): Response
    {
        $data = $this->validate([
            'name' => '

use PaigeJulianne\NanoMVC\Session;

// Set and get values
Session::set('user_id', 123);
$userId = Session::get('user_id');
$name = Session::get('name', 'Guest');  // With default

// Check and remove
if (Session::has('user_id')) {
    Session::forget('user_id');
}

// Get all session data
$all = Session::all();

// Clear all data
Session::flush();

// Destroy session completely
Session::destroy();

// Set flash message (available only on next request)
Session::flash('success', 'User created successfully!');

// Get flash message (automatically removed)
$message = Session::getFlash('success');

// Get CSRF token (for forms)
$token = Session::csrfToken();

// In your form
<input type="hidden" name="_token" value="<?= Session::csrfToken() 

Session::configure([
    'name' => 'my_app_session',
    'lifetime' => 7200,      // 2 hours
    'path' => '/',
    'domain' => '',
    'secure' => true,        // HTTPS only
    'httponly' => true,      // No JavaScript access
    'samesite' => 'Lax',     // CSRF protection
]);

use PaigeJulianne\NanoMVC\FileSessionDriver;

// Use file-based sessions with custom path
$driver = new FileSessionDriver('/path/to/sessions', 7200);
Session::setDriver($driver);

use PaigeJulianne\NanoMVC\RateLimiter;
use PaigeJulianne\NanoMVC\FileRateLimitStore;

// Configure storage (erId;
if (RateLimiter::attempt($key, maxAttempts: 60, decaySeconds: 60)) {
    // Within limit - process request
} else {
    // Rate limited
    $retryAfter = RateLimiter::availableIn($key);
}

// Get remaining attempts
$remaining = RateLimiter::remaining($key, 60);

// Clear rate limit
RateLimiter::clear($key);

use PaigeJulianne\NanoMVC\ThrottleMiddleware;

// 60 requests per minute
Router::get('/api/users', [ApiController::class, 'index'], [
    new ThrottleMiddleware(60, 1)
]);

// 100 requests per hour with custom key
Router::post('/api/search', [ApiController::class, 'search'], [
    new ThrottleMiddleware(100, 60, fn($req) => $req->header('X-API-Key'))
]);

// Apply to route group
Router::group(['prefix' => 'api', 'middleware' => [new ThrottleMiddleware(120, 1)]], function () {
    Router::get('/users', [ApiController::class, 'users']);
    Router::get('/posts', [ApiController::class, 'posts']);
});

use PaigeJulianne\NanoMVC\CsrfMiddleware;

// Apply to all POST/PUT/DELETE routes
Router::group(['middleware' => [new CsrfMiddleware()]], function () {
    Router::post('/users', [UsersController::class, 'store']);
    Router::delete('/users/{id}', [UsersController::class, 'destroy']);
});

// Exclude specific paths (e.g., webhooks)
$csrf = new CsrfMiddleware(['/api/webhooks/*', '/api/stripe/*']);

use PaigeJulianne\NanoMVC\CorsMiddleware;

// Allow all origins
Router::group(['prefix' => 'api', 'middleware' => [new CorsMiddleware()]], function () {
    Router::get('/users', [ApiController::class, 'users']);
});

// Configure specific origins
$cors = new CorsMiddleware([
    'allowed_origins' => ['https://example.com', 'https://app.example.com'],
    'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE'],
    'allowed_headers' => ['Content-Type', 'Authorization', 'X-API-Key'],
    'exposed_headers' => ['X-RateLimit-Remaining'],
    'max_age' => 86400,
    'supports_credentials' => true,
]);

 $baseUrl = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/'); 

 $baseUrl = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/'); 
ini
[app]
debug=true

[views]
engine=php
path=views
cache=cache
ini
[app]
debug=true
name=My Application

[views]
engine=php      # php, blade, smarty, or twig
path=views
cache=cache

[routes]
file=routes.php
smarty
<h1>{$title}</h1>
<ul>
{foreach $users as $user}
    <li>{$user->name}</li>
{/foreach}
</ul>
nginx
location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    
ini
[views]
path=views
cache=cache