Laravel Basic Structure Overview

Laravel is one of the most popular and elegant PHP frameworks used for building modern web applications. Its expressive syntax, structured organization, and powerful built-in tools make it a favorite among developers who seek clean, maintainable, and scalable codebases.

One of the first challenges beginners face is understanding the folder structure that appears after installing Laravel. This structure may look intimidating at first, but each folder serves a clear purpose, and once you know what goes where, everything becomes easier.

In this detailed guide, we will walk through the major directories in a fresh Laravel installation, focusing on:

  • The app/ directory
  • The routes/ directory
  • The resources/ directory
  • The database/ directory

Along with explanations, we will also look at real code examples so you understand not just the theory but also practical usage.

Why Laravel’s Structure Matters

A well-organized framework ensures that developers can quickly navigate files, maintain code, and follow consistent conventions. Laravel’s philosophy emphasizes:

  • Separation of concerns
  • Clean architecture
  • Reusability
  • Readability

By understanding where your controllers, models, views, migrations, and routes live, you can start building projects with clarity and confidence.


app/ Directory – The Heart of Your Application

The app/ folder contains most of the core logic of your application. It houses:

  • Models
  • Controllers
  • Middleware
  • The application service provider
  • Custom classes you build

It is often considered the central place where business logic resides.

The directory tree looks like this:

app/
Console/
Exceptions/
Http/
    Controllers/
    Middleware/
    Requests/
Models/
Providers/

Let’s explore each subdirectory.


Models (app/Models)

Laravel uses Eloquent ORM, making database tables map directly to PHP classes called “models.”

A model represents a database table. For example, a users table corresponds to a User model.

Example Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
protected $fillable = &#91;
    'title',
    'content'
];
}

In this example:

  • The model represents a posts table.
  • The $fillable property defines which fields can be mass-assigned.

Models handle relationships, data retrieval, and database interaction.


Controllers (app/Http/Controllers)

Controllers group related request-handling logic. Instead of writing everything in routes, Laravel encourages moving logic into controllers.

A controller may look like this:

<?php

namespace App\Http\Controllers;

use App\Models\Post;

class PostController extends Controller
{
public function index()
{
    return view('posts.index', &#91;
        'posts' =&gt; Post::all()
    ]);
}
}

In this example:

  • The index() method fetches all posts and sends them to a view.
  • Controllers communicate between routes and models.

Middleware (app/Http/Middleware)

Middleware filters HTTP requests entering your application.
Examples include:

  • Authentication checks
  • Logging
  • Input trimming
  • Request redirection

Example Middleware

<?php

namespace App\Http\Middleware;

use Closure;

class CheckAdmin
{
public function handle($request, Closure $next)
{
    if (!auth()-&gt;user() || !auth()-&gt;user()-&gt;is_admin) {
        abort(403);
    }
    return $next($request);
}
}

This middleware ensures only admin users can access certain routes.


routes/ Directory – Defining Application Entry Points

The routes/ folder defines all the URLs of your application. Each route maps a URL to:

  • A controller method
  • A closure
  • A resource controller
  • An API endpoint

The folder includes multiple files:

routes/
web.php
api.php
console.php
channels.php

Let’s explore the two most common ones.


web.php – Routes for Web Pages

web.php handles browser-based routes which use sessions and cookies.

Example Route

Route::get('/posts', [PostController::class, 'index']);

This route points /posts to the controller’s index method.

Closure-Based Route

Route::get('/', function () {
return view('welcome');
});

Route with Parameters

Route::get('/posts/{id}', function ($id) {
return "Post ID: " . $id;
});

api.php – Routes for APIs

api.php is designed for stateless endpoints typically consumed by front-end clients or mobile apps.

Example:

Route::get('/posts', function () {
return \App\Models\Post::all();
});

API routes automatically apply api middleware which handles rate-limiting and removes sessions.


resources/ Directory – Views, Assets, and Front-End Files

The resources/ directory contains everything related to the user interface:

  • Blade template files
  • CSS and JavaScript
  • Localization strings
  • React/Vue/Svelte resources (if installed)

The structure:

resources/
views/
css/
js/
lang/

