Module 1: PHP Foundations
Modern PHP: Not Your 2005 PHP
PHP has a reputation problem. Many developers formed their opinion of it years ago, when a typical PHP project was a folder of files that mixed HTML, database queries and business rules on the same page. That style still exists in old code, but the language and its ecosystem have changed a great deal. Modern PHP is fast, has a real type system, strong object-oriented features and a mature package manager. It powers content systems, online shops, payment back ends and internal business tools around the world, including many systems built by Nairobi agencies and start-ups. Knowing what modern PHP looks like helps you write code that is easy to maintain, and helps you recognise outdated advice when you see it online.
What changed and why it matters
The biggest shift came with the PHP 7 series, which brought a large performance improvement and scalar type declarations. The PHP 8 series then added features that make code clearer and safer. The ones you will use every day are:
- Type declarations for parameters, return values and class properties, so mistakes are caught early instead of silently producing wrong results.
- Constructor property promotion, which removes repetitive boilerplate in classes.
- Named arguments, which make long function calls readable.
- The
matchexpression, a stricter and more compact alternative toswitch. - The nullsafe operator
?->, which shortens chains of null checks. - Enums and readonly properties, which let you model fixed sets of values and immutable data properly.
Alongside the language, the ecosystem matured. Composer became the standard way to install libraries, the PHP-FIG group published shared standards such as PSR-4 autoloading and PSR-12 coding style, and frameworks such as Laravel and Symfony gave teams a consistent structure. Always check the official PHP website for which versions currently receive security support, and use a supported version for any new project.
Old style versus modern style
Here is the kind of code you may still find in older projects. It fetches an order and prints a status label:
<?php
$id = $_GET['id'];
$result = mysql_query("SELECT * FROM orders WHERE id = $id");
$row = mysql_fetch_assoc($result);
if ($row['status'] == 1) { echo "Paid"; }
else if ($row['status'] == 2) { echo "Shipped"; }
else { echo "Pending"; }
This has several problems. The mysql_* functions were removed from PHP long ago, the query is open to SQL injection because user input goes straight into the SQL string, the status values are unexplained numbers, and data access is mixed with output. A modern version separates concerns and uses types:
<?php
declare(strict_types=1);
enum OrderStatus: int
{
case Pending = 0;
case Paid = 1;
case Shipped = 2;
public function label(): string
{
return match ($this) {
self::Pending => 'Pending',
self::Paid => 'Paid',
self::Shipped => 'Shipped',
};
}
}
function findOrderStatus(PDO $db, int $orderId): ?OrderStatus
{
$stmt = $db->prepare('SELECT status FROM orders WHERE id = :id');
$stmt->execute(['id' => $orderId]);
$value = $stmt->fetchColumn();
return $value === false ? null : OrderStatus::from((int) $value);
}
echo findOrderStatus($db, 42)?->label() ?? 'Order not found';
The prepared statement keeps user input out of the SQL text. The enum gives each status a name. The function has a clear contract: it takes a database connection and an integer, and returns either an OrderStatus or null. The nullsafe operator and the null coalescing operator ?? handle a missing order in one readable line.
How a modern PHP project is organised
A typical modern project has a composer.json file listing its dependencies, a vendor folder that Composer manages for you, a src or app folder for your classes, a public folder that is the only directory the web server exposes, and a tests folder. Configuration secrets such as database passwords live in environment variables or a .env file that is never committed to version control. Laravel follows exactly this pattern, so learning it now will make the rest of the course feel familiar.
Common mistakes to avoid
- Copying tutorials that use removed functions such as
mysql_query. If a guide uses them, look for a more recent source. - Building SQL strings by joining user input. Always use prepared statements or an ORM.
- Leaving off
declare(strict_types=1);in plain PHP files, which lets PHP quietly convert types in ways that hide bugs. - Placing the whole project inside the web root, which can expose configuration files to the public.
- Running an unsupported PHP version on a production server because "it still works". Unsupported versions stop receiving security fixes.
In the rest of this module you will build on these ideas: the syntax and type system, object-oriented programming, and Composer. Together they are the foundation Laravel is built on.
Exercise
Install a currently supported PHP version on your computer and run php -v in a terminal to confirm it. Create a file called status.php containing the OrderStatus enum from this lesson, then add a fourth case called Cancelled and update the label method. Run it with php status.php after adding a line that echoes OrderStatus::from(1)->label(), and confirm it prints Paid.
Key points
- Modern PHP has a real type system, enums, match expressions and readonly properties.
- Prepared statements, not string building, keep user input out of SQL.
- A modern project uses Composer, a public web root and secrets kept outside version control.
- Always run a PHP version that still receives official security support.