Recommend this page to a friend! |
![]() |
Info | Documentation | Demos | Videos | ![]() |
![]() |
![]() |
Reputation | Support forum | Blog | Links |
Last Updated | Ratings | Unique User Downloads | Download Rankings | |||||
2024-09-03 (Less than 1 hour ago) ![]() | Not yet rated by the users | Total: 36 | All time: 10,974 This week: 59![]() |
Version | License | PHP version | Categories | |||
luminova 3.2.11 | MIT/X Consortium ... | 8.0 | Tools, Libraries, Templates, Console, C..., D..., P... |
Description | Author | |
PHP Luminova Framework is a robust MVC and HMVC framework, supporting Twig, Smarty, and PHP templating with layout inheritance and extensions using methods like `begin`, `end`, `import`, and `extend`. |
The Framework You Didn't Know You Needed to Illuminate Your Project
PHP Luminova is a web development framework for PHP 8 and above, it's simple yet powerful, supporting both MVC and HMVC architectures, Twig, Smarty, and PHP templating with layout inheritance and extending.
Luminova comes packed with useful modules for application security and optimization.
Whether you prefer routing using PHP attributes or traditional code-based routing, we've got you covered.
You can install the package from the PHP Classes Composer repository following the instructions in the Download tab.
Alternatively, you can download Luminova as a ZIP or .tar.gz archive. After extracting the archive to your preferred directory, run the following command to install the required modules:
composer update
Installing Luminova via Composer is recommended for easy updates:
composer create-project luminovang/luminova my-project
Download the latest version from Luminova's official website: Download Luminova.
Alternatively, you can manually download it from GitHub by following the instructions here: Installation Guide.
You can now define routes using the PHP8 attribute (e.g., #[Route('/', methods: ['GET', 'POST'])]
).
Supports serving partially static content to improve performance. Enable page.caching
in your env
file and append an extension (e.g., .html
) to your request URL. This reduces view response time by up to 10%
by loading cached pages without invoking controller methods and other modules.
Example:
- Original URL: https://example.com/blog/how-to-install-luminova
- Static URL: https://example.com/blog/how-to-install-luminova.html
> Note: When a content extension is specified, application events and middleware are bypassed.
This documentation covers the basic implementation of template handling within the Luminova framework controllers.
Controllers are classes that handle requests made to your application, whether they originate from HTTP requests or CLI commands. Upon initialization, a controller method processes the request, receiving all necessary parameters and dependencies. After processing the information, the controller renders the response or handles it accordingly. All controller classes should be placed in the /app/Controllers/
directory.
*
Luminova provides two base controller classes for handling HTTP requests, both of which manage requests in a similar manner but differ in their initialization processes.
*
Extending Luminova\Base\BaseController automatically initializes the HTTP request class \Luminova\Http\Request
and the input validation class Luminova\Security\Validation
.
// /app/Controllers/MyController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
class MyController extends BaseController
{
//...
}
*
Extending Luminova\Base\BaseViewController does not automatically initialize any additional classes, allowing for manual initialization when necessary. This is particularly useful for web pages that do not require immediate user input validation.
// /app/Controllers/MyController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseViewController;
class MyController extends BaseViewController
{
//...
}
*
Extending Luminova\Base\BaseCommand allows the controller to handle command line operations in a manner similar to HTTP controllers. For more details on command line implementation, see examples.
// /app/Controllers/MyCommand.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseCommand;
class MyCommand extends BaseCommand
{
//...
}
*
In Luminova, you have multiple ways to handle and respond to requests. You can use the Luminova\Template\Response
class, which provides a global response
function, or utilize the Template View
handling class, readily available in the core application object.
The primary difference lies in how they receive and process content. Additionally caching is not implemented for response class but for template view object cache is implemented.
*
The Response
class allows you to handle any type of response rendering without additional processing, making it particularly useful for APIs that need to return JSON responses, downloadable content, and more.
// /app/Controllers/BookController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
use Luminova\Attributes\Route;
use Luminova\Attributes\Error;
use App\Controllers\Errors\ViewErrors;
#[Error('api', onError: [ViewErrors::class, 'onApiError'])]
class BookController extends BaseController
{
#[Route('/api/books', methods: ['POST'])]
public function apiListBooks(): int
{
$books = [
['id' => 100, 'name' => 'Basic Programming'],
['id' => 1001, 'name' => 'Advanced Programming']
];
return response(200)->json($books);
}
}
In above example, when a POST request is sent to https://example.com/api/books
, it will output a JSON response containing the list of books.
*
The View
object is designed to load and render templates stored in the /resources/views
directory. Supported template file extensions include:
- .tpl
: For the Smarty template engine
- .twg
: For the Twig template engine
- .php
: For standard PHP templates
When you pass the template file name without the extension, the View
object automatically loads the template, processes the content, and allows you to pass optional metadata during rendering.
// /resources/views/books.php
<!DOCTYPE html>
<html lang="en">
<head>
<title><?php $this->_title;?></title>
</head>
<body>
<h1>My Book Website</h1>
<ul>
<?php foreach ($this->_books as $book): ?>
<li>[<?= $book['id']; ?>] <?= $book['name']; ?></li>
<?php endforeach; ?>
</ul>
</body>
</html>
*
// /app/Controllers/BookController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseViewController;
use Luminova\Attributes\Route;
use Luminova\Attributes\Error;
use App\Controllers\Errors\ViewErrors;
#[Error(onError: [ViewErrors::class, 'onWebError'])]
class BookController extends BaseViewController
{
#[Route('/books', methods: ['GET'])]
public function webShowBooks(): int
{
// Assume loading books from a database.
$books = [
['id' => 100, 'name' => 'Basic Programming'],
['id' => 1001, 'name' => 'Advanced Programming']
];
return $this->view('books', [
'books' => $books
]);
}
}
In this example, when a GET request is sent to https://example.com/books
, it displays an HTML page containing the list of books.
*
There may be cases where you want to generate a template's output without displaying it directly to the user, such as when sending an email with the rendered content.
Here's how you can achieve this:
// /app/Controllers/BookController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
use Luminova\Email\Mailer;
use Luminova\Attributes\Route;
use Luminova\Attributes\Error;
use App\Controllers\Errors\ViewErrors;
#[Error(onError: [ViewErrors::class, 'onWebError'])]
class BookController extends BaseController
{
#[Route('/books/send', methods: ['GET'])]
public function sendShowBooks(string $email): int
{
$books = [
['id' => 100, 'name' => 'Basic Programming'],
['id' => 1001, 'name' => 'Advanced Programming']
];
// Generate the view content without rendering it
$content = $this->respond('books', [
'books' => $books
]);
// Send the generated content as an email
Mailer::to($email)->send($content);
// Redirect the user after sending the email
$this->app->redirect('thank-you');
return STATUS_SUCCESS;
}
}
This approach is useful when you need to use the output of a template for purposes other than direct display, such as generating emails, saving content to a file, or performing other custom actions.
*
Luminova automatically handles the basic headers for your template output, but there may be times when you want to include additional headers to be sent along with your template.
Here's how you can do it:
<?php
namespace App\Controllers;
use Luminova\Base\BaseViewController;
use Luminova\Attributes\Route;
use Luminova\Attributes\Error;
use App\Controllers\Errors\ViewErrors;
#[Error(onError: [ViewErrors::class, 'onWebError'])]
class MyController extends BaseViewController
{
#[Route('/books', methods: ['GET'])]
public function webShowBooks(): int
{
// Set multiple headers at once using an array
$this->app->headers([
'Content-Type' => 'text/html; charset=utf-8',
'X-Custom-Header' => 'CustomValue'
]);
// Or set a single header using key-value pairs
$this->app->header('Content-Type', 'text/html; charset=utf-8');
return $this->view('books');
}
}
This flexibility ensures that you can customize the headers sent with your views to match your specific needs, whether it's content type, caching controls, or custom headers.
*
The template view in Luminova allows you to cache content, serving a cached version of the page upon revisits. Caching can be implemented either automatically or manually to learn more about view caching read documentation.
To enable page view caching, update your environment variables as follows:
Automatic caching requires no additional implementation after enabling the caching feature and setting the desired cache expiration and controls.
*
This method allows you to render cached content if it is still valid. The callback function will only be executed if the cache does not exist or has expired.
<?php
namespace App\Controllers;
use Luminova\Base\BaseViewController;
use Luminova\Attributes\Route;
use Luminova\Attributes\Error;
use App\Controllers\Errors\ViewErrors;
#[Error(onError: [ViewErrors::class, 'onWebError'])]
class MyController extends BaseViewController
{
#[Route('/books', methods: ['GET'])]
public function webShowBooks(): int
{
// The first argument is the type of view content.
$this->app->onExpired('html', function() {
$books = [
['id' => 100, 'name' => 'Basic Programming'],
['id' => 1001, 'name' => 'Advanced Programming']
];
return $this->view('books', [
'books' => $books
]);
});
}
}
*
This approach uses a traditional if-else check to first verify if the cache has expired. If the cache is still valid, the existing content is rendered when you call the reuse
method. If the cache has expired, new content is generated to refresh the content.
<?php
namespace App\Controllers;
use Luminova\Base\BaseViewController;
use Luminova\Attributes\Route;
use Luminova\Attributes\Error;
use App\Controllers\Errors\ViewErrors;
use Luminova\Core\CoreApplication;
#[Error(onError: [ViewErrors::class, 'onWebError'])]
class MyController extends BaseViewController
{
#[Route('/books', methods: ['GET'])]
public function webShowBooks(): int
{
// Set an expiration time (in seconds) or leave blank/null to use the default expiration.
$this->app->cache(3600);
if ($this->app->expired()) {
$books = [
['id' => 100, 'name' => 'Basic Programming'],
['id' => 1001, 'name' => 'Advanced Programming']
];
return $this->view('books', [
'books' => $books
]);
}
return $this->app->reuse();
}
}
In these examples, when a GET request is sent to https://example.com/books
, the application checks for cached content and serves it accordingly, ensuring efficient use of resources and faster response times.
*
Luminova supports serving static content, meaning that when content is cached, your controller class or method will not be invoked upon page visits. Instead, the cached version is served, enhancing performance.
To enable static cache serving, specify the list of supported static content types in your environment configuration file (.env
).
In the following example, we specify the supported view content types as HTML
and JSON
.
This configuration instructs the framework to process any URLs ending with these extensions. If a corresponding view exists, it will be served.
page.caching.statics = html|json
In this case, if a user visits https://example.com/books.html
, the cached content will be served if available; otherwise, it will be cached.
Conversely, since there is no view matching .json
, visiting https://example.com/books.json
will trigger a 404 error.
*
While caching is enabled globally, you can exclude certain views from being cached or specify a list of views that can be cached. This can be accomplished in your application class's onCreate
or __construct
method, or within your controller class's onCreate
or __construct
method.
To exclude views from caching, define them as follows:
<?php
namespace App;
use Luminova\Core\CoreApplication;
class Application extends CoreApplication
{
protected function onCreate(): void
{
$this->noCaching([
'edit_book',
'book_payment',
'book_cart'
]);
}
}
*
If you have many views but only want to cache one, you can use the cacheOnly
method to specify just that view, avoiding the need to list all others:
<?php
namespace App;
use Luminova\Core\CoreApplication;
class Application extends CoreApplication
{
protected function onCreate(): void
{
// Accepts a string or an array of views.
$this->cacheOnly('books');
}
}
*
Organizing content in a framework is crucial for easy access and management. Luminova provides a simple and effective way to maintain a clean and organized structure for your view templates based on URL prefixes.
Imagine you have a website with the following URL patterns:
Placing all templates directly under the resources/views/
directory could become unmanageable as your project grows. To maintain orderliness, you can organize your views into separate directories based on URL prefixes.
You can create dedicated controller classes for each URL prefix, such as ApiController
for API requests, AdminController
for the admin interface, and WebController
for the main website.
Within each controller's onCreate
or __construct
method, you can specify the base directory where the corresponding template files are located under the /resources/views/
root directory.
Here's how you can set it up:
// /app/Controllers/WebController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
class WebController extends BaseController
{
protected function onCreate(): void
{
// No need to change the directory; it uses the default root directory.
}
}
// /app/Controllers/ApiController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
class ApiController extends BaseController
{
protected function onCreate(): void
{
// Organize API views in /resources/views/apis/
$this->setFolder('apis');
}
}
// /app/Controllers/AdminController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
class AdminController extends BaseController
{
protected function onCreate(): void
{
// Organize admin views in /resources/views/admins/
$this->setFolder('admins');
}
}
*
In Luminova, you can easily enable output minification when rendering HTML templates using the template view object. This feature automatically minifies your web page content by removing inline comments and newlines, resulting in a more compact and faster-loading page.
When you visit some websites and use Ctrl + U
to view the HTML source, you may notice that it's not easily readable due to such minification. Luminova allows you to achieve this in your project by enabling the page.minification
environment variable in your .env
file. Simply set it to true
to minify your template output.
*
Minifying all content is generally beneficial, but it can be problematic for websites that display sample code within HTML <pre><code>
blocks. Minification can make the code within these blocks unreadable by removing newlines, which also prevents JavaScript syntax highlighters from functioning correctly.
Luminova offers a solution to this issue by allowing you to exclude code blocks from minification while still ensuring the rest of your page content is properly minified. Here's how you can do it:
Example:
In your application controller's onCreate
or __construct
method, you can call the codeblock
method and pass false
as the first parameter to exclude code blocks from minification. You can also pass true
as the second parameter to include a copy button alongside the code block, similar to what's found on the Luminova documentation website.
// /app/Controllers/AdminController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
class AdminController extends BaseController
{
protected function onCreate(): void
{
$this->codeblock(
false, // Exclude code blocks from minification
true // Include a copy button with the code block
);
}
}
By using this approach, you can maintain both the readability of your code samples and the overall performance benefits of minified content.
*
Luminova provides two rendering modes for templates, which can be configured in your application's template configuration class located at /app/Config/Template.php
. These modes allow you to choose your preferred coding style and determine how templates interact with application objects.
When the template rendering mode is set to isolation, the view processing is entirely isolated, meaning you cannot access application class objects using the $this
keyword. Instead, a custom keyword $self
is provided to access properties defined in the application's class scope.
However, to still access protected or public properties defined in the application class, you need to export them using the export
method. This method allows you to make specific objects or class instances available within the isolated template context.
// /app/Controllers/AdminController.php
<?php
namespace App\Controllers;
use Luminova\Base\BaseController;
use App\Models\Users;
use App\Utils\Foo;
use App\Utils\Bar;
use App\Utils\Baz;
class AdminController extends BaseController
{
protected Users $users;
public function __construct()
{
// Initialize and export an instance of the Users class
$this->users = new Users();
$this->export($this->users, 'users');
// Export a class that has static methods without initialization
$this->export(Foo::class, null, false);
// Export a class and initialize it upon export
$this->export(Bar::class, null, true);
// Export a class, initialize it, and assign it a different name (alias) for use in templates
$this->export(Baz::class, 'ClassBaz', true);
}
}
*
*
This approach is particularly useful in complex applications where templates need access to specific objects or classes while maintaining a strict separation between the view and controller logic. By exporting the necessary objects or classes, you ensure that your templates have the required context and data to render correctly, even in isolated mode.
Luminova is a PHP framework built for speed and efficiency, designed to enhance your existing coding skills. At Luminova, we prioritize performance by offering feature customization through the env
file. This ensures the framework includes only what's needed for your project, based on the features you enable. This approach allows you to enable or disable features as well as customizing your preferred template rendering mode and coding style.
Luminova, provide access to the template View
object within the view files, allowing you to call template methods and properties using $this
keyword within template files. This can be disabled if you prefer your views to be rendered in isolation, disabling it will allow you to access exported application classes using custom keyword $self
.
Ready to light up your projects? Dive into our official documentation. For more tips, tricks, and some coding fun, check out our YouTube channel.
Install luminova via Composer.
composer create-project luminovang/luminova my-project
To start the PHP
development server, run the following NovaKit
command.
php novakit server
To generate your website sitemap use the below NovaKit
command.
php novakit generate:sitemap
To learn more about NovaKit commands read the novakit documentation.
Luminova support flexible routing implementation using Attributes
or Router
methods.
Define your route using PHP8
attributes:*
#[Route('/', methods: ['GET'])]
public function index(): int
{
return $this->view('index');
}
Or define your route using code-based routing:
<?php
$router->get('/', 'YourController::index');
Here we can brief you on the basic features you can expect in Luminova. There's a lot more than what is written here. As Linus Torvalds said, "Talk is cheap. Show me the code."
Q: My session works on the development server but not on the production server.
- A: In production, update the $sessionDomain
in /app/Config/Session.php
to your actual production domain. A quick fix is to use '.' . APP_HOST
. Also, don't forget to update the Cookie.php
configuration accordingly.
Q: My CSS and images are broken on the production server.
- A: Make sure you set the app.environment.mood
key to production
in your environment file when deploying to production. This small step ensures your assets are served correctly.
Your feedback is highly appreciated! Drop us a line at peter@luminova.ng. Let us know what we can add to enhance your experience with Luminova. You can also recommend tutorials for our YouTube channel to help you understand and use Luminova better.
Most importantly, don't forget to rate Luminova on GitHub. Your rating is like fuel, helping to illuminate our motivation to add more features and make Luminova even better known and more powerful.
Videos (3) | ||
![]() |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() |
||||
![]() |
||||
![]() |
||||
![]() |
||||
![]() |
||||
![]() |
||||
![]() |
||||
![]() ![]() |
Data | Auxiliary data | ||
![]() ![]() |
Data | Auxiliary data | ||
![]() ![]() |
Lic. | License text | ||
![]() ![]() |
Appl. | Luminova CLI Tool | ||
![]() ![]() |
Aux. | Auxiliary script | ||
![]() ![]() |
Data | Auxiliary data | ||
![]() ![]() |
Data | Auxiliary data | ||
![]() ![]() |
Doc. | Documentation | ||
![]() |
Class | Class source |
![]() |
/ | app |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() |
||||
![]() |
||||
![]() |
||||
![]() |
Class | Class source |
![]() |
/ | app | / | Config |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() ![]() |
Aux. | Configuration script | ||
![]() |
Class | Class source | ||
![]() ![]() |
Aux. | Configuration script | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() ![]() |
Aux. | Configuration script | ||
![]() |
Class | Class source |
![]() |
/ | app | / | Config | / | Templates | / | Smarty |
File | Role | Description |
---|---|---|
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
/ | app | / | Config | / | Templates | / | Twig |
File | Role | Description |
---|---|---|
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
/ | app | / | Controllers |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() ![]() |
Example | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source |
![]() |
/ | app | / | Languages |
File | Role | Description |
---|---|---|
![]() ![]() |
Aux. | Configuration script |
![]() ![]() |
Aux. | Configuration script |
![]() |
/ | app | / | Utils |
File | Role | Description |
---|---|---|
![]() |
Class | Class source |
![]() ![]() |
Aux. | Configuration script |
![]() |
/ | bootstrap |
File | Role | Description |
---|---|---|
![]() ![]() |
Example | Example script |
![]() ![]() |
Aux. | Auxiliary script |
![]() |
Class | Class source |
![]() |
/ | public |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() ![]() |
Data | Auxiliary data | ||
![]() ![]() |
Icon | Icon image | ||
![]() |
Class | Class source | ||
![]() ![]() |
Doc. | Documentation |
![]() |
/ | resources | / | views |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() ![]() |
Example | Example script | ||
![]() ![]() |
Aux. | Auxiliary script | ||
![]() ![]() |
Data | Auxiliary data | ||
![]() ![]() |
Data | Auxiliary data |
![]() |
/ | resources | / | views | / | system_errors |
File | Role | Description |
---|---|---|
![]() ![]() |
Aux. | Auxiliary script |
![]() ![]() |
Example | Example script |
![]() |
Class | Class source |
![]() ![]() |
Data | Auxiliary data |
![]() ![]() |
Example | Example script |
![]() ![]() |
Aux. | Configuration script |
![]() ![]() |
Data | Auxiliary data |
![]() ![]() |
Aux. | Auxiliary script |
![]() ![]() |
Example | Example script |
![]() ![]() |
Aux. | Auxiliary script |
![]() |
/ | routes |
![]() |
/ | system |
![]() |
/ | system | / | Composer |
File | Role | Description |
---|---|---|
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
/ | system | / | Debugger |
File | Role | Description |
---|---|---|
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
/ | system | / | plugins |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() |
||||
![]() ![]() |
Aux. | Auxiliary script |
![]() |
/ | system | / | plugins | / | composer |
File | Role | Description |
---|---|---|
![]() ![]() |
Aux. | Auxiliary script |
![]() ![]() |
Aux. | Auxiliary script |
![]() ![]() |
Aux. | Auxiliary script |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() ![]() |
Data | Auxiliary data |
![]() ![]() |
Aux. | Auxiliary script |
![]() |
Class | Class source |
![]() ![]() |
Lic. | License text |
![]() ![]() |
Aux. | Auxiliary script |
![]() |
/ | system | / | plugins | / | psr | / | log |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() ![]() |
Data | Auxiliary data | ||
![]() ![]() |
Lic. | License text | ||
![]() |
Class | Class source |
![]() |
/ | system | / | plugins | / | psr | / | log | / | Psr | / | Log |
File | Role | Description | ||
---|---|---|---|---|
![]() |
||||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source | ||
![]() |
Class | Class source |
![]() |
/ | system | / | plugins | / | psr | / | log | / | Psr | / | Log | / | Test |
File | Role | Description |
---|---|---|
![]() |
Class | Class source |
![]() |
Class | Class source |
![]() |
Class | Class source |
The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page. |
![]() |
Version Control | Unique User Downloads | Download Rankings | |||||||||||||||
100% |
|
|
Applications that use this package |
If you know an application of this package, send a message to the author to add a link here.