When developing a custom PHP framework for building applications such as a CMS, CRM, or eCommerce platform, you might not want to reinvent the wheel for every feature. Instead of building everything from scratch, a great approach is to leverage existing components from widely-used PHP frameworks. By combining components from Symfony, Laravel, and Nette, you can create a powerful, modular framework that offers flexibility and scalability, while still being lightweight and customizable.
In this blog, we’ll walk through how to build a Modular PHP Framework using key components from these frameworks. We will focus on:
- Database interaction using Laravel’s Eloquent ORM
- Form handling using Nette Forms
- Routing and HTTP response handling using Symfony’s HTTP Foundation
By the end of this tutorial, you’ll have an MVP (Minimum Viable Product) for a modular framework that can be expanded into a CMS, CRM, or eCommerce system.
Prerequisites
Before we get started, make sure you have the following installed:
- PHP 7.4+
- Composer (for dependency management)
- MySQL or SQLite (for the database)
Let’s begin by setting up our project and installing the necessary dependencies.
Step 1: Set Up the Project
1.1. Create the Project Directory
Create a new directory for your project and initialize it with Composer:
mkdir my-php-framework
cd my-php-framework
composer init
1.2. Install the Required Components
Next, we need to install the components from Symfony, Laravel, and Nette:
composer require symfony/http-foundation symfony/routing symfony/validator symfony/twig
composer require illuminate/database nette/forms
This command will install the Symfony HttpFoundation (for handling HTTP requests and responses), Symfony Routing (for routing), Laravel Eloquent ORM (for database interaction), and Nette Forms (for form handling).
Step 2: Create the Project Structure
Now, let’s set up a basic folder structure for the project:
/my-php-framework
/src
/Core
/Component
/Cms
/Crm
/Commerce
/Database
/Form
/Http
/Routing
/templates
/public
/config
/vendor
composer.json
This structure will help keep your project modular and organized, with separate directories for each key feature (Database, Form, HTTP, Routing, etc.).
Step 3: Database Interaction with Laravel’s Eloquent ORM
We will use Laravel’s Eloquent ORM to interact with the database. Eloquent provides an elegant way to query the database using PHP objects, making it easier to interact with database tables.
3.1. Configure the Database
Create a file for database configuration (config/config.php
):
// config/config.php
return [
'database' => [
'driver' => 'mysql',
'host' => '127.0.0.1',
'database' => 'your_db_name',
'username' => 'root',
'password' => '',
]
];
3.2. Set Up the Database Class
Now, set up a Database
class to initialize Eloquent:
// src/Core/Database/Database.php
namespace Core\Database;
use Illuminate\Database\Capsule\Manager as Capsule;
class Database
{
public function __construct(array $config)
{
$capsule = new Capsule;
// Set up the Eloquent ORM configuration
$capsule->addConnection($config);
// Make the Capsule instance available globally via static methods
$capsule->setAsGlobal();
// Boot Eloquent ORM
$capsule->bootEloquent();
}
}
3.3. Initialize Eloquent
In the public/index.php
file, include the configuration and initialize the database:
// public/index.php
require '../vendor/autoload.php';
use Core\Database\Database;
$config = include('../config/config.php');
// Initialize the database connection
$database = new Database($config['database']);
// Now you can interact with the database using Eloquent models (e.g., User, Post, etc.)
Step 4: Form Handling with Nette Forms
Nette Forms provide a powerful form-building component, which will allow us to handle form submission and validation with ease.
4.1. Create a Form Factory Class
Let’s create a simple form with two fields: name
and email
.
// src/Core/Form/FormFactory.php
namespace Core\Form;
use Nette\Forms\Form;
class FormFactory
{
public function createForm()
{
$form = new Form;
$form->addText('name', 'Name:')
->setRequired('Please enter your name.');
$form->addEmail('email', 'Email:')
->setRequired('Please enter a valid email address.');
$form->addSubmit('send', 'Submit');
return $form;
}
}
4.2. Handle the Form in the Controller
Now, let’s integrate the form into our main application logic. In the public/index.php
file, we’ll handle the form submission:
// public/index.php
require '../vendor/autoload.php';
use Core\Form\FormFactory;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$formFactory = new \Core\Form\FormFactory();
$form = $formFactory->createForm();
$form->handleRequest($request->request->all());
if ($form->isSubmitted() && $form->isValid()) {
// Handle form submission and data
$data = $form->getData();
$response = new Response("Form submitted with: " . json_encode($data));
} else {
// Render the form
$response = new Response($form->render());
}
$response->send();
This simple form validation ensures that both the name
and email
fields are filled out correctly before the form can be submitted.
Step 5: Routing and HTTP Response with Symfony
We’ll use Symfony’s Routing Component to handle routing. This will allow us to define routes and associate them with controller actions.
5.1. Set Up a Simple Router
Create a basic router that can match routes like /
(home page) and /form
(form page):
// src/Core/Routing/Router.php
namespace Core\Routing;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
class Router
{
public function __construct()
{
$routes = new RouteCollection();
$routes->add('home', new Route('/', [
'_controller' => function() {
return 'Welcome to the home page!';
}
]));
$routes->add('form', new Route('/form', [
'_controller' => function() {
return 'This is the form page!';
}
]));
$this->matcher = new UrlMatcher($routes, new RequestContext());
}
public function match($url)
{
return $this->matcher->match($url);
}
}
5.2. Match Routes and Handle Requests
In public/index.php
, we will match the requested URL and respond accordingly:
// public/index.php
require '../vendor/autoload.php';
use Core\Routing\Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$router = new Router();
$route = $router->match($request->getPathInfo());
if ($route['controller'] === 'home') {
$response = new Response('Welcome to the home page!');
} elseif ($route['controller'] === 'form') {
$response = new Response('This is the form page!');
} else {
$response = new Response('404 Not Found', 404);
}
$response->send();
Step 6: Final Touches
6.1. Testing the Application
To run the application, use PHP’s built-in server:
php -S localhost:8000 -t public/
Visit the following URLs in your browser:
http://localhost:8000/
– The home page.http://localhost:8000/form
– The form page.
6.2. Expanding the Framework
Now that you have the basic setup working, you can easily expand it:
- Add database models: Use Eloquent models to interact with your database tables (e.g.,
User
,Product
, etc.). - Implement CRUD operations: Implement create, read, update, delete (CRUD) operations for managing records.
- Enhance routing: Add more complex routes and controllers to handle business logic for CMS, CRM, or eCommerce.
- Template rendering: Integrate a templating engine like Twig for separating logic and presentation.
Conclusion
In this tutorial, we’ve successfully built a Modular PHP Framework by combining components from Symfony, Laravel, and Nette. The framework offers a modular architecture that’s lightweight and flexible, and it can be expanded into a full CMS, CRM, or eCommerce system.
We covered:
- Database interaction with Eloquent ORM (from Laravel)
- Form handling with Nette Forms
- Routing and HTTP responses with Symfony’s HTTP Foundation
This MVP provides a solid foundation for building more complex systems, allowing you to integrate other PHP components as needed. You now have the building blocks to create a powerful and scalable PHP application.
Leave a Reply