Laravel框架学习笔记

001需求和安装

需求

PHP >= 7.3
BCMath PHP 拓展
Ctype PHP 拓展
Fileinfo PHP 拓展
JSON PHP 拓展
Mbstring PHP 拓展
OpenSSL PHP 拓展
PDO PHP 拓展
Tokenizer PHP 拓展
XML PHP 拓展

安装

composer create-project --prefer-dist laravel/laravel blog

运行

php artisan serve

注: 需要给storage文件夹写权限

002文件夹结构的详细

根目录

app 目录
bootstrap 目录
config 目录
database 目录
public 目录
resources 目录
routes 目录
storage 目录
tests 目录
vendor 目录

APP目录

Broadcasting 目录
Console 目录 用于控制台注册
Events 目录
Exceptions 目录 注册处理异常方法
Http 目录
Jobs 目录
Listeners 目录
Mail 目录
Models 目录
Notifications 目录
Policies 目录
Providers 目录
Rules 目录

M:app/Models V:resource/views C:app/Controllers

003了解着陆页

// route/web.php
Route::get('/', function () {
    return view('welcome');
});

返回resources/views/welcome.blade.php文件

004创建第一个程序

查看帮助

php artisan
php artisan help 命令

创建控制器

php artisan make:controller Site
// app/Http/Controllers/Site.php
public function first()
    {
//        echo "<h1>欢迎来到我的第一个控制器</h1>";
        return view("first"); // first.blade.php
    }
// routes/web.php
/* 如果controller没有任何操作, 可以直接调用view
use App\Http\Controllers\Site;
Route::get("/first", [Site::class, "first"]);
*/
Route::get("/first", function () {
   return view("first");
});
// resources/views/first.blade.php
<h1>欢迎来到我的第一个控制器</h1>

005006路由

// routes/web.php
// 基础路由
Route::get("/first", [Site::class, "first"]);
// 视图路由
Route::view("/services", "first");
// 带参路由
Route::get("/services/{id}", [Site::class, "first"]);
Route::get("/services/{id?}", [Site::class, "first"]);
Route::get("/services/{id}/{name}", [Site::class, "first"]);
// 重定向路由
Route::redirect("/here", "/there");
Route::redirect("/here", "/there", 301);
// 正则匹配路由
Route::get("/services/{id}", [Site::class, "first"])
    ->where("id", "[0-9+]");
Route::get("/services/{id}/{name}", [Site::class, "first"])
    ->where(["id" => "[0-9]+", "name" => "[a-zA-Z]+"]);

007视图的完整详细信息

// routes/web.php
/*
Route::get("/services/{id}/{name}", function ($id, $name) {
    return view("services", ["id"=>$id, "name"=>$name]);
})->where(["id" => "[0-9]+", "name" => "[a-zA-Z]+"]);
*/
Route::get("/services/{id}/{name}", function ($id, $name) {
    return view("services", compact("id", "name"));
})->where(["id" => "[0-9]+", "name" => "[a-zA-Z]+"]);
// resources/views/services.blade.php
<h1>这是服务 {{$id}} 名称是{{$name}}</h1>

008009blade模板引擎

// resources/views/services.blade.php
// 模板基本语法
<?php echo $name; ?> ~ {{$name}}
{{-- 注释, 不会解析在html中 --}}
{{ strtoupper("hello") }}
@isset($name)
@endisset
@empty($name)
@endempty
@if (count($arr) > 0)
@elseif(...)
@else
@endif
@for($i = 0; $i<10; $i++)
@endfor
// 文件包含语法
// 新建 resources/views/articles/top_hearder.blade.php
@include("articles.top_hearder")
@csrf
@foreach($arr as $value)
    <h4>{{$value}}</h4>
@endforeach
@json($arr) // json_encode($arr)

010创建布局和使用布局

