Part I — A New Kind of Learner

Chapter 3

Reading Code You Didn't Write

The skill that separates developers who grow quickly from those who stay stuck — and why it matters more than ever in the AI era.

There's a skill that separates developers who grow quickly from those who stay stuck — and it has nothing to do with how fast you type or how many languages you know. It's the ability to sit down with a piece of code you've never seen before and figure out what it does.

In the AI era, this skill is more important than ever. When you ask an AI assistant to generate code, you'll get back something that works — but that you didn't write. If you can't read it, you're in trouble the moment it needs to change. And it will need to change.

This chapter is a guided practice session in reading code. We're going to take the Laravel application you installed in Chapter 2 and trace what happens from the moment a browser makes a request all the way to the HTML that appears on screen. We'll read every file involved, line by line. By the end, you'll have a technique for reading any unfamiliar code — and you'll understand one of the most important patterns in all of web development.

How to Read Code: A Technique

Most beginners read code the way they read a novel — top to bottom, starting at line one and hoping it makes sense by the end. That doesn't work. Code has a different structure than prose. Functions are defined before they're used, files import each other in non-obvious ways, and the 'start' of execution is often not at the top of the file.

Here's a technique that works much better. Think of it as detective work rather than reading.

The four questions

When you encounter any unfamiliar piece of code, ask these four questions in order:

  1. What is the entry point? Where does execution start?
  2. What is the expected output or effect? What should this code produce?
  3. What are the key steps between input and output?
  4. What don't I understand yet? What's a question to ask AI?

You don't need to understand every line before moving to the next question. The goal is to build a rough map first, then fill in the details.

We're going to apply this technique to a real Laravel request right now. But first, let's make sure you understand what actually happens when a browser asks for a webpage.

What Happens When You Visit a URL

When you type http://127.0.0.1:8000 into your browser and press Enter, a sequence of events begins. Understanding this sequence is the foundation of all web development — framework or no framework.

Step 1: The browser sends an HTTP request

Your browser sends a message to the server saying, in effect: 'I want the resource at the path /, using the GET method.' This message is called an HTTP request. Every interaction with a web server starts with one.

Step 2: The server receives the request

In our case, 'the server' is the php artisan serve process running in your terminal. It receives the request and hands it to PHP.

Step 3: PHP loads Laravel

PHP starts at a single file: public/index.php. This is the entry point for every single request in a Laravel application — no matter what URL is requested, every request flows through this one file first.

Step 4: Laravel routes the request

Laravel looks at the URL and the HTTP method (GET, POST, etc.) and finds the matching rule in your routes files. This process is called routing.

Step 5: A controller or closure runs

The matched route tells Laravel what code to run — either a function defined inline, or a method in a controller class. That code does whatever the feature requires: querying a database, processing data, whatever is needed.

Step 6: A view is returned

The code returns a response — usually an HTML page built from a template. Laravel sends this back to the browser, which renders it on screen.

This pattern has a name

What you just read is a description of the MVC pattern — Model, View, Controller. It's one of the oldest and most widely-used patterns in web development.

  • Model: the data layer (databases, business logic)
  • View: the presentation layer (HTML templates)
  • Controller: the glue (receives requests, talks to models, returns views)

Laravel is built around MVC. You'll hear this term constantly. When you see it, just remember: it's a description of how a request flows through your application.

Tracing a Request Through Laravel

Let's apply this to the actual files in your project. We're going to trace exactly what happens when you visit http://127.0.0.1:8000 — the homepage you saw in Chapter 2.

File 1: public/index.php

Open public/index.php. This is the entry point — the very first PHP file that runs for every request. Let's read it together.

<?php

use Illuminate\Foundation\Application;

define('LARAVEL_START', microtime(true)); // Records the start time (for performance measuring)

if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) { // Checks if app is in maintenance mode
    require $maintenance;
}

require __DIR__.'/../vendor/autoload.php'; // Loads ALL Composer packages in one shot

$app = require_once __DIR__.'/../bootstrap/app.php'; // Creates the Laravel application instance

$app->handleRequest(Request::capture()); // Hands the HTTP request to Laravel to process

Notice how short this file is. That's intentional — it does almost nothing itself. Its job is to bootstrap the framework and hand off control. The real work happens deeper in Laravel's code.

The most important line is the last one. Request::capture() reads the incoming HTTP request from PHP's superglobals ($_GET, $_POST, headers, etc.) and wraps it in a clean Laravel object. Then handleRequest() takes that object and runs it through the entire framework.

Try this prompt

I'm looking at public/index.php in a Laravel project. Can you explain what 'vendor/autoload.php' does in plain terms, and why loading it with a single require line gives us access to every Composer package?

File 2: routes/web.php

After the framework boots, Laravel looks at the incoming URL and method to find a matching route. Open routes/web.php.

<?php

