The Goal: From Static Data to Real Data
Currently, our controller "hard-codes" the data it sends to the view (['name' => 'StartWithSite Learner']
). This isn't practical for a real application. It's time to introduce the Model, the 'M' in MVC. The Model's only job is to talk to the database. The Controller will ask the Model for data, and the Model will handle all the SQL queries and return the results.
Step 1: The Dependency Container (A Simple Registry)
To make our database connection available to our models without using messy global variables, we'll create a tiny "Dependency Container" or "Registry". It's a simple class that will hold our database connection object and anything else we might want to share across the application.
Create a new file: app/Core/App.php
<?php
namespace App\Core;
class App
{
protected static $registry = [];
public static function bind($key, $value)
{
static::$registry[$key] = $value;
}
public static function get($key)
{
if (! array_key_exists($key, static::$registry)) {
throw new \Exception("No {$key} is bound in the container.");
}
return static::$registry[$key];
}
}
Step 2: The Base Model
Next, we'll create a BaseModel
. All of our future models (like Post, User, etc.) will extend this class. Its main job is to get the database connection from our new App container.
Create a new file: app/Core/Model.php
<?php
namespace App\Core;
class Model
{
protected $pdo;
public function __construct()
{
$this->pdo = App::get('database');
}
}
Step 3: Creating the Post Model
Now for the exciting part! Let's create a Post
model that knows how to fetch posts from your database. It will extend our BaseModel
to get the database connection automatically.
Create a new file: app/Models/Post.php
<?php
namespace App\Models;
use App\Core\Model;
class Post extends Model
{
/**
* Fetch all posts from the database.
*/
public function fetchAll()
{
$stmt = $this->pdo->query("SELECT title, content FROM posts ORDER BY created_at DESC LIMIT 5");
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
}
Step 4: Bootstrapping the Application
We need to tell our application how to connect to the database. We will do this once in our main entry point, public/index.php
. This process of setting up the core services is called "bootstrapping".
Update your file: public/index.php
<?php
// This is the single entry point for our entire application.
// Load the main configuration file, which creates the $pdo object.
require_once __DIR__ . '/../config.php';
// Load the Composer autoloader.
require_once __DIR__ . '/../vendor/autoload.php';
use App\Core\Router;
use App\Core\App;
// Bind the database connection into our App container.
// Now, any part of our app can access it via App::get('database').
App::bind('database', $pdo);
// Create a new Router instance
$router = new Router();
// Register our routes
$router->add('/', 'HomeController', 'index');
// Dispatch the router to handle the current request
$router->dispatch();
Step 5: Updating the Controller to Use the Model
Now, we'll change our HomeController
to use the Post
model to fetch real data and pass it to the view.
Update your file: app/Controllers/HomeController.php
<?php
namespace App\Controllers;
use App\Models\Post;
class HomeController
{
public function index()
{
// 1. Create an instance of our Post model.
$postModel = new Post();
// 2. Fetch all posts from the database.
$posts = $postModel->fetchAll();
// 3. Pass the fetched posts to the view.
view('home', [
'posts' => $posts
]);
}
}
Step 6: Updating the View to Display the Posts
Finally, let's update our home.view.php
to loop through the $posts
array and display the titles.
Update your file: views/home.view.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to Our Framework</title>
<style>
body { font-family: sans-serif; background-color: #f0f2f5; margin: 0; padding: 20px; }
.container { max-width: 800px; margin: 40px auto; background: white; padding: 40px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); }
h1 { color: #333; }
ul { list-style: none; padding: 0; }
li { background: #f8f9fa; margin-bottom: 10px; padding: 15px; border-radius: 5px; border-left: 3px solid #007bff; }
</style>
</head>
<body>
<div class="container">
<h1>Latest Blog Posts</h1>
<p>This data is being fetched live from your database!</p>
<ul>
<?php foreach ($posts as $post): ?>
<li><?php echo htmlspecialchars($post['title']); ?></li>
<?php endforeach; ?>
</ul>
</div>
</body>
</html>
Your Mission
- Create the new files:
app/Core/App.php
andapp/Core/Model.php
. - Create the new model file:
app/Models/Post.php
. - Update the bootstrap file:
public/index.php
. - Update the controller:
app/Controllers/HomeController.php
. - Update the view:
views/home.view.php
. - Visit your project homepage. You should now see a list of the 5 most recent post titles from your actual database!
Congratulations! Your MVC framework is now fully connected to your database and displaying dynamic content.