// 新建 resources/views/layouts/app.blade.php
// 在 resources/views/about.blade.php 中 继承布局
@extends("layouts.app") // 继承布局
// @section("content", "我是about的title")
@section("content") // 定义了片段的内容
    <div>我是about里的内容</div>
@endsection
// 在 resources/views/layouts/app.blade.php 中 显示片段的内容
@yield("content") // 显示片段的内容

011012组件的创建和使用

创建

php artisan help make:component
php artisan make:component message
会生成2个文件
app/View/Components/Message.php
resources/views/components/message.blade.php
// app/View/Components/Message.php
public $type; // 定义public属性后, 可以在组件里使用属性
public $message;
public function __construct($type, $message)
{
    $this->type = $type;
    $this->message = $message;
}
public function render()
{
    return view('components.message');
}
// resources/views/components/message.blade.php
<div>
    <!-- Be present above all else. - Naval Ravikant -->
    这是一个组件 内容
    类型是: {{$type}}
    内容是: {{$message}}
</div>

组件使用

// resources/views/first.blade.php
<x-{{}}/>
<x-message/>
<h3>
    <x-message type="success" :message="$message"/>
</h3>

013组件中的插槽和内部插槽

php artisan make:component Alert

插槽

// resources/views/components/alert.blade.php
<div>
{{$solt}}
</div>
// resources/views/first.blade.php
<x-alert> 弹出数据 </x-alert>

内部插槽

// resources/views/components/alert.blade.php
<div>
{{$solt}}
{{$title}} // 使用内部插槽, x-slot的name属性
</div>
// resources/views/first.blade.php
// 内部插槽, 用x-slot的name属性定义
<x-alert> <x-slot name="title">首页</x-slot> 弹出数据 </x-alert>

014内联组件

php artisan make:component MessageBox --inline

配置

// app/View/Components/MessageBox.php
public $name; // 定义public属性后, 可以在组件里使用属性
public function __construct($name)
{
    $this->name = $name;
}
public function render()
{
    return <<<'blade'
<div>
	{{$name}} // 111 // 组件的基本使用
	{{$slot}} // 222 // 组件的插槽
	{{$my_message}} // 我的信息 // 组件的内部插槽
</div>
blade;
}

使用

// resources/views/first.blade.php
<x-message-box name="111"/> // 组件的基本使用
<x-message-box name="111">222</x-message-box> // 组件的插槽
<x-message-box name="111"> <x-slot name="my_message">我的信息</x-slot> 222</x-message-box> // 组件的内部插槽

015创建并将表单提交至服务器

php artisan make:controller StudentController --resource
php artisan make:request StoreStudentData

路由

// routes/web.php
Route::resource("student", StudentCrontroller::class);

控制器

// app/Http/Controllers/StudnetController.php
public function index()
{
    return view("student.index");
}
public function create()
{
    return view("student.create");
}
public function store(StoreStudentData $request)
{
    $request->validated();
    var_dump($request->all());
}
public function show($id)
{
}
public function edit($id)
{
}
public function update(Request $request, $id)
{
}
public function destroy($id)
{
}

列表

// resources/views/student/index.blade.php
<a href="{{route("student.create")}}">添加</a>

新增

// resources/views/student/create.blade.php
<form action="{{route("student.store")}}" method="post">
    @csrf
    姓名: <input type="text" name="name" value="{{old("name")}}"><br>
    @error("name")
    {{$message}}<br>
    @enderror
    邮箱: <input type="text" name="email" value="{{old("email")}}"><br>
    @error("email")
    {{$message}}<br>
    @enderror
    手机: <input type="text" name="mobile" value="{{old("mobile")}}"><br>
    @error("mobile")
    {{$message}}<br>
    @enderror
    <input type="submit" value="提交"><br>
</form>

016017018019表单数据验证 接015

数据验证

// app/Http/Requests/StoreStudentData.php
public function authorize()
{
    return true;
}
public function rules()
{
    return [
        "name" => "required|min:6",
        "email" => "required",
        "mobile" => "required",
    ];
}

