GitHub - alvarotala/phpLightMVC: A simple PHP web framework.

# phpLightMVC

A lightweight, MVC-based PHP framework inspired by Ruby on Rails. phpLightMVC provides a simple yet powerful structure for building web applications with minimal configuration.

## Features

- **MVC Architecture**: Clean separation of concerns with Models, Views, and Controllers
- **Flexible Routing**: Powerful URL routing system with support for custom routes, parameters, and optional segments
- **ActiveRecord ORM**: Built-in PHP ActiveRecord implementation supporting MySQL, PostgreSQL, SQLite, and Oracle
- **Helper Classes**: Rich set of utility classes for common tasks (String, Session, Cookie, Flash, Template, Upload, Crypto, etc.)
- **View Rendering**: Automatic view rendering with support for custom templates and layouts
- **Before Filters**: Controller callbacks for authentication and authorization
- **Flash Messages**: Built-in flash message system for user notifications
- **Email Support**: SMTP email sending with HTML template support
- **URL Rewriting**: Works with or without mod_rewrite

## Requirements

- PHP 5.3 or higher
- Apache with mod_rewrite (optional, but recommended)
- MySQL, PostgreSQL, SQLite, or Oracle database

## Installation

1. Clone or download this repository to your web server directory
2. Configure your web server to point to the `public` directory as the document root
3. Copy the example environment file:
   ```bash
   cp .env.example .env
   ```
4. Edit `.env` to configure your settings:
   - Database credentials
   - Site domain and paths
   - Email SMTP settings
   - Security vault key


## Project Structure

```
phpLightMVC/
├── app/                    # Application code
│   ├── controllers/        # Controller classes
│   │   ├── application_controller.php  # Base controller
│   │   └── example_controller.php     # Example controller
│   ├── models/            # Model classes (ActiveRecord)
│   │   └── Example.php
│   ├── views/             # View templates
│   │   ├── example/       # Views for example controller
│   │   ├── mails/         # Email templates
│   │   └── templates/     # Shared templates/layouts
│   └── helpers/           # Helper classes
├── core/                  # Framework core
│   ├── boot.php           # Bootstrap file
│   ├── config.php         # Configuration
│   ├── routes.php         # Route definitions
│   └── libs/              # Framework libraries
│       ├── framework/     # MVC framework classes
│       ├── classes/       # Utility classes
│       └── active_record/ # ORM implementation
└── public/                # Public web root
    ├── index.php          # Entry point
    └── .htaccess          # URL rewriting rules
```

## Configuration

Configuration is managed via environment variables in the `.env` file.

```ini
APP_ENV=development
APP_DEBUG=true
APP_URL=http://localhost/path/to/public

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=root
DB_PASSWORD=

SMTP_HOST=smtp.host.com
SMTP_PORT=25

SECURITY_VAULT=__your_secret_key_here__
```


## Routing

Routes are defined in `core/routes.php`. The framework supports flexible URL patterns:

```php
// Simple route
$map->connect("/", array('controller' => 'example', 'action' => 'index'));

// Route with parameter
$map->connect("/example/show/:id", array('controller' => 'example', 'action' => 'show'));

// Route with multiple parameters
$map->connect("/mostrar/:id/otra/:other", array('controller' => 'example', 'action' => 'show'));

// Route with wildcard
$map->connect("/mostrar_otro/:id/:other/*", array('controller' => 'example', 'action' => 'show'));

// Custom route
$map->connect("/login", array('controller' => 'example', 'action' => 'login'));

// Default catch-all route (must be last)
$map->connect(":controller/:action/*");
```

### Route Parameters

- `:variable` - Captures a URL segment as a parameter
- `*array` - Captures multiple segments as an array
- Parameters are available in controllers via `$this->params['get']['variable']`

## Controllers

Controllers extend `ApplicationController` (which extends `ActionController`). They handle requests and prepare data for views.

### Creating a Controller

Create a new file in `app/controllers/` named `your_name_controller.php`:

```php
<?php
class YourNameController extends ApplicationController {
    
    // Before filter - runs before every action
    protected function before_filter() {
        parent::before_filter();
        // Your code here
    }
    
    // Action method
    function index() {
        $this->variable_name = "Hello World";
        // Variables assigned to $this are available in views
    }
    
    // Action with parameters
    function show() {
        $id = $this->params['get']['id'];
        $this->item = Example::find($id);
    }
    
    // Redirect
    function create() {
        // ... save data ...
        $this->redirect(WWW_PATH . '/example/index');
    }
    
    // Custom render (no view)
    function api() {
        $this->render(json_encode($data), 'application/json');
    }
    
    // Disable view rendering
    function ajax() {
        $this->render(false);
        echo json_encode($data);
    }
}
?>
```