use Illuminate\Support\Facades\Route; // Imports the Route class so we can use it below

Route::get('/', function () { // Register a route: GET requests to '/' run this function
    return view('welcome'); // Return the 'welcome' view (a Blade template)
});

This file is beautifully simple. It says: when someone makes a GET request to the root path (/), run this anonymous function. That function returns a view called 'welcome'.

Two things worth understanding here. First, Route::get is what's called a static method call — the double colon (::) is PHP's way of calling a method directly on a class rather than on an instance of that class. Second, view('welcome') is a Laravel helper function that finds and renders a template file. But which file, exactly?

How Laravel finds a view

When you call view('welcome'), Laravel looks for a file called welcome.blade.php inside the resources/views/ folder.

The .blade.php extension tells Laravel to process the file through its Blade templating engine before sending it to the browser. If you called view('emails.welcome'), Laravel would look for resources/views/emails/welcome.blade.php — dots become folder separators.

This naming convention is consistent across all of Laravel. Once you know it, you'll always know where to find any view.

File 3: resources/views/welcome.blade.php

Open resources/views/welcome.blade.php. This is the template that generates the HTML you see in the browser. It's longer than the other files we've read — a mix of HTML and some Blade-specific syntax.

Don't try to understand every line right now. Instead, apply the four questions. What's the entry point? The top of the file. What's the output? An HTML page. What are the key steps? The template mixes static HTML with some dynamic pieces. What don't you understand? Let's find out.

Look for lines that look like this:

@if(Route::has('login'))
    @
@endif

That @@ symbol at the start of a line means it's a Blade directive — a special instruction that Laravel processes before the HTML is sent to the browser. The @if / @endif pair works just like an if statement in PHP. The {{ }} double curly braces print a value. The @ syntax is a Blade comment — it never appears in the final HTML.

Try this prompt

I'm reading resources/views/welcome.blade.php in a new Laravel project. Can you explain the difference between @{{ }}, {!! !!}, and @if in Blade templates, and when I would use each one?

After reading this template, you've now traced a complete request from browser to HTML. You started at public/index.php, followed the route definition in routes/web.php, and arrived at the Blade template in resources/views/. That's the full journey.

Reading AI-Generated Code: A Worked Example

Now let's practice the same skill on code we ask AI to generate — because that's the situation you'll be in constantly throughout this book and beyond.

We're going to ask AI to create a simple new page in our Laravel app, then read every line of what it gives us.

Try this prompt

I have a fresh Laravel application. Can you show me how to add a new page at the URL /about that displays a simple 'About Us' page? Please give me: the route to add to web.php, and the Blade view file to create. Keep it simple — just basic HTML, no styling needed.

When you run that prompt, you'll get something like the following. Read through it before you copy anything into your project.

routes/web.php addition

// In routes/web.php, add:
Route::get('/about', function () {
    return view('about');
});

resources/views/about.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>About Us</title>
</head>
<body>
    <h1>About Us</h1>
    <p>Welcome to our about page.</p>
</body>
</html>

Before you add this to your project, ask yourself the four questions. The entry point is the route definition — that's where Laravel starts when someone visits /about. The expected output is an HTML page with a heading and paragraph. The key steps are: route matches, anonymous function runs, view() finds about.blade.php, Blade renders it, HTML is returned. What don't you understand? Let's dig into one potential question.

You might wonder: why does the view file need the .blade.php extension if we only pass 'about' to view()? And why is it .blade.php and not just .php? These are exactly the kind of questions to ask.

Try this prompt

In Laravel, when I call view('about'), why does the actual file need to be named 'about.blade.php' rather than just 'about.php'? What would happen if I named it 'about.php' instead? What does Blade actually do to the file?

Go ahead — add the route and create the view file, then visit http://127.0.0.1:8000/about. You should see your new About page. You just added a page to a web application. Notice how the process felt: you read the code before you ran it, you understood what it was doing, and you had questions ready for the parts that weren't clear.

Recognising Patterns, Not Memorising Syntax

Here's something experienced developers know that beginners often don't: you're never expected to remember exact syntax. Even developers with twenty years of experience look things up constantly. What changes with experience isn't memory — it's pattern recognition.

When a senior developer reads code, they're not processing it character by character. They're seeing familiar shapes: 'that's a route definition,' 'that's a Blade loop,' 'that's an Eloquent query.' The details vary, but the pattern is immediately recognisable.

Your goal as a beginner isn't to memorise Laravel's API. It's to build up a library of patterns — common structures you've seen enough times that they feel familiar. Reading code, even code you didn't write, is the fastest way to build that library.

Patterns to start recognising in Laravel

Route definitions: Route::get('/path', ...) Returning a view: return view('template-name'); Blade output: {{ $variable }} Blade conditionals: @if ... @else ... @endif Blade loops: @foreach($items as $item) ... @endforeach Blade comments: @

You'll see each of these dozens of times throughout this book. Don't try to memorise them now — just notice when you see them.

When You Don't Understand a Line: A Decision Tree

Not understanding a line of code is the normal state of affairs for any developer reading unfamiliar code. What separates good developers from frustrated ones is having a reliable process for resolving that confusion.

Here's the decision tree to follow when you hit a line you don't understand:

The understanding ladder

  1. Read it again, slowly. Sometimes a second pass is all it takes. Look at the punctuation as carefully as the words.
  2. Read what's around it. Code rarely makes sense in isolation. The lines above and below often provide context.
  3. Look up the function name. If you see a function call you don't recognise (like array_map or collect), look it up in the PHP or Laravel docs. A two-sentence description is usually enough.
  4. Ask AI. Paste the specific line or block with its surrounding context and ask: 'Can you explain what this code is doing, line by line?' Be specific about which part confuses you.
  5. Move on with a note. If you still don't fully understand it, that's okay. Write a comment or a note: '? — don't fully understand this yet.' Come back to it later. Blocking on one line indefinitely is the enemy of progress.

The most important thing on that list is step five. Give yourself permission to not understand everything immediately. Understanding comes in layers — you'll revisit the same concepts many times throughout this book, and each pass will add depth.

Watch out

A specific trap to avoid: asking AI to just rewrite something you don't understand with 'simpler' code. This often produces functionally identical code with different syntax — and you've learned nothing.

Instead, ask AI to explain the existing code. 'Can you explain what this specific line does?' is almost always more valuable than 'Can you simplify this?'

Building Your Reading Habit

Reading code is a skill, and like all skills it improves with deliberate practice. Here's a habit worth building right now, before you move further into the book.

Every time you add something to your project — whether you wrote it or AI generated it — read it fully before you run it. Not skimming, not just making sure it compiles. Read it the way you'd read a short document you're about to sign. What does every significant line do? What are the inputs? What are the outputs? What could go wrong?

This habit will feel slow at first. It will get faster very quickly. And it will save you an enormous amount of debugging time, because you'll catch mistakes and misunderstandings before they become running code.

A reading checklist for AI-generated code

Before accepting any code from an AI assistant, run through this mentally:

  • [ ] Do I understand what each significant line is doing?
  • [ ] Does this code do what I actually asked for?
  • [ ] Are there any lines I don't understand at all? (Flag them.)
  • [ ] Does anything look dangerous? (Deleting data, ignoring errors, exposing user input?)
  • [ ] Can I explain this code to someone else in plain English?

That last question is the most powerful test. If you can explain it, you understand it. If you can't, you don't yet.

What You've Learned to See

You've covered a lot of ground in this chapter — not just Laravel specifics, but a way of thinking about code that will serve you for your entire career. Let's take stock.

You now know that every Laravel request flows through public/index.php, then through a matching route definition, then through whatever code the route points to, then (usually) through a Blade template. That's the backbone of almost every page in every Laravel application you'll ever build.

You have a technique — the four questions — for approaching any unfamiliar code. You have a decision tree for when you don't understand a line. And you have a checklist for evaluating code that comes from AI.

Most importantly, you've practiced the core habit: reading before running. It feels slightly unnatural at first, especially when you just want to see something work. But it's the single most effective way to learn, and it's the habit that separates developers who grow quickly from those who stay stuck copying and pasting forever.

In the next chapter, we leave the framework scaffold behind and dive into PHP itself. We'll start building a genuine mental model of the language — variables, types, control flow — using the generate-read-modify-break-fix loop we introduced in Chapter 1.

✦ Exercises

  1. Trace the request for the /about page you created. Open each of the three files involved (public/index.php, routes/web.php, resources/views/about.blade.php) and write a one-sentence description of what each file's job is in your own words.
  2. Ask your AI assistant to add a second route to your application — a /contact page that displays a name and an email address stored in PHP variables passed from the route to the view. Before you copy any code into your project, read all of it and apply the four questions. Only add it once you can describe what every line does.
  3. Open resources/views/welcome.blade.php and find a Blade directive you haven't seen before (something starting with @@). Look it up in the Laravel documentation at laravel.com/docs, then ask AI to explain it with an example. Write a one-sentence explanation in a code comment above the line.
  4. Take the /about view you created and intentionally introduce a Blade syntax error — for example, open an @if without an @endif. Observe the error Laravel shows you. Read the error message carefully: what file does it name? What line number? What does the message say? Now fix it.
  5. Ask your AI assistant: 'In Laravel, what is the difference between a route that returns a view directly and a route that calls a controller method? When would I use one versus the other?' Keep this answer — it will make Chapter 9 much easier.

Next up: Chapter 4 — Variables, Types, and Control Flow

Previous: Chapter 2 Chapter 4 coming soon