Blade Templates (resources/views)

Blade is Laravel’s templating engine. It allows you to use clean syntax with features like:

  • Template inheritance
  • Loops
  • Conditionals
  • Components

Example Blade View

<!DOCTYPE html>
<html>
<head>
&lt;title&gt;Laravel Example&lt;/title&gt;
</head> <body>
&lt;h1&gt;{{ $title }}&lt;/h1&gt;
@foreach ($posts as $post)
    &lt;h2&gt;{{ $post-&gt;title }}&lt;/h2&gt;
    &lt;p&gt;{{ $post-&gt;content }}&lt;/p&gt;
@endforeach
</body> </html>

Blade files end with .blade.php.


CSS and JS (resources/css and resources/js)

Laravel uses Vite for asset bundling.

Example JS file (resources/js/app.js):

// Example JS code
console.log("Laravel JS Loaded");

Example CSS (resources/css/app.css):

body {
font-family: sans-serif;
}

Vite builds these assets into public/.


database/ Directory – Migrations, Seeders, Factories

The database/ folder manages everything related to your database structure and sample data.

Structure:

database/
migrations/
seeders/
factories/

Migrations (database/migrations)

Migrations create and modify database tables. Think of them as version control for the database.

Example Migration

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
public function up() {
    Schema::create('posts', function (Blueprint $table) {
        $table-&gt;id();
        $table-&gt;string('title');
        $table-&gt;text('content');
        $table-&gt;timestamps();
    });
}
public function down() {
    Schema::dropIfExists('posts');
}
};

Run migrations using:

php artisan migrate

Seeders (database/seeders)

Seeders populate the database with initial or testing data.

Example Seeder

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Post;

class PostSeeder extends Seeder
{
public function run()
{
    Post::create(&#91;
        'title' =&gt; 'First Post',
        'content' =&gt; 'This is an example post.'
    ]);
}
}

Run:

php artisan db:seed --class=PostSeeder

Factories (database/factories)

Factories generate fake data for testing.

Example Factory

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
public function definition()
{
    return &#91;
        'title' =&gt; $this-&gt;faker-&gt;sentence(),
        'content' =&gt; $this-&gt;faker-&gt;paragraph()
    ];
}
}

You can use it like:

Post::factory()->count(10)->create();

How These Folders Work Together

To understand the Laravel flow, consider this example:

  1. User visits /posts
  2. The route in routes/web.php triggers PostController@index
  3. Controller fetches posts from Post model
  4. Controller passes data to the Blade view
  5. Blade template renders HTML with the data

Flow summary:

Route → Controller → Model → View → Browser

This clean separation ensures maintainable and testable code.


Practical Example: Creating a Basic Post Feature

Let’s build a small real-world example using the directories we learned.


Step 1: Migration

php artisan make:migration create_posts_table

Example migration:

Schema::create('posts', function (Blueprint $table) {
$table-&gt;id();
$table-&gt;string('title');
$table-&gt;text('content');
$table-&gt;timestamps();
});

Step 2: Model

php artisan make:model Post

app/Models/Post.php

class Post extends Model
{
protected $fillable = &#91;'title', 'content'];
}

Step 3: Controller

php artisan make:controller PostController
public function index()
{
$posts = Post::all();
return view('posts.index', compact('posts'));
}

Step 4: Route

routes/web.php

Route::get('/posts', [PostController::class, 'index']);

Step 5: View

resources/views/posts/index.blade.php

<h1>All Posts</h1>

@foreach($posts as $post)
&lt;h2&gt;{{ $post-&gt;title }}&lt;/h2&gt;
&lt;p&gt;{{ $post-&gt;content }}&lt;/p&gt;
@endforeach

You now have a working page that fetches posts from the database and displays them.


Additional Important Directories in Laravel

Even though you asked for the most important ones, here is a brief overview of other helpful folders.


public/

Contains the entry point index.php and compiled assets like images, CSS, and JS after Vite builds them.


storage/

Handles logs, cached views, uploaded files, and compiled Blade templates.


config/

Stores all configuration files for:

  • Database
  • Mail
  • Cache
  • Queue
  • Session
  • Services

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *