For what it’s with worth(not much) I find these discussions interesting but no MVC framework that I’ve come across is even a close contender to the elegant simplicity of Rails.
So, if I were using PHP I would try to implement the conventions and methods of Rails because I think they make a lot of sense.
I’d try to implement code that looked something like this… lots of psedo code and I haven’t written php in years.
I would set up routes somewhere which map HTTP to a controller and action
routes
method url controller#action helper_method
GET /users users#index users_path
POST /users users#create users_path
GET /users/new users#new new_user_path
GET /users/:id/edit users#edit edit_user_path(user)
GET /users/:id users#show user_path(user)
POST /users/:id users#update user_path(user)
POST /users/:id/delete users#delete delete_user_path(user)
The model should contain the validations
models/user.php
class User extends ApplicationModel {
public $name = ''
public $email = ''
public function validate() {
$errors = [];
if ($this->name == '') {
$errors['name'] = 'Name cannot be blank';
}
if (!filter_var($this->$email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = 'Email is invalid';
}
return $errors
}
}
The controller should expose methods to the view to consume data as well as handling params to the actions and deciding what to do
controllers/users_controller.php
class UsersController extends ApplicationController {
// expose an api to the views
public function users {
return User.all()
}
public function user {
if (params('id')) {
return User.find(params('id'))
}
else {
$user = new User
if (params('user')) {
$user.attributes(params('user'))
}
return $user
}
}
// actions
public function create() {
if (user().save()) {
flash('success', 'User created!');
redirect_to(users_path());
}
else {
flash('error', 'Errors');
render('new');
}
}
public function update() {
if (user().save()) {
flash('success', 'User created!');
redirect_to(users_path());
}
else {
flash('error', 'Errors');
render('new');
}
}
public function delete() {
user().delete()
flash('success', 'User deleted!');
redirect_to(users_path());
}
}
The view should have access to the exposed methods of the controller and helper methods like named routes and flash
views/users/index.php
<h1>Users</h1>
<ul>
<?php foreach (users() as $user) { ?>
<li><?php echo $user.name ?></li>
<?php } ?>
</ul>
views/users/show.php
<h1><?php echo user().name ?></h1>
<p>Email: <?php echo user().email ?></p>
views/users/new.php
<h1>New User</h1>
<form action="<?php echo users_path() ?>" method="post">
<?php render('form') ?>
<input type="submit" value="Create">
</form>
views/users/edit.php
<h1>Edit User</h1>
<form action="<?php echo user_path(user()) ?>" method="post">
<?php render('form') ?>
<input type="submit" value="Update">
</form>
views/users/_form.php
<div>
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" value="<?php params('user[name]') ?>">
</div>
<div>
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" value="<?php params('user[email]') ?>">
</div>
I’d have an application layout which renders the views
views/layouts/application.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>untitled</title>
</head>
<body>
<?php if (flash('error')) {
<div id="error"><?php echo flash('error') ?></div>
<?php } ?>
<?php if (flash('success')) {
<div id="success"><?php echo flash('success') ?></div>
<?php } ?>
<div id="content">
<?php render_view() ?>
</div>
</body>
</html>
I’d abstract everything that you want to be able to reuse across your models controllers and views into a separate part of the app.
framework/application_model.php
class ApplicationModel {
public static function all() {
// select * from <pluralised lowercased __CLASS__>;
}
public static function find($id) {
// select * from table where id=$id;
}
public function save() {
$errors = $this->validate()
if ($errors.length == 0) {
// UPDATE table where id=$id
}
else {
return false;
}
}
public function delete() {
// DELETE FROM table where id=$id
}
public function attributes($attributes) {
foreach($attributes as $attr => $value) {
$this->$attr = $value
}
}
}
framework/application_controller.php
class ApplicationController {
public function params($key) {
// map nested params ?user[name]=mark&user[email]=markbrown4@gmail.com
// params('user') == { name: 'mark', email: 'markbrown4@gmail.com' }
// params('user[email]') == 'markbrown4@gmail.com'
}
public function redirect_to($url, $flash) {}
public function flash($key, $value) {
// set a short lived variable in session
}
public function render($view) {
// render a view from a controller
}
// 7 rest actions
public function index() {}
public function show() {}
public function new() {}
public function edit() {}
public function create() {}
public function update() {}
public function delete() {}
}
framework/application_view.php
class ApplicationView {
public function flash($key) {
}
public function render($partial) {
// render '_$partial.php'
}
public function render_view() {
}
}
I just thought this may give you some ideas to play with.