Swiftlet is quite possibly the smallest MVC framework you'll ever use. And it's swift.
Licensed under the MIT license.
✔ Micro-Framework
✔ Loosely coupled
✔ Namespaced
✔ Unit tested
✔ Pluggable
✔ PSR-0
✔ PHP5
✔ MVC
✔ OOP
✘ ORM
- Step 1: Clone (or download and extract) Swiftlet into a directory on your PHP supported web server.
- Step 2: Congratulations, Swiftlet is now up and running.
- Step 3: There is no step 3.
Let's create a page. Each page consists of a controller and at least one view.
The controller does most of the work; views should be limited to simple presentation logic (loops and switches).
Controller vendor/HelloWorld/Controllers/Foo.php
<?php
namespace HelloWorld\Controllers;
class Foo extends \Swiftlet\Abstracts\Controller
{
protected $title = 'Foo'; // Optional but usually desired
// Default action
public function index(array $args = $args)
{
// Pass a variable to the view
$this->view->helloWorld = 'Hello world!';
}
}
Important: class names are written in CamelCase and match their filename.
View views/foo.php
<h1><?= $this->pageTitle ?></h1>
<p>
<?= $this->helloWorld ?>
</p>
The controller can set variables directly on the view. Values are automatically
made safe for use in HTML, use $this->get('variable', false)
on values that
should be treated as code.
You can now view the page by navigating to http://<swiftlet>/foo
in your web
browser!
If you get a "404 Not Found" you will need to enable rewrites in the web server
configuration. Alternatively you can navigate to http://<swiftlet>?q=foo
.
Swiftlet can be invoked from the command line (e.g. to run cron jobs). Simply
run php public/index.php -q foo
.
Notice how you can access the page at /foo
by simply creating a controller
named Foo
. The application maps URLs to controllers, actions and arguments.
Consider this URL: /foo/bar/baz/qux
In this case foo
becomes the name of the controller and view, bar
the name
of the action and baz
and qux
are arguments (accessible through the $args
variable in the controller).
If the controller or action is not specified they default to index
(/
will call index()
on HelloWorld\Controller\Index
).
Underscores in the controller name are translated to directory separators, so
/foo_bar
will point to vendor/HelloWorld/Controllers/Foo/Bar.php
.
Dashes in routes are ignored; /foo-bar/baz-qux
calls bazqux()
in
vendor/HelloWorld/Controllers/Foobar.php
.
Custom routes
Automatic routing is convenient but more granular control is often desirable. In these cases custom routes can be defined.
A route maps a URL to an action (method).
URL segments can be replaced with a "wildcard" placeholder (a variable name prefixed with a colon). This value becomes available for use in the controller.
Consider this route: bar/:qux
Navigating to <controller>/bar/something
matches this route. The value of
$args['qux']
becomes something
.
<?php
namespace HelloWorld\Controllers;
class Foo extends \Swiftlet\Abstracts\Controller
{
protected $routes = array(
'hello/world' => 'index',
'bar/:qux' => 'bar'
);
public function index(array $args = $args)
{
// You navigated to foo/hello/world
}
public function bar(array $args = $args)
{
// You navigated to foo/bar/<something>
// $args['qux'] contains the second URL argument
}
}
Actions are methods of the controller. A common example might be edit
or
delete
:
/blog/edit/1
This will call the function edit()
on Blog
with 1
as an argument (the
id of the blog post to edit).
Arguments can be accessed through $this->app->getArgs()
.
To use a different view for a specific action you may change the value of
$this->view->name
. The view name is a filename relative to the views
directory, without the .php
suffix.
Let's throw a model into the mix and update the controller.
Model vendor/HelloWorld/Models/Foo.php
<?php
namespace HelloWorld\Models;
class Foo extends \Swiftlet\Abstracts\Model
{
public function getHelloWorld()
{
return 'Hello world!';
}
}
Controller vendor/HelloWorld/Controllers/Foo.php
<?php
namespace HelloWorld\Controllers;
class Foo extends \Swiftlet\Abstracts\Controller
{
protected $title = 'Foo';
public function index()
{
// Get an instance of the Example class
// See vendor/HelloWorld/Models/Example.php
$example = $this->app->getModel('example');
$this->view->helloWorld = $example->getHelloWorld();
}
}
A model typically represents data. This can be an entry in a database or an object such as a user.
<?php
$user = $this->app->getModel('user');
$user->setEmail('[email protected]');
$user->save();
Loading and saving data should almost always happen in a model. You can create as many models as you like; they aren't tied to specific controllers or views.
Plugins implement hooks. Hooks are entry
points for code that extends the application. Swiftlet has a few core hooks and
additiontal ones can be registered pretty much anywhere using
$this->app->registerHook($hookName, $controller, $view)
.
Plugin vendor/HelloWorld/Plugins/Foo.php
<?php
namespace HelloWorld\Plugins;
class Foo extends \Swiftlet\Abstracts\Plugin
{
public function actionAfter()
{
// Overwrite our previously set "helloWorld" variable
$this->view->helloWorld = 'Hi world!';
}
}
This plugin implements the core actionAfter
hook and changes the view
variable helloWorld
from our previous example to Hi world!
.
Plugins don't need to be installed or activated, all files in the
vendor/HelloWorld/Plugins/
directory are automatically included and their classes
instantiated. Plugins are hooked in alphabetical order.
The core hooks are:
-
actionBefore
Called before each action -
actionAfter
Called after each action
Reusable components such as code to send an email or generate a thumbnail image should go in a separate library class.
<?php
$email = $this->app->getLibrary('email');
$email->send($to, $subject, $message);
No configuration is needed to run Swiftlet. If you're writing a model that
does require configuration, e.g. credentials to establish a database connection,
you may use the application's setConfig
and getConfig
methods:
<?php
$this->app->setConfig('variable', 'value');
$value = $this->app->getConfig('variable');
Values can be set in config/main.php
or a custom file.
Application Swiftlet\App
-
App dispatchController()
Determine which controller to use and run it -
App serve()
Serve the page -
mixed getConfig(string $variable)
Get a configuration value -
App setConfig(string $variable, mixed $value)
Set a configuration value -
Model getModel(string $modelName)
Get a model instance -
Library getLibrary(string $libraryName)
Get a library instance -
App registerHook(string $hookName, array $params)
Register a hook
View Swiftlet\View
-
mixed get(string $variable [, bool $htmlEncode = true ])
Get a view variable, encoded for safe use in HTML by default -
View set(string $variable [, mixed $value ])
Set a view variable -
mixed get(string $variable [, bool $htmlEncode ])
Get a view variable, passfalse
as the second parameter to prevent values from being HTML encoded. -
string getRootPath()
Absolute client-side path to the website root -
mixed htmlEncode(mixed $value)
Recursively make a value safe for HTML -
mixed htmlDecode(mixed $value)
Recursively decode a previously encoded value to be rendered as HTML -
View render(string $path)
Render the view