Labo-Esi is a PHP/MySQL web application for managing a research laboratory website. It covers public laboratory pages, research projects, publications, teams, equipment reservations, events, contact messages, user dashboards, notifications, PDF reporting, and an RBAC-protected administration area.
The project intentionally uses a custom lightweight PHP mini framework instead of a full-stack framework. The framework is small, explicit, and easy to follow: one front controller, a query-string router, base MVC classes, PDO models, .phtml templates, and reusable PHP UI components.
Requests enter through public/index.php, which starts the session, loads local configuration, loads the core framework classes, loads view/component classes, and dispatches the request through Router.
The routing convention is:
public/index.php?controller=Home&action=index
public/index.php?controller=Project&action=detail&id=12
public/index.php?controller=AdminProject&action=edit&id=12
If no route is provided, the router defaults to:
controller=Home
action=index
Core framework files:
core/
Controller.php Base controller helpers: model(), view(), loadLang(), redirect(), json(), pagination
Router.php Maps controller/action query params to app/Controllers/*Controller.php
Model.php Base PDO model with shared database access
Database.php PDO singleton for MySQL
View.php Base view class and .phtml template inclusion
Component.php Base class for reusable renderable PHP UI components
- Public website pages for the laboratory homepage, presentation, projects, publications, teams, members, equipment, offers, events, and contact.
- User authentication with session-based login/logout.
- Member dashboard with profile editing, projects, publications, and reservations.
- Admin dashboard protected by permissions rather than hardcoded roles.
- User, team, project, publication, event, partner, equipment, contact, settings, and role management modules.
- Equipment reservation workflow with maintenance windows, conflict detection, urgent reservations, admin approval/rejection, and reporting stats.
- Publication submission and validation workflow.
- Event publishing, registration, reminders, and member notifications.
- Dynamic homepage/layout configuration stored in the database.
- Bilingual language files in
lang/fr.phpandlang/en.php. - PDF report generation through bundled FPDF classes.
- Native test runner without PHPUnit.
app/
Components/ Reusable PHP UI components
Controllers/ Public, dashboard, auth, and admin controllers
Helpers/ URL and date helper classes
Lib/ Bundled libraries, including FPDF and PDF report classes
Models/ PDO-backed business/data access classes
Views/
Classes/ View classes that prepare/render templates
Templates/ .phtml templates
core/ Custom mini framework
lang/ Translation arrays
public/ Front controller, CSS, JS, images, and uploads
tests/ Native transactional test suite
- PHP with PDO MySQL enabled
- MySQL or MariaDB
- A web server that can serve the
public/directory, or PHP's built-in server for local development - Existing project database schema and seed data
No composer.json is present in this repository, and the app does not require a Composer install for the committed code.
Local config is intentionally ignored by Git:
app/Config/config.php
app/Config/*.local.php
Create app/Config/config.php before running the app. A minimal local config should define the constants and helpers expected by the mini framework:
<?php
define('BASE_PATH', dirname(__DIR__, 2) . DIRECTORY_SEPARATOR);
define('BASE_URL', 'http://localhost:8000/');
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'TDW');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_CHARSET', 'utf8mb4');
define('DEFAULT_LANG', 'fr');
define('UPLOAD_PATH', BASE_PATH . 'public' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR);
define('KEY_SUCCESS', 'success');
define('KEY_ERROR', 'error');
function getCurrentLanguage(): string
{
$lang = $_GET['lang'] ?? $_SESSION['lang'] ?? DEFAULT_LANG;
$allowed = ['fr', 'en'];
if (!in_array($lang, $allowed, true)) {
$lang = DEFAULT_LANG;
}
$_SESSION['lang'] = $lang;
return $lang;
}Adjust BASE_URL, database credentials, and database name to match your environment.
From the repository root:
php -S localhost:8000 -t publicThen open:
http://localhost:8000/index.php
Example routes:
http://localhost:8000/index.php?controller=Project&action=index
http://localhost:8000/index.php?controller=Publication&action=index
http://localhost:8000/index.php?controller=Auth&action=login
http://localhost:8000/index.php?controller=Admin&action=index
For WAMP/XAMPP, point the virtual host or browser URL at the public/ directory and make sure BASE_URL matches that public URL.
The database schema is not committed in this checkout; .gitignore excludes *.sql. The code expects a MySQL database with tables for users, roles, permissions, teams, projects, publications, equipment, reservations, maintenances, events, partners, settings, notifications, contact messages, activity logs, PDF settings, and layout settings.
The admin settings module can generate database backups from an existing database through SettingsModel::generateBackupSQL().
Follow the mini-framework convention:
- Add or update a model in
app/Models, extendingModel. - Add or update a controller in
app/Controllers, extendingControllerorAdminController. - Add a view class in
app/Views/Classeswhen needed. - Add a
.phtmltemplate inapp/Views/Templates. - Add reusable UI pieces under
app/Componentswhen markup is shared. - Link to the route with
index.php?controller=Name&action=method.
For admin modules, extend AdminController so login and admin.access permission checks happen before module logic.
The project uses a native test runner, not PHPUnit. Tests run inside a database transaction and roll back at the end.
Run with a PHP CLI that has PDO MySQL enabled:
php tests/run.phpOn WAMP, the command may look like:
C:\wamp64\bin\php\php7.4.33\php.exe tests/run.phpExisting test coverage includes authentication, equipment reservations, publication logic, project queries, and RBAC permissions. See tests/README.md for details.
- Keep
public/index.phpas the only browser entry point. - Keep local secrets and database dumps out of Git.
- Store user-uploaded files under
public/uploads/; this directory is ignored. - Use
Controller::json()for AJAX responses. - Use
Controller::loadLang()andlang/*.phpfor translatable UI strings. - Use
Componentclasses for repeated UI blocks instead of duplicating template markup. - Run
php tests/run.phpafter backend changes that affect models, controllers, permissions, or reservation/publication/project logic.