Introduction
Environment & Tools
Editeur VS Code - Extensions
Mastering Laravel : From Fundamentals to Advanced Web Development
- Installation & setup
- Routes, Vues & Layouts
- Handling Dynamic Route Parameters in Laravel
- Dynamic Routes with Multiple Parameters in Laravel
- Rendering HTML Content in Laravel Blade Templates
- Blade Template with Unescaped Content
- Models and Migrations
- Creating a MySQL Database
- Creating a New Migration File in Laravel
- Steps to Create a Migration for Adding a New Column to table Post
- Introduction to Laravel Models
- Tinker in Laravel
- Lazy Collection in laravel
- Creating, Updating and Reading data
- Displaying a List of Posts with forelse
- Forms and CSRF token
- Working Session flash messages
- Validation basics
- For*m Requests*
- old() helper in forms
- Edit & Update & Delete Method
what is Laravel
Laravel is a web application framework with expressive, elegant syntax. It simplifies tasks in web development by easing common tasks, such as routing, sessions, caching, and authentication. Laravel aims to make the development process a pleasing one for the developer without sacrificing application functionality. It's accessible, yet powerful, providing tools needed for large, robust applications.
Why Laravel
Laravel is considered the best choice for many developers due to its elegant syntax, robust features, and extensive ecosystem. It offers a powerful ORM (Eloquent), efficient routing, an intuitive queue system, and simple authentication, which speeds up the web development process. Laravel's extensive libraries and MVC architecture make it ideal for building scalable applications. Moreover, its strong community support, comprehensive documentation, and built-in tools for testing and debugging enhance its appeal. This combination of ease of use, scalability, and functionality makes Laravel a top choice in modern web development.
💡 documentation. For further details on Laravel commands, in-depth explanations, and advanced usage, you can refer to the Laravel documentation at Laravel Official Documentation. This resource is highly recommended for staying updated with the latest Laravel features and best practices.
Environment & Tools
Laragon
Laragon is a portable, isolated, fast, and powerful universal development environment for PHP, Node.js, Python, Java, Go, Ruby. It is designed to provide developers with a quick and easy way to set up a local development environment. The interface displayed in your screenshot is user-friendly and typically includes options to manage services like Apache, MySQL, and others, with the ability to start, stop, and reload these services. It also integrates a terminal and other tools like root access and database management to streamline development workflows. Laragon is often favored for its simplicity and the convenience of having multiple development utilities in one place.
XAMPP
XAMPP is a free and open-source cross-platform web server solution stack package. It simplifies the process of installing and configuring Apache server, MySQL, PHP, and Perl. XAMPP is widely used by developers to build and test web applications locally before deploying them. Its user-friendly interface and straightforward setup make it ideal for beginners and professionals alike, providing a reliable and consistent development environment.
Composer
Composer is a dependency manager for PHP, facilitating the management of libraries and packages in PHP projects. It allows developers to declare the libraries their project depends on and manages them for you. Composer streamlines the process of installing and updating libraries, ensuring compatibility and reducing conflicts. It's an essential tool for modern PHP development, promoting efficient and effective management of project dependencies.
Git
Download Git
Git is a distributed version control system used for tracking changes in source code during software development. It enables multiple developers to work collaboratively on the same project, allowing them to branch, merge, and track their work independently. Git is known for its speed, data integrity, and support for distributed, non-linear workflows, making it a staple in the toolkit of developers for managing and maintaining codebases efficiently.
HeidiSQL
HeidiSQL is a powerful, easy-to-use interface for managing MySQL, MariaDB, SQL Server, PostgreSQL, and SQLite databases. It allows users to browse and edit data, create and modify tables, views, procedures, triggers, and scheduled events. Additionally, HeidiSQL provides a user-friendly interface for importing and exporting data, making database management more accessible and manageable for developers and database administrators.
VS Code
Visual Studio Code (VS Code) is a free, open-source code editor developed by Microsoft. It supports a variety of programming languages and includes features like syntax highlighting, intelligent code completion, snippets, and code refactoring. VS Code also has a vast extension library, which allows developers to customize their environment to suit their needs. Its lightweight design, powerful features, and ease of customization make it a popular choice among developers for writing and editing code.
Editeur VS Code - Extensions
In our course, we are installing several useful extensions for Visual Studio Code that greatly enhance our coding experience. These include:
- PHP IntelliSense: Provides smart code completion and navigation for PHP.
- PHP Intelephense: An efficient and feature-rich PHP language server.
- PHP DocBlocker: Assists in generating and maintaining PHP DocBlocks.
- PHP Namespace Resolver: Streamlines the management and resolution of namespaces.
- Laravel Blade Snippets: Offers handy snippets for Laravel Blade templates.
- Laravel Artisan: Integrates Laravel's Artisan commands into VS Code.
- Laravel Goto View: Simplifies navigation to Laravel views from controllers.
These extensions collectively improve our PHP and Laravel development workflow within Visual Studio Code
Mastering Laravel: From Fundamentals to Advanced Web Development
Installation & setup
now let start by installing our first laravel project with those command :
composer create-project laravel/laravel example-app
The MVC (Model-View-Controller) architecture is a software design pattern that separates an application into three main logical components: the model, the view, and the controller. Each of these components is represented in the Laravel directory structure shown in your image:
-
Model: The
Models
directory contains the application's business logic and is responsible for retrieving, inserting, and updating information in the database. In your screenshot, theUser.php
file inside theModels
directory represents a model. -
View: The
views
directory inside theresources
folder contains the presentation layer of the application. It's where the application's user interface is stored. Views are responsible for displaying data provided by the controller in a format that the user can interact with. -
Controller: The
Controllers
directory inside theHttp
folder contains the controllers. Controllers handle user requests, process them (often with the help of models), and return a response, usually by rendering a view.
cd example-app
php artisan serve
Routes, Vues & Layouts
creating first route and views in our project :
Home
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Home</title>
</head>
<body>
<h1>Home Pge</h1>
<p>Learn Laravel</p>
</body>
</html>
About
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>About</title>
</head>
<body>
<h1>About Page</h1>
</body>
</html>
routes :
Route::get('/', function () {
return view('home');
});
Route::get('/about', function () {
return view('about');
});
instead of duplicating the same HTML structure across different pages, you use a layout, often referred to as a "master page". This layout serves as a template for other views and contains common HTML structures such as the header, footer, and main navigation elements.
To implement a layout in Laravel, you create a master blade file, typically named layout.blade.php
or master.blade.php
, which includes placeholders for content (@yield
directives) that can be filled by individual views. Here's a basic example of how you might structure a master layout:
let try to add only @extends('layout')
layout.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
{{-- @yield('content') --}}
</body>
</html>
home.blade.php
@extends('layout')
<h1>Home Pge</h1>
<p>Learn Laravel</p>
When you use @extends('layout')
in a Blade template with Laravel, it's typically used for inheriting a master layout. However, this current implementation is not optimal for search engine optimization (SEO) because it not respecting the Content Placement
home.blade.php
@extends('layout')
@section('content')
<h1>Home Pge</h1>
<p>Learn Laravel</p>
@endsection
Comparing Route Definitions in Laravel: Closures vs. Route::view
for Static Pages
Route::get('/', function () {
return view('home');
});
Route::get('/about', function () {
return view('about');
});
Route::view('/','home');
Route::view('/about','about');
- The primary difference is in their simplicity and potential for expansion. The first method (using closures) is slightly more verbose but allows for added complexity, such as passing data to views, condition checks, or other operations before returning the view.
- The second method (
Route::view
) is more succinct and is ideal for static pages where you're only returning a view without needing any additional logic or data passed to the view.
Handling Dynamic Route Parameters in Laravel
In this section, we explore how to define routes with dynamic parameters in Laravel. This is particularly useful when you want to fetch or manipulate data based on a variable part of the URL, like an ID from a database.
Example: Fetching a Post by ID
Consider a scenario where you need to display a specific post based on its ID. The ID is dynamically provided in the URL. Here's how you can define such a route:
Route::get('/posts/{id}', function ($id) {
return $id;
});
testing this dynamic Route :
Dynamic Routes with Multiple Parameters in Laravel
This example demonstrates how to use multiple dynamic parameters in Laravel routes and pass data to a view. We'll use a route with two dynamic parameters (id
and author
) and then pass the data to a Blade template.
Example 1 :
Route::get('/posts/{id}/{author}', function ($id,$author) {
return $id. " author: $author ";
});
Example 2:
show.blade.php
@extends('layout')
@section('content')
<p>{{ $post['title'] }}</p>
@endsection
Explanation:
-
@extends('layout')
: Indicates that this Blade file extends a master layout namedlayout
. -
@section('content')
: Starts a section namedcontent
. This is where you define the content that will be injected into thelayout
. -
{{ $post['title'] }}
: Blade syntax for outputting the title of the post. This data is passed from the route.
Route::get('/posts/{id}/{author}', function ($id,$author) {
$posts = [
1 => ['title' => 'Intro to Laravel'],
2 => ['title' => 'Intro to PHP'],
];
return view('posts.show', [
'post' => $posts[$id]
]);
});
Explanation:
-
Route::get('/posts/{id}/{author}', ...)
: Defines a GET route with two dynamic segments,{id}
and{author}
. Laravel will pass these as parameters to the provided closure. -
$posts = [...];
: An associative array simulating a data source (like database records). -
return view('posts.show', ['post' => $posts[$id]]);
: The function returns a view namedposts.show
, passing along thepost
data retrieved from the$posts
array using the provided$id
.
result expected :
Example: Optional Route Parameters in Laravel
Route::get('/posts/{id}/{author?}', function ($id,$author = "default name") {
$posts = [
1 => ['title' => 'Intro to Laravel'],
2 => ['title' => 'Intro to PHP'],
];
return view('posts.show', [
'post' => $posts[$id] ,
'author' => $author
]);
});
Explanation:
-
Route::get('/posts/{id}/{author?}', ...)
: Defines a GET route where{id}
is a required parameter, and{author}
is optional (indicated by the?
after the parameter name). -
$author = "default name"
: Sets a default value for the$author
parameter. Ifauthor
is not provided in the URL, it will default to "default name". - The route closure returns the
posts.show
view, passing thepost
data (based on$id
) and theauthor
name.
Use Case:
This approach is valuable for creating more flexible web routes, where certain parts of the URL might be optional. It's particularly useful in scenarios where you want to provide additional context or filters for a page, but those filters are not mandatory.
Rendering HTML Content in Laravel Blade Templates
Background:
Laravel Blade templates escape output by default. This means that any HTML tags included in variables will not be rendered as HTML but will be displayed as plain text. This is a security feature to prevent Cross-Site Scripting (XSS) attacks, where malicious scripts are injected into web pages.
Example: Route with HTML Content in Data Array
Route::get('/posts/{id}/{author?}', function ($id,$author = "default name") {
$posts = [
1 => ['title' => '<a> Intro to Laravel </a>'],
2 => ['title' => 'Intro to PHP'],
];
return view('posts.show', [
'post' => $posts[$id] ,
'author' => $author
]);
});
Explanation:
- The
$posts
array includes HTML content (<a> Intro to Laravel </a>
) for the title of the first post. - By default, Blade will escape this HTML content, meaning it will be displayed as plain text in the view, not as an actual link.
Blade Template with Unescaped Content
To render the HTML content as actual HTML rather than escaped text, you use the {!! !!}
syntax in Blade:
@extends('layout')
@section('content')
<h1>{!! $post['title'] !!}</h1>
<p>Author: {{ $author }}</p>
@endsection
Controller basics
Controllers in Laravel are used to organize the logic of handling HTTP requests. They serve as an intermediary between the models (which interact with the database) and views (which present data to the user). Controllers help in keeping the code clean and separating the logic from the routing layer.
Key Concepts:
-
Creation and Structure: Controllers are typically stored in the
app/Http/Controllers
directory. They can be generated using the Artisan commandphp artisan make:controller <ControllerName>
. A controller class usually extends the base controller class provided by Laravel. - Methods and Routes: Each public method in a controller can be linked to a route. These methods handle requests and return responses. For example, a method can return a view, a redirect, or a JSON response.
- Passing Data: Data can be passed to controller methods via route parameters or request data. Controllers can then pass this data to views or use it to interact with models.
-
Resource Controllers: For standard CRUD operations, Laravel provides resource controllers with methods like
index
,create
,store
,show
,edit
,update
, anddestroy
. These can be automatically set up with a single route declaration. - Dependency Injection: Controllers support dependency injection, allowing you to type-hint dependencies in the constructor or method signatures. Laravel's service container automatically injects these dependencies.
Let Create our first Controller
php artisan make:controller HomeController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
//
public function home()
{
return view('home');
}
public function about()
{
return view('about');
}
public function blog($id,$author = "default name")
{
$posts = [
1 => ['title' => '<a> Intro to Laravel </a>'],
2 => ['title' => 'Intro to PHP'],
];
return view('posts.show', [
'post' => $posts[$id] ,
'author' => $author
]);
}
}
replace welcome blade code with this :
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" />
<!-- Styles -->
</head>
<body class="antialiased">
<a href="{{ route('home') }}">Home</a>
<a href="{{ route('about') }}">About</a>
<a href="{{ route('blog-posts', ['id' => 1]) }}">Show Post</a>
</body>
</html>
let change our olds route with newest ones :
Route::get('/posts/{id}/{author?}', [HomeController::class, 'blog'])->name('blog-posts');
Route::get('/home', [HomeController::class, 'home'])->name('home');
Route::get('/about', [HomeController::class, 'about'])->name('about');
Models and Migrations
after this phase we need to connect our application with a Database in mysql
For this, Laravel provides a robust and flexible database layer that integrates seamlessly with various database engines. The configuration settings for databases are primarily located in the config/database.php
file, along with the .env
file for environment-specific settings.
Configuring the Database Connection:
-
Environment File (.env): Laravel uses the
.env
file to manage environment-specific configurations. To connect to a MySQL database, you need to set the appropriate values in your.env
file for your database connection, likeDB_CONNECTION
,DB_HOST
,DB_PORT
,DB_DATABASE
,DB_USERNAME
, andDB_PASSWORD
. This is an example of how you might configure these: -
Database Configuration File (config/database.php): This file holds the configuration for all your database connections. Laravel supports several database drivers out of the box: MySQL, PostgreSQL, SQLite, and SQL Server. You can define settings for each of these and switch between them as needed. The configurations read the values from the
.env
file, ensuring security and ease of deployment across different environments.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
Creating a MySQL Database
When you click on the database icon in Laragon, it opens an interface for HeidiSQL, which is included with the Laragon installation. Laragon is an all-in-one development environment that simplifies database management and other development tasks
i called my Database : first
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=first
DB_USERNAME=root
DB_PASSWORD=
After creating your database named "first", you need to update your Laravel .env
file to reflect the correct database settings, including the database name (DB_DATABASE=first
). Then, you can use the Artisan migrate
command to set up your database tables:
php artisan migrate
**php artisan migrate:rollback**
Key Aspects of php artisan migrate:rollback
-
Undo Last Migrations: The command undoes the last batch of migrations that were run. In Laravel, migrations are batched each time you run the
php artisan migrate
command.migrate:rollback
targets the migrations from the latest batch. -
Rollback to a Specific Point: You can specify how many steps of migrations you want to rollback using the
-step
option. For example,php artisan migrate:rollback --step=1
will rollback the last migration only. -
Invoking the
down
Method: Each migration file has two methods:up()
anddown()
. Theup()
method is used to add new tables, columns, or indexes to your database, while thedown()
method should reverse the operations performed by theup()
method. Themigrate:rollback
command calls thedown()
method for each migration in the last batch.
Creating a New Migration File in Laravel
Introduction:
In Laravel, migrations are essential for managing your application's database schema. They allow you to define and modify your database tables and columns in a programmatic and version-controlled manner. Let's walk through the process of creating a new migration file.
Step-by-Step Process:
**Using Artisan Command:**
Laravel provides an Artisan command-line tool to simplify the creation of migration files. To create a new migration, use the make:migration
command followed by a name that describes the purpose of the migration. The naming convention typically involves a description of the action followed by the name of the table. For example:
php artisan make:migration create_posts_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title',120);
$table->text('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Migration File Structure:
The new migration file will be placed in the database/migrations
directory. The file name includes a timestamp to ensure migrations are executed in the order they were created. Inside the migration file, you will find two methods: up()
and down()
.
-
up()
Method: Defines the database operations to be executed when the migration is run (e.g., creating a table, adding columns). -
down()
Method: Defines the operations to revert the actions of theup()
method (e.g., dropping a table).
Steps to Create a Migration for Adding a New Column to table Post
-
Generate the Migration File:
First, you need to create a new migration file. The name of the migration should describe the action it performs. Use the Artisan command:
php artisan make:migration add_slug_and_active_to_posts_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('posts', function (Blueprint $table) {
//
$table->string('slug')->unique();
$table->boolean('active')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('slug');
$table->dropColumn('active');
// or this $table->dropColumn(['slug','active']);
});
}
};
### Introduction to Laravel Models
**Overview:**
In Laravel, a model is a fundamental part of the Eloquent ORM (Object-Relational Mapping) and represents a single database table. Models provide a simple and elegant way to interact with your database. They allow you to query the database tables and perform various operations on the database records in an object-oriented manner.
**Naming Conventions:**
- **Singular and Capitalized**: By convention, model names in Laravel are singular and use "StudlyCaps" (also known as PascalCase). This means the first letter of each word is capitalized, and there are no underscores between words.
- **Correspondence with Database Tables**: The model name should be the singular form of the table name. For instance, if you have a table named **`posts`**, the corresponding model should be named **`Post`**.
### **Generating a Model**
To generate a model in Laravel, you use the Artisan command-line tool. Here's how you can create a model for a **`posts`** table:
```makefile
php artisan make:model Post
```
This command creates a **`Post`** model in the **`app/Models`** directory.
**Example of a Basic Post Model:**
```php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// Model content goes here
}
```
**Key Features of Models:**
1. **Eloquent ORM**: Laravel's Eloquent ORM provides an active record implementation, making it easier to interact with your database. Each model you create corresponds to a database table, and each instance of the model represents a row in the table.
2. **Property Mapping**: The columns in the database table are automatically mapped to properties of the model. So, you can access and set these properties directly to interact with the corresponding database columns.
3. **Timestamps**: By default, Eloquent expects **`created_at`** and **`updated_at`** columns to be present in your table. It will automatically set these values when models are created or updated.
4. **Mass Assignment Protection**: You can specify either a **`fillable`** or **`guarded`** property on your model to protect against mass-assignment vulnerabilities.
5. **Relationships**: Models can define relationships (like one-to-many, many-to-many) with other models. These relationships are methods that return instances of the relationship.
However, if you want your model to use a different table name that doesn't follow this convention, you can explicitly define the table name in your model. To do this, you can set the **`$table`** property within your model class. Here's an example of how to do this:
```php
protected $table = 'my_custom_posts';
```
In Laravel, **`-mcr`** is a combination of options used with the **`artisan make:model`** command. This command is used to generate a new model, and the options specify additional files that should be created alongside the model. Here's what each letter in **`-mcr`** stands for:
- **`m`**: This option tells Artisan to also create a migration file for the model. Migrations are used to define the database schema. For example, if you're creating a **`Post`** model, using **`m`** will create a corresponding migration file for creating the **`posts`** table in the database.
- **`c`**: This option is for creating a controller. When used, Artisan will generate a new controller file in the **`app/Http/Controllers`** directory. The controller will be named after the model. For a **`Post`** model, this would create a **`PostController`**.
- **`r`**: This indicates that the generated controller should be a resource controller. A resource controller includes methods for the standard set of create, read, update, and delete operations (CRUD). This is useful for quickly scaffolding the basic CRUD functionality.
```php
php artisan make:model Category -mcr
```
---
### Tinker in Laravel
Tinker, included in Laravel, is an interactive shell that integrates with your Laravel application, providing a convenient way to interact with your app's data and functionalities directly from the command line. It leverages the PsySH package to offer an interactive PHP REPL (Read-Eval-Print Loop) for running PHP code in real-time.
Here's a brief overview of what Tinker allows you to do:
1. **Interact with Eloquent Models**: You can create, retrieve, update, and delete database records using Eloquent models directly from the command line.
2. **Run Application Code**: Tinker lets you execute any PHP code or Laravel-specific code in the context of your application. This is particularly useful for testing and debugging.
3. **Event and Job Testing**: You can dispatch events and jobs to test their behavior without needing to trigger them through the application's UI or API.
4. **Experimentation and Prototyping**: It provides a playground for experimenting with new ideas and code snippets, making it easier to prototype without the need to create routes or controllers.
5. **Database Queries**: Apart from Eloquent, you can also run raw database queries or use the query builder for more complex operations.
To use Tinker, you simply run **`php artisan tinker`** in your terminal. This command opens a shell where you can type in your PHP code, and it will be executed within the context of your Laravel application. This immediate feedback loop makes Tinker an invaluable tool for Laravel developers for quick testing and debugging.
let try to isnert first row in our table post :
```php
php artisan tinker
> $post = new Post();
> $post->title = "learn laravel";
= "learn laravel"
> $post->slug = "learn-laravel";
= "learn-laravel"
> $post->content = "laravel is a php framwork";
= "laravel is a php framwork"
> $post->active = true;
= true
> $post->save();
= true
$post->title = "learn angular";
= "learn angular"
> $post->content = "angular is a js framwork";
= "angular is a js framwork"
> $post->slug = "learn-angular";
= "learn-angular"
> $post->active = false;
= false
> $post->save();
```
```php
// get all the posts
> Post::all();
= Illuminate\Database\Eloquent\Collection {#5019
all: [
App\Models\Post {#6025
id: 1,
title: "learn laravel",
content: "laravel is a php framwork",
created_at: "2024-01-13 21:06:26",
updated_at: "2024-01-13 21:06:26",
slug: "learn-laravel",
active: 1,
},
App\Models\Post {#5016
id: 2,
title: "learn angular",
content: "angular is a js framwork",
created_at: "2024-01-13 21:10:34",
updated_at: "2024-01-13 21:10:34",
slug: "learn-angular",
active: 0,
},
],
}
// get the First post
> Post::first();
= App\Models\Post {#6026
id: 1,
title: "learn laravel",
content: "laravel is a php framwork",
created_at: "2024-01-13 21:06:26",
updated_at: "2024-01-13 21:06:26",
slug: "learn-laravel",
active: 1,
}
// get the last post
> Post::get()->last();
= App\Models\Post {#6039
id: 2,
title: "learn angular",
content: "angular is a js framwork",
created_at: "2024-01-13 21:10:34",
updated_at: "2024-01-13 21:10:34",
slug: "learn-angular",
active: 0,
}
```
Lazy Collection in laravel
Lazy Collections in Laravel are an efficient way to handle large datasets with minimal memory usage. When you use Post::cursor()
, Laravel returns an instance of Illuminate\Support\LazyCollection
. This collection leverages PHP's generators to keep memory usage low by only fetching one item at a time from the database as it's being iterated over.
Key points for Lazy Collections:
- Efficient Memory Usage: Ideal for processing large datasets without consuming a lot of memory. Only the current item in the iteration is loaded into memory.
- Seamless Iteration: Works like regular collections but under the hood, it fetches items one by one, which is great for large datasets.
- Useful for Data Export: Perfect for exporting or processing large amounts of data, like generating large CSV files or reports.
-
Easy to Implement: Just replace
get()
withcursor()
in your Eloquent query. The rest of the code remains the same.
Example Usage:
Post::cursor();
= Illuminate\Support\LazyCollection {#5813
+source: Closure() {#6028 …4},
}
> $posts = Post::cursor();
= Illuminate\Support\LazyCollection {#6038
+source: Closure() {#5011 …4},
}
> foreach ($posts as $post) { echo "{$post->title} \n"; }
learn laravel
learn angular
This code fetches posts one by one from the database, echoing the title of each post. It's highly efficient for large tables where loading all records at once would be impractical due to memory constraints.
Creating, Updating and Reading data
php artisan make:controller PostController --resource
-
Creating the Controller:
- The
make:controller
Artisan command is used to create a new controller file in your Laravel application. -
PostController
is the name of the controller. Laravel will place this controller in theapp/Http/Controllers
directory.
- The
-
Resource Controller:
- The
-resource
flag generates a controller with methods for each of the available resource operations. These includeindex
,create
,store
,show
,edit
,update
, anddestroy
. - Each method corresponds to a specific CRUD operation and is pre-defined with a method signature.
- The
and for creating route for each method exist in the post Controller , Laravel provides a very convenient and concise way to define routes for all the CRUD operations in a resource controller using the Route::resource
method. When you use Route::resource('posts', PostController::class);
in your routes/web.php
file, it automatically creates routes for each method in the PostController
.
Route::resource('posts', PostController::class);
you can check all the Routes exist in your web.php with this command line :
php artisan route:list
use in different case :
Route::resource('posts', PostController::class)->only(['create']);
This line of code will register only the create
route for the PostController
. It means that Laravel will only set up the route that shows the form to create a new post (/posts/create
with the GET
method, mapped to the create
method in PostController
), and all other resource routes (like index
, store
, show
, edit
, update
, destroy
) will not be registered.
PostController (PostController.php
)
Now, let's complete each method in the PostController
:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$posts = Post::all(); // or [] for forelse test in the blade
return view('posts.index', [
'posts' => $posts]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$post = Post::findOrFail($id);
return view('posts.show', [
'post' => $post
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
Explanation
- index: Lists all posts.
- create: Shows a form to create a new post.
- store: Saves a new post to the database.
- show: Displays a specific post.
- edit: Shows a form to edit an existing post.
- update: Updates an existing post in the database.
- destroy: Deletes a post from the database.
Each method interacts with the Post
model to perform CRUD (Create, Read, Update, Delete) operations. The views
(posts.index
, posts.create
, posts.show
, posts.edit
) referenced in these methods need to be created within the resources/views/posts
directory. These Blade templates will form the user interface for interacting with the posts.
Blade directives @if, @foreach, dates
index.blade.php
@extends('layout')
@section('content')
<h1>list of Post</h1>
<ul>
@foreach($posts as $post)
<li>
<h2><a href="{{route('posts.show',['post'=>$post->id])}}">{{$post->title}}</a></h2>
<p>{{$post->content}}</p>
<em>{{$post->created_at}}</em>
</li>
@endforeach
</ul>
@endsection
show.blade.php
@extends('layout')
@section('content')
<h2>{{$post->title}}</h2>
<p>{{$post->content}}</p>
<em>{{$post->created_at}}</em>
@if ($post->active)
<p>status : Active</p>
@else
<p>status : Desactivated</p>
@endif
@endsection
Displaying a List of Posts with forelse
Example :
@extends('layout')
@section('content')
<h1>list of Post</h1>
<ul>
@forelse($posts as $post)
<li>
<h2><a href="{{route('posts.show',['post'=>$post->id])}}">{{$post->title}}</a></h2>
<p>{{$post->content}}</p>
<em>{{$post->created_at}}</em>
</li>
@empty
<p>No blog post yet!</p>
@endforelse
</ul>
@endsection
-
@forelse
is a Blade directive that functions like aforeach
loop, but it also handles the case where the array ($posts
in this case) is empty. - It iterates over each
Post
object within the$posts
collection. - Post Details
- This section displays the title, content, and creation date of each post.
- The title is wrapped in a hyperlink (
<a>
tag) generated by theroute()
function, which creates a URL to the route namedposts.show
, passing the post's ID as a parameter. -
{{ }}
is used to display the data, and it automatically escapes HTML entities to prevent XSS attacks. Handling No Posts
The
@empty
directive is part of the@forelse
loop. It specifies the content to show when the$posts
collection is empty.In this case, it displays a simple message: "No blog post yet!"
Understanding diffForHumans()
The diffForHumans()
method in Carbon provides a human-readable difference between two dates. It's particularly useful when you want to display the time elapsed in a way that is easy for users to understand. For example, instead of showing a date like "2021-03-31 08:30:00", you could display "5 hours ago", "2 days ago", or "a month ago".
Basic Usage
When you retrieve a timestamp from the database in Laravel, Eloquent automatically casts it to a Carbon instance (if you're using standard timestamp fields like created_at
, updated_at
). This allows you to directly use Carbon methods on these fields. Here’s a basic example:
<em>{{$post->created_at->diffForHumans()}}</em>
Other Features
- Comparison with Other Dates: You can compare any two Carbon instances, not just the current time.
- Localization: Carbon supports localization, so you can display time differences in different languages.
- Precision: You can control the precision of the difference (like seconds, minutes, hours, etc.).
Forms and CSRF token
let create a blade to test our first senario for forms ;
@extends('layout')
@section('content')
<form action="{{route('posts.store')}}" method="POST">
<div><label for="title">your title</label><input name="title" id="title" type="text" name="" id=""></div>
<div><label for="content"></label><input name="content" id="content" type="text" name="" id=""></div>
<button type="submit">Create Post</button>
</form>
@endsection
update the layout page :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<a href="{{ route('home') }}">Home</a>
<a href="{{ route('about') }}">About</a>
<a href="{{ route('posts.create') }}">new Post</a> // adding link for create new post
@yield('content')
</body>
</html>
testing senario :
after clicking on create button we got this page :
The 419 error page (indicating a "Page Expired" issue) that you encounter when submitting a form in Laravel is due to the absence of a CSRF token in the form. CSRF stands for Cross-Site Request Forgery, which is a type of malicious exploit where unauthorized commands are transmitted from a user that the web application trusts.
Laravel includes CSRF protection as a default feature for all POST, PUT, PATCH, and DELETE requests to protect your application from such attacks. When you submit a form without a CSRF token, Laravel's security feature kicks in and rejects the request, resulting in a 419 error.
now let insert our first Post with from the Blade page
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
dd($request->all());
$request->validate([
'title' => 'required|min:3',
'content' => 'required|min:10'
]);
}
use Illuminate\Support\Str; // add this line
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// dd($request->all());
$title = $request->input('title');
$content = $request->input('content');
$slug = \Str::slug($title);
$post = new Post();
$post->title = $title;
$post->content = $content;
$post->slug = $slug;
$post->save();
return redirect()->route('posts.index');
}
Working Session flash messages
Here's a typical use case for setting a flash message in a controller and displaying it in a view:
$request->session()->flash('status', 'Post was created!');
Displaying the Message in a View
To display this message, you would typically have something like the following in your Blade template (e.g., in resources/views/layout.blade.php
or a similar layout file):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
@if(session()->has('status'))
<h3 style="color: green">
{{session()->get('status')}}
</h3>
@endif
<a href="{{ route('home') }}">Home</a>
<a href="{{ route('about') }}">About</a>
<a href="{{ route('posts.create') }}">new Post</a>
@yield('content')
</body>
</html>
Validation basics
In Laravel, when you use the $request->validate()
method in a controller action, it performs form validation based on the rules you have specified. If the validation fails (meaning the user input does not meet the validation criteria), Laravel automatically redirects the user back to the previous page, which is typically the form submission page. This redirection is a HTTP 302 (Found) response, which is a standard way of performing a redirection on the web.
Here's a breakdown of what happens:
- Form Submission: The user submits the form, sending a POST request to the server.
-
Validation in Controller: In the
store
method of your controller, you validate the request using$request->validate()
. -
Validation Rules: The
title
andcontent
fields have specific rules ('required|min:3'
and'required|min:10'
, respectively). If the user input doesn't meet these criteria, the validation fails. - Automatic Redirection on Failure: If validation fails, Laravel automatically generates a session error bag containing the validation errors and then redirects the user back to the form page with a 302 HTTP status code.
- Displaying Errors: On the form page, you can display these validation errors to inform the user what they need to correct. Laravel's Blade templates make it easy to display these errors by accessing the session error bag.
$request->validate([
'title' => 'required|min:3',
'content' => 'required|min:10'
]);
Displaying validation errors
Customize the Error message in the Front end
@extends('layout')
@section('content')
<form action="{{route('posts.store')}}" method="POST">
@csrf <!-- CSRF Token -->
<div><label for="title">your title</label><input name="title" id="title" type="text" name="" id=""></div>
<div><label for="content"></label><input name="content" id="content" type="text" name="" id=""></div>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<button type="submit">Create Post</button>
</form>
@endsection
For*m Requests*
Customize the Form Request
php artisan make:request StorePost
First, open the generated StorePost.php
file. You'll see two main methods: authorize()
and rules()
.
-
authorize()
: This method determines if the user is authorized to make this request. You returntrue
to allow orfalse
to deny the request. You can also include more complex logic using Laravel's authentication and authorization features. -
rules()
: Here, you define the validation rules for your form data.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePost extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false; // return this to true
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'title' => 'required|min:3|max:255',
'content' => 'required|min:10',
];
}
}
Use the Form Request in a Controller
Next, modify the corresponding controller method to type-hint the StorePost
request. This automatically triggers validation when the method is called.
Example:
/**
* Store a newly created resource in storage.
*/
public function store(StorePost $request)
{
// dd($request->all());
// Get validated data
$validated = $request->validated();
$title = $request->input('title');
$content = $request->input('content');
$slug = Str::slug($title);
$post = new Post();
$post->title = $title;
$post->content = $content;
$post->slug = $slug;
$post->save();
$request->session()->flash('status', 'Post was created!');
return redirect()->route('posts.index');
// return redirect()->route('posts.show', ['post' => $post->id]');
}
now let try to save our post with more concise way ;
To simplify your store
method and use the Post::create
method, you can take advantage of Laravel's Mass Assignment feature. This allows you to create a new Post
model and save it to the database
for this to work, you need to ensure that the fields you are trying to mass assign are listed in the $fillable
attribute of your Post
model.
First, update your Post
model to include the $fillable
property:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['title', 'content', 'slug'];
// Other model properties and methods...
}
Now, in your controller's store
method, you can use the Post::create
method. You will still need to manually create the slug before calling create
:
$data = $request->only(['title', 'content']);
$data['slug'] = Str::slug($data['title']);
$data['active'] = false;
$post = Post::create($data);
old() helper in forms
The old()
helper function in Laravel is a convenient tool used in forms to repopulate form fields with their previous values. This is particularly useful when a form submission fails (e.g., due to validation errors) and the page is reloaded. The old()
function ensures that the user doesn't have to re-enter all the form data again.
Usage in Blade Templates
Here's how you might use the old()
helper in a Blade template:
<input type="text" name="title" value="{{ old('title') }}">
Handling Select, Checkbox, and Radio Inputs
For select, checkbox, and radio inputs, the old()
helper can be used to determine which option should be selected or checked.
Select:
<select name="category">
<option value="1" {{ old('category') == 1 ? 'selected' : '' }}>Category 1</option>
<option value="2" {{ old('category') == 2 ? 'selected' : '' }}>Category 2</option>
</select>
Checkbox
<input type="checkbox" name="agree" {{ old('agree') ? 'checked' : '' }}>
Radio:
<input type="radio" name="gender" value="male" {{ old('gender') == 'male' ? 'checked' : '' }}>
<input type="radio" name="gender" value="female" {{ old('gender') == 'female' ? 'checked' : '' }}>.
Edit & Update & Delete Method
edit method
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$post = Post::findOrFail($id);
return view('posts.edit', [
'post' => $post
]);
}
Blade : edit.blade.php
@extends('layout')
@section('content')
<form action="{{route('posts.update',['post'=>$post->id])}}" method="POST">
@csrf <!-- CSRF Token -->
@method('PUT')
<div><label for="title">your title</label><input name="title" id="title" type="text" value="{{old('title',$post->title)}}"></div>
<div><label for="content"></label><input name="content" id="content" type="text" value="{{old('content',$post->content)}}""></div>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<button type="submit">Update Post</button>
</form>
@endsection
adding this to the index.blade.php
<a href="{{route('posts.edit',['post'=>$post->id])}}">Edit</a>
update method
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$request->validate([
'title' => 'required|min:3|max:255',
'content' => 'required|min:10',
]);
$post = Post::findOrFail($id);
$post->title = $request->input('title');
$post->content = $request->input('content');
$post->slug = Str::slug($request->input('title'));
$post->save();
$request->session()->flash('status', 'Post was updated!');
return redirect()->route('posts.show', ['post' => $post->id]);
}
Additional Points
- The
findOrFail
method is used to retrieve the post by its ID. If the post is not found, it throws aModelNotFoundException
, which Laravel will automatically convert into a 404 response.
testing senario with find and findOrfail :
if we use findorFail :
if we use only find :
delete method
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
$post = Post::findOrFail($id);
$post->delete();
session()->flash('status', 'Post was deleted!');
return redirect()->route('posts.index');
}
blade :
<form action="{{route('posts.destroy',['post'=>$post->id])}}" method="POST">
@csrf <!-- CSRF Token -->
@method('DELETE')
<button type="submit">Delete</button>
</form>
Our first CRUD View achevied :
Top comments (2)
Hi! Nice tutorial for beginners! Could you fix some format errors?
thanks for your support ! i will fix it right now apperciate it