### Controller Methods

- `$this->params` - Access route and query parameters
- `$this->render($content, $content_type)` - Custom rendering
- `$this->redirect($url)` - Redirect to another URL
- `$this->notice($message)` - Set flash notice message
- `$this->error($message)` - Set flash error message
- `$this->ajax($status, $data)` - Return JSON response

## Models

Models use PHP ActiveRecord. They extend `ActiveRecord\Model` and provide an ORM interface to your database.

### Creating a Model

Create a new file in `app/models/` named `YourModel.php`:

```php
<?php
class YourModel extends ActiveRecord\Model {
    
    static $table_name = 'your_table_name';
    
    // Define relationships
    static $has_many = array(
        array('comments')
    );
    
    static $belongs_to = array(
        array('user')
    );
    
    // Validations
    static $validates_presence_of = array(
        array('name'),
        array('email')
    );
}
?>
```

### ActiveRecord Usage

```php
// Find records
$user = User::find(1);
$users = User::all();
$user = User::find_by_email('user@example.com');

// Create
$user = new User();
$user->name = 'John';
$user->email = 'john@example.com';
$user->save();

// Update
$user = User::find(1);
$user->name = 'Jane';
$user->save();

// Delete
$user = User::find(1);
$user->delete();

// Query
$users = User::find('all', array('conditions' => array('active = ?', 1)));
```

For more ActiveRecord features, see the [PHP ActiveRecord documentation](http://www.phpactiverecord.org/).

## Views

Views are PHP files located in `app/views/{controller}/{action}.php`. Variables assigned in controllers are available via `$this->variable_name`.

### Example View

```php
<!DOCTYPE html>
<html>
<head>
    <title><?= SITE_NAME ?></title>
</head>
<body>
    <h1><?= $this->variable_name ?></h1>
    
    <?php if (isset($this->items)): ?>
        <?php foreach ($this->items as $item): ?>
            <p><?= $item->name ?></p>
        <?php endforeach; ?>
    <?php endif; ?>
    
    <?php Flash::show() ?>
</body>
</html>
```

### Templates

Load shared templates:

```php
<?php Template::load('template_name.php'); ?>
```

### Flash Messages

Display flash messages in views:

```php
<?php Flash::show() ?>
```

## Helper Classes

The framework includes several utility classes:

### String

```php
String::camelize('hello_world');      // 'HelloWorld'
String::underscore('HelloWorld');     // 'hello_world'
String::humanize('hello_world');      // 'Hello World'
String::sub('Long text', 10);         // 'Long text...'
String::url('Hello World');           // 'hello-world'
String::pr($array);                   // Pretty print array
```

### Session

```php
Session::set('key', 'value');
$value = Session::get('key');
Session::delete('key');
Session::clear();
```

### Cookie

```php
Cookie::set('key', 'value', 3600);
$value = Cookie::get('key');
Cookie::delete('key');
```

### Flash

```php
Flash::notice('Success message');
Flash::error('Error message');
Flash::show(); // Display in view
```

### Template

```php
$tmpl = Template::mail('email_template.php');
$tmpl->replace(array('name' => 'John'));
$html = $tmpl->render();
```

### Sendmail

```php
Sendmail::send(array(
    'to' => 'user@example.com',
    'subject' => 'Hello',
    'body' => $html_body
));
```

### Upload

```php
$upload = new Upload();
$upload->handle('file_field_name');
if ($upload->is_valid()) {
    $upload->save('/path/to/destination');
}
```

### Crypto

```php
```php
$hash = Crypto::md5('password'); // Returns secure hash (bcrypt/argon2)
$verify = Crypto::verify('password', $hash); // Returns true/false
$token = Crypto::random_str(32); // Returns secure random string
```
```

## URL Rewriting

### With mod_rewrite (Recommended)

The `.htaccess` file in `public/` handles URL rewriting. URLs work like:
- `/example/index`
- `/example/show/1`

### Without mod_rewrite

If mod_rewrite is not available, use query parameters:
- `/?url=/example/index`
- `/?url=/example/show/1`

## Examples

See `app/controllers/example_controller.php` and `app/views/example/` for complete examples of:
- Basic controller actions
- Before filters
- Redirects
- Custom rendering
- AJAX responses
- Flash messages
- View rendering

## Author

**Alvaro Talavera** (alvarotala@gmail.com)

## License

This framework is provided as-is for educational and development purposes.

## Notes

- The framework uses PHP short tags (`<?`). Ensure your PHP configuration has `short_open_tag = On` or convert to full tags (`<?php`)
- Error reporting is configured in `core/config.php` - adjust for production
- The ActiveRecord library is based on the PHP ActiveRecord project
- Router implementation includes code inspired by the Akelos Framework