public function messages()
{
    return [
        "name.required" => "Name is needed",
        "email.required" => "email is needed",
        "mobile.required" => "mobile is needed",
        "name.min" => "Name 必须 大于6个字符",
    ];
}

020数据库连接基础

// .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel85
DB_USERNAME=root
DB_PASSWORD=root
// config/database.php

021022运行数据库原始查询

DB::insert()

$users = DB::insert("insert into students (name, age,address) values ('hahaha', 10, 'address')");
// 返回true或false

DB::update()

$users = DB::update("update students set age = '10' where name = ?", ['hahaha']);
// 返回更新行数n

DB::select()

$users = DB::select("select * from students where id = :id", ["id" => 1]);
// 返回二维数组或array{}

DB::delete()

$users = DB::delete("delete from students where `name` = ?", ['hahaha']);
// 返回删除行数n

023迁移和使用方法

php artisan make:migration create_students_table # 创建
php artisan migrate # 迁移
php artisan migrate --seed # 迁移并生成faker数据
php artisan migrate:rollback # 回滚
php artisan migrate:refresh # 迁移 + 回滚
// database/migrations/2021_05_16_***_create_students_table.php
public function up()
    {
        Schema::create('students', function (Blueprint $table) {
            $table->id(); // id
            $table->string("name", 120); // string
            $table->string("email", 50)->nullable(); // 可以为空
            $table->string("mobile", 30)->nullable();
            $table->integer("age")->default(0); // 默认值
            $table->enum("gender", ["male", "female", "others"]); // 枚举
            $table->text("address")->comment("地址"); // comment描述
            $table->timestamp("created_at")->useCurrent(); // 当前时间戳
            $table->timestamp("updated_at")->useCurrent();
        });
    }

024迁移和列修饰符将列添加到表

https://learnku.com/docs/laravel/8.x/migrations/9403

025Seeder基础知识

php artisan make:seeder StudentSeeder # 生成学生seeder
php artisan db:seed # 执行 database/seeders/DatabaseSeeder.php
php artisan db:seed --class=StudentSeeder # 执行指定seeder
// database/seeders/StudentSeeder.php
public function run()
    {
        // 生成一条数据
        DB::table("students")->insert([
            "name" => "小白",
            "email" => "[email protected]",
            "mobile" => "1624645324254",
            "age" => 56,
            "gender" => "male",
            "address" => "上海市嘉定区江桥"
        ]);
        // faker 生成伪造数据 一条
        $faker = \Faker\Factory::create();
        DB::table("students")->insert([
            "name" => $faker->name,
            "email" => $faker->safeEmail,
            "mobile" => $faker->phoneNumber,
            "age" => $faker->numberBetween(20, 40),
            "gender" => $faker->randomElement(['male','female','others']),
            "address" => $faker->address
        ]);
    }

注: 修改faker语言, config/app.php文件'faker_locale' => 'zh_CN',

// database/seeders/DatabaseSeeder.php
public function run()
    {
        // \App\Models\User::factory(10)->create();
//        $this->call(
//            StudentsSeeder::class
//        );
        \App\Models\Student::factory(10)->create();
    }

026faker库的使用

laravel自带此库

https://github.com/fzaninotto/Faker

027工厂基础和seeder使用工厂

php artisan make:model Student # 建model, 工厂依赖model
php artisan make:factory StudentFactory # 建工厂
// database/factories/StudentFactory.php
public function definition()
    {
        return [
            "name" => $this->faker->name,
            "email" => $this->faker->safeEmail,
            'mobile' => $this->faker->phoneNumber,
            "age" => $this->faker->numberBetween(20, 40),
            "gender" => $this->faker->randomElement([
                "male",
                "female",
                "others"
            ]),
            "address" => $this->faker->address
        ];
    }

028模型基础及成员变量的使用

https://learnku.com/docs/laravel/8.x/eloquent/9406

php artisan make:mode Employee --all
# Model created successfully.
# Factory created successfully.
# Created Migration: 2021_05_20_010345_create_employees_table
# Seeder created successfully.
# Controller created successfully.
// app/Models/Employee.php
class Employee extends Model
{
    use HasFactory;
    protected $table = "tpl_employee"; // 定义表名 默认employee
    protected $primaryKey = "student_id"; // 定义主键 默认id
    protected $keyType = "string"; // 主键不是整数
    public $incrementing = false; // 主键不自增
    public const CREATED_AT = "create_date";
    public const UPDATED_AT = "last_update";
    public $timestamps = false; // 不存时间戳, miration建表语句中也要去掉timestamp
}

029创建表单数据并保存到数据表里

https://www.youtube.com/watch?v=0m5h45_bQgE&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=29

php artisan serve
php artisan migrate
php artisan make:model Student -a 
# Generate a migration, seeder, factory, and resource controller for the model

030会话Flash消息的设置和表单重定向

https://www.youtube.com/watch?v=//QNvUKf9pouc&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=30

// 表单提交后, flash消息回显
// session()->flash("key", "message");
$request->seession()->flash("success", "添加成功");
return redirect(route("users/create"));
@if(session()->has("success"))
    <h3>{{session("success")}}</h3>
@endif

031数据库模型从表中查数据

Student::all();Student::get();
Student::where()->first(); // 查一条
Student::find(1); // 查一条
Student::find([1,5,8]); // 查多条
Student::firstWhere('email', ''); // 查一条

032数据库到布局/model到布局

https://www.youtube.com/watch?v=gDvxJLmsxZw&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=32

033删除操作

https://www.youtube.com/watch?v=gDvxJLmsxZw&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=33

$student = Student::find($id);
$student->delete();

034更新操作

https://www.youtube.com/watch?v=NzM1MiguPiA&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=34

035查询生成器 select

DB::table('students')->get();
DB::table('students')->select("name", "email as email_address")->get();
DB::table('students')->where('id', 5)->select()->get();

036选择查询 and or

$students = DB::table('students')->where('id', 3)->where('name', 'abc')->get();
$students = DB::table('students')->where('id', 3)->where(function($query){
    $query->where('name', 'abc')->orWhere('email', '[email protected]');
})->get();
$students = DB::table('students')->where('name', 'abc')->orWhere(function($query){
    $query->where('id', 3)->where('email', '[email protected]');
})->get();
$students = DB::table('students')->whereBetween('id', [2,30])->get();
$students = DB::table('students')->whereIn('id', [2,30])->get();

037连接查询 join left right

$students = DB::table('students')->join('courses','students.id','=','courses.student_id')->get();
$students = DB::table('students')-select('')>join('courses','students.id','=','courses.student_id')->get();

038插入和更新

DB::table('students')->insert([
    'name'=>'test',
    'age'=>20
]);
$insert_id = DB::table('students')->insertGetId([
    'name'=>'test',
    'age'=>20
]);
DB::table('students')->insert([
    [
        ['name'=>'test2','age'=>20],
        ['name'=>'test3','age'=>22],
    ]
]);
DB::table('students')->where('id', 5)->update([
	'name'=>'test','age'=>99
]);

039更新 删除和截断

DB::table('students')->updateOrInsert(
    ['name'=>'test'], //条件
    ['name'=>'hahaha', 'age'=>55] // data
);
DB::table('students')->where('name','test')->delete();
DB::table('students')->truncate();

040中间件基础关于全局中间件

php artisan make:middleware CountryCheck
// app/Http/Kernel.php $middleware
\App\Http\Middleware\CountryCheck::class,
// app/Http/Middleware/CountryCheck.php
if ($request->country && !in_array($request->country, ['us', 'in'])) {
    return redirect('noaccess');
}

041中间件组

// app/Http/Kernel.php $middlewareGroups
'apprestrict' =>[
    \App\Http\Middleware\CountryCheck::class,
],
// routes/web.php
Route::get("/sample1", function () {
    echo "sample 1 page";
});
Route::get("/sample2", function () {
    echo "sample 2 page";
});
Route::group(['middleware' =>['apprestrict']], function ()
{
    Route::get("/sample3", function () {
        echo "sample 3 page";
    });
    Route::get("/sample4", function () {
        echo "sample 4 page";
    });
});

042路由中间件

// app/Http/Kernel.php $routeMiddleware
'ck' => \App\Http\Middleware\CountryCheck::class,
// routes/web.php
Route::get("/sample5", function () {
    echo "sample 5 page";
})->middleware('ck');

043使用GET REST APIs

php artisan make:countroller PostController
// app/Http/Controllers/PostController.php
public function index()
{
    $posts = Http::get("http://jsonplaceholder.typicode.com/posts");
    return json_decode($posts);
}

044本地化 多语言网站概念

https://www.youtube.com/watch?v=vn-OTkiYJLI&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=44

php artisan make:controller ServiceController
// app/Http/Controllers/ServiceController.php
public function service($locale)
{
    App::setLocale($locale);
    return view("lang");
}
// resources/views/lang.blade.php
<h3>{{ __('app.langtest') }}</h3>
<h3>{{ trans('app.langtest') }}</h3>
<h3>@lang('app.langtest')</h3>
// resources/lang/en/app.php
// resources/lang/zh_CN/app.php
return [
    "langtest" => "欢迎来到实力至上主义的教室",
];

045访问器的概念

// app/Models/Student.php
public function getEmailAttribute($value){
    return strtoupper($value);
}
public function getCreatedAtAttribute($value)
{
    return date("Y-m-d H:i:s", strtotime($value));
}
// app/Http/Controllers/StudentController.php
public function index()
{
    $students = Student::all();
    return $students;
}

046修改器的概念

// app/Models/Student.php
public function setMobileAttribute($value)
{
    $this->attributes["mobile"] = "+91" . $value;
}

047ORM一对一的关系

// app/Models/User.php
public function phone()
{
    return $this->hasOne(Phone::class, 'user_id', 'id'); // 关联的model/phone, 关联的model字段/phone.user_id, 当前的model字段/user.id
}
// app/Models/Phone.php
public function user()
{
    return $this->belongsTo(User::class, 'user_id', 'id'); // 反向关联的model/user, 当前model关联user/id, 反向关联model的phone/user_id
}

048一对多

// app/Models/User.php
public function phones()
{
    return $this->hasMany(Phone::class); // 第二个第三个参数会自动识别 user_id, id
}

049一对一直通关系

// Person -> Broker -> Home
public function homeInformation()
{
    return $this->hasOneThrough(Home::class, Broker::class);
}

050一对多直通关系

// Person -> Broker -> Homes
public function homeList()
{
    return $this->hasManyThrough(Home::class, Broker::class);
}

051多对多

// app/Models/User.php
public function roles()
{
    return $this->belangsToMany(Role::class);
}
// app/Models/Role.php
public function getUsers()
{
    return $this->belangsToMany(User::class);
}

052如何使用列名

看047

053身份验证基本描述

composer require laravel/breeze --dev
php artisan help breeze:install
npm install && npm run dev

054脚手架文件/功能

055JetStream

composer require laravel/jetstream
php artisan jetstream:install livewire
php artisan migrate
npm install && npm run dev

056关于脚手架文件 Auth的JetStream

// config/fortify.php
'features' => [
    // 注释删除注册功能
    Features::registration(), // 注册
    Features::resetPasswords(), // 重置密码
    // Features::emailVerification(),
    Features::updateProfileInformation(), // 更新个人信息
    Features::updatePasswords(), // 更新密码
    Features::twoFactorAuthentication([ // 二次认证
        'confirmPassword' => true,
    ]),
],
// config/jetstream.php
'features' => [
    // Features::termsAndPrivacyPolicy(),
    // Features::profilePhotos(), // 照片
    // Features::api(),
    // Features::teams(['invitations' => true]),
    Features::accountDeletion(), // 删除用户
],

057脚手架文件和身份验证

composer require laravel/jetstream
php artisan jetstream:install inertia
php artisan migrate
npm install && npm run dev

058什么是stub, 存根定制

php artisan make:controller EmployeeController
php artisan make:model Employee
php artisan stub:publish
/stubs 目录

059路由模型绑定

060URL生成器功能

url()
route()
action()

061关于资源控制器

php artisan make:controller MemberController -r
php artisan route:list

062063CURD

php artisan make:model Device -m # 创建模型和迁移文件
# php artisan make:model Device -a # 创建所有
php artisan migrate # 迁移
php artisan make:controller DeviceController -r --model=Device # 创建控制器use Device model

064布局

071thinker简介

php artisan thinker
echo "11";
Student::insert(["name"=>"hahaha",'created_at'=>new DateTime()]);
Student::create(["name"=>"hahaha",'created_at'=>new DateTime()]);
Student::all();
Student::find(1);
Student::where('name'=>'hahaha')->get();
Student::where('name'=>'hahaha')->first();
Student::where('name'=>'hahaha')->update(['name'=>'222']);
Student::where('id'=>2)->delete();

072thinker使用DB类

DB::table('students')->insert([ 'name'=>'lisi','created_at'=>new DateTime() ]);
DB::table('students')->get();
where, first, update, delete

073关于model事件-1

Create,update,delete,save: creating() & created() # 前 后
// app/Models/Device.php
public static function boot(){
    parent::boot();
    static::creating(function($item){
        Log::info( "访问前" . $item );
	});
}

074075Events Listener监听器-23

php artisan make:event StudentCreatingEvent
// app/Models/Device.php
protected $dispatchesEvents = [
    'creating' => StudentCreatingEvent::class,
];
php artisan make:listener StudentCreatingListener --event=StudentCreatingEvent

076Observer(观察者)模型事件-4

php artisan make:observer StudentObserver --model=Student

077自定义HTTP 404页面

php artisan vendor:publish --tag=laravel-errors

081创建自定义artisan命令

php artisan make:command UserInfo
// app/Console/Commands/UserInfo.php
protected $signature = 'user:info';
protected $description = '查询用户信息';
public function handle()
{
    $name = $this->ask("你的名字?");
    //        $this->info('输入成功!' . $name);
    //        $this->line('输入成功!' . $name);
    $this->error('输入成功!' . $name);

    return 0;
}

082自定义命令和model交互

https://www.youtube.com/watch?v=XMUArtkDy0A&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=82

083使用Gmail SMTP发邮件

php artisan make:controller SampleController
php artisan make:mail TestMail

084markdown发送邮件

php artisan make:mail TestMail2 --markdown=emails.sample-mail2

086markdown自定义样式

php artisan vendor:publish --tag=laravel-mail

087多数据库链接

public $connection = "mysql_2"; # model
DB::connection("mysql_2")->table('procuts')->get(); // controller
Schena::connection('mysql_2')->create() // migration

088Helpers使用

// app/Helpers.php
// composer.json
"autoload"
    "files": [
        "app/Helpers.php"
    ]
composer dump-autoload

089路由前缀

Route::prefix('admin')->group(function(){   
});

091分页

https://www.youtube.com/watch?v=CaHF1zbevwg&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=91

https://onlinewebtutorblog.com/step-by-step-laravel-8-pagination-tutorial/

092trait的概念

https://onlinewebtutorblog.com/concept-of-trait-in-laravel-8-tutorial-with-example/

093多重身份验证和角色登录访问

https://www.youtube.com/watch?v=A0M4qn5L03I&list=PLT9miexWCpPUCBjFVFR_05Rr8pvLeoHO0&index=93

094Voyager管理面板