st779779

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

laravel 安装配置功能

linux 安装

curl -s https://laravel.build/example-app | bash

通过composer安装

composer create-project laravel/laravel example-app
//下载8版本
composer create-project laravel/laravel example-app v8.*

cd example-app

php artisan serve

更新laravel 框架

https://www.php.cn/faq/544989.html

安装phpstorm开发插件

安装

composer require barryvdh/laravel-ide-helper

php artisan ide-helper:generate  
#  选择 generate 生成提示索引命令 
//更多的参数
ide-helper:eloquent  
# //Add \Eloquent helper to \Eloquent\Model
ide-helper:generate  
# 生成一个新的IDE帮助程序文件。
ide-helper:meta      
# 生成PhpStorm的元数据
ide-helper:models    
# 为模型生成自动补全

到phpstorm搜索插件 laravel 安装 laravel Query 安装
Alt text

Alt text

配置命令行工具

Alt text
Alt text
Alt text

apchae配置

<VirtualHost *:80>
	# 设置网站目录
	DocumentRoot "F:\www\class\web\www.zfw.com\public"
	# 设置网站域名
	ServerName www.zfw.com
	# 一定要设置日志,日志可以访问我们进行系统统计
	# 日志是目录不会自动创建需要手动创建,文件是会自动创建
	# 错误日志
	ErrorLog "F:\www\class\web\www.zfw.com\logs\error.log"
	# 成功日志
	CustomLog "F:\www\class\web\www.zfw.com\logs\access.log" combined
	# 设置目录访问权限
	<Directory "F:\www\class\web\www.zfw.com\public">
	    # 指定目录启用特性
	    Options Indexes FollowSymLinks 
	    # 是否允许使用.htaccess文件
	    AllowOverride All
	    # 访问目录权限 apache2.4
	    Require all granted
	</Directory>
</VirtualHost>

伪静态

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.PHP [L]
</IfModule>

配置数据库连接

env文件

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=wwwzfwcom
DB_USERNAME=root
DB_PASSWORD=root
//前缀
DB_PREFIX=zfw_

新建数据库

数据库 字符集 排序规则
mysql utf8mb4 urf8mb4_unicode_ci

本地化配置

设置中文配置: config/app.php

# 时区
'timezone' => 'PRC',
# 验证提示中文
'locale' => 'zh-CN',
# faker中文
'faker_locale' => 'zh_CN',

中文验证

https://github.com/caouecs/Laravel-lang/tree/master/src/
https://packagist.org/packages/laravel-lang/lang#3.0.9/
https://laravel-lang.com/

语言包
composer require laravel-lang/lang
https://blog.csdn.net/qq_40829735/article/details/118038006
删除旧的安装新的

composer remove laravel-lang/publisher laravel-lang/lang laravel-lang/attributes laravel-lang/http-statuses

直接安装

composer require laravel-lang/common --dev
# 添加
php artisan lang:add zh_CN
# 更新
php artisan lang:update
# 使用 publish 来发布语言包
php artisan lang:publish

可省略--- 将 zh_CN 语言包从 vender里面拿出来 放到 resources/lang

安装验证码扩展

地址: https://packagist.org/packages/mews/captcha

Composer方法安装代码依赖包:

composer require mews/captcha

配置

修改配置文件:config/app.php
适用于 Laravel 5.1+

 'providers' => [
         // ... 
        Mews\Captcha\CaptchaServiceProvider::class,
    ]

  'aliases' => [
         // ... 
        'Captcha' => Mews\Captcha\Facades\Captcha::class,
    ]

自定义设置
php artisan vendor:publish
选择Captcha
config/captcha.php

return [
     'default'    => [
        //验证码长度
         'length'     => 5 ,
         'width'      => 120 ,
         'height'     => 36 ,
         'quality'    => 90 ,
         'math'       => true ,   //启用数学验证码
        'expire '     => 60 ,     //验证码过期
    ],
    // ... 
];

禁用验证

要禁用验证码验证,请使用CAPTCHA_DISABLE环境变量。例如.env配置:
CAPTCHA_DISABLE = true

用法示例

//返回url
captcha_src();
Captcha::src();
<!-- 在模板中使用 -->
<!-- 其他用法跟校验 看官方文档 -->
<form action="{{ url->current() }}" method="post"> 
    <!-- .... -->
    <input type='text' name='captcha' value=''> <img src="{{ captcha_src() }}">

    <input type='submit'>
</form>
    //表单验证
    $validateData=$this->validate($request,[
        'captcha'=>'required|captcha'
    ]);
    if($validateData->fails()){
        //验证失败
        return redirect('admin/login')->withErrors($validateData)->withInput();
    }

分页功能

https://learnku.com/docs/laravel/10.x/pagination/14884#b05120

php代码

//每页展示的数量
$pagesize=5;
$data=Db::table('xrshop')->paginate($pagesize);
return view('admin.list',compact('data'))

前端视图

<div class="container">
    @foreach ($users as $user)
        {{ $user->name }}
    @endforeach
</div>
{{ $users->links() }}
<!-- 调整分页链接窗口 控制每侧显示多少个链接 -->
{{ $users->onEachSide(5)->links() }}

分页功能 多条件查询的时候要把旧的的查询内容通过appends()来传入

@if(!empty($old))
{{--            {!! $users->appends($old)->render() !!}--}}
    {{ $users->appends($old)->links() }}
@else
    {{ $users->links() }}
@endif

返回json数据注意事项

使用这种括号 {!! !!}

var items = {!!  json_encode($items) !!};
var items = {!!  json_encode($users->toArray()['data']) !!};

注意,外层不要加引号。相当于拼接字符串构成一行代码。
这里用到了 Laravel Blade 模板的取消转义功能
否则,json 中的引号会被转义

[{"appointment_date":"2017-12-28","appointment_price":56465},{"appointment_date":"2018-01-3","appointment_price":654}]

设置默认样式 使用Bootstrap

App\Providers\AppServiceProvider 使用boot方法
后可以直接引入Bootstrap的样式文件来显示效果或者选择下面修改css样式

use Illuminate\Pagination\Paginator;
/**
 * 引导应用程序服务
 */
public function boot(): void
{
    Paginator::useBootstrapFive();
    Paginator::useBootstrapFour();
}

前端修改样式

<style>
    #pull_right{
        text-align:center;
    }
    .pull-right {
        /*float: left!important;*/
    }
    .pagination {
        display: inline-block;
        padding-left: 0;
        margin: 20px 0;
        border-radius: 4px;
    }
    .pagination > li {
        display: inline;
    }
    .pagination > li > a,
    .pagination > li > span {
        position: relative;
        float: left;
        padding: 6px 12px;
        margin-left: -1px;
        line-height: 1.42857143;
        color: #428bca;
        text-decoration: none;
        background-color: #fff;
        border: 1px solid #ddd;
    }
    .pagination > li:first-child > a,
    .pagination > li:first-child > span {
        margin-left: 0;
        border-top-left-radius: 4px;
        border-bottom-left-radius: 4px;
    }
    .pagination > li:last-child > a,
    .pagination > li:last-child > span {
        border-top-right-radius: 4px;
        border-bottom-right-radius: 4px;
    }
    .pagination > li > a:hover,
    .pagination > li > span:hover,
    .pagination > li > a:focus,
    .pagination > li > span:focus {
        color: #2a6496;
        background-color: #eee;
        border-color: #ddd;
    }
    .pagination > .active > a,
    .pagination > .active > span,
    .pagination > .active > a:hover,
    .pagination > .active > span:hover,
    .pagination > .active > a:focus,
    .pagination > .active > span:focus {
        z-index: 2;
        color: #fff;
        cursor: default;
        background-color: #428bca;
        border-color: #428bca;
    }
    .pagination > .disabled > span,
    .pagination > .disabled > span:hover,
    .pagination > .disabled > span:focus,
    .pagination > .disabled > a,
    .pagination > .disabled > a:hover,
    .pagination > .disabled > a:focus {
        color: #777;
        cursor: not-allowed;
        background-color: #fff;
        border-color: #ddd;
    }
    .clear{
        clear: both;
    }
</style>

展示效果
Alt text

artisan常用指令

安装
composer require laravel/tinker
phpstorm 可以通过 ctrl+shift+x 通过配置运行命令来查看更多的指令信息

常用

//运行服务
php artisan serve
//生成模块
php artisan make:model 
//生成控制器
php artisan make:controller
//生成资源路由控制
php artisan make:controller PhotoController -r
php artisan make:controller PhotoController --resource
//生成中间件
php artisan make:middleware
//显示路由信息
php artisan route:list
//筛选路由信息
php artisan route:list name=admin
//创建新的命令类
php artisan make:command Tests
//创建后使用命令
php artisan app:tests
// 服务提供者
php artisan make:provider RiakServiceProvider

数据迁移


# 生成数据迁移文件
php artisan make:migration create_flights_table
# 执行数据迁移
php artisan migrate
# 查看执行了那些迁移
php artisan migrate:status
# 执行强制迁移
php artisan migrate --force
# 回滚迁移
php artisan migrate:rollback
# 回滚5部
php artisan migrate:rollback --step=5
# 会回滚应用已运行过的所有迁移:
php artisan migrate:reset
# 首先会回滚已运行过的所有迁移,随后会执行migrate 
php artisan migrate:refresh
# 重置数据库,并运行所有的 seeds...
php artisan migrate:refresh --seed

数据填充

# 生成的 seeders 都放在 database/seeders
php artisan make:seeder UserSeeder
# 运行命令
php artisan db:seed
#  选项来指定一个特定的填充类:
php artisan db:seed --class=UserSeeder
# 这将删除数据库中所有表并重新运行所有迁移。此命令对于完全重建数据库非常有用
php artisan migrate:fresh --seed
# --seed 选项可以用来指定要运行的填充文件
php artisan migrate:fresh --seed --seeder=UserSeeder 
# 在生成环境中强制运行填充命令
php artisan db:seed --force

表单验证

快速开始

简单示例

/**
 * 存储一篇新的博客文章。
 */
public function store(Request $request): RedirectResponse
{
    $validated = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);
    // 博客文章验证通过...
    return redirect('/posts');
}

在首次验证失败时停止运行

$request->validate([
    'title' => 'bail|required|unique:posts|max:255',
    'body' => 'required',
]);

如果传入的 HTTP 请求包含「嵌套」参数,你可以在验证规则中使用. 语法来指定这些参数:

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'author.name' => 'required',
    'author.description' => 'required',
]);

另外,如果你的字段名称包含点,则可以通过使用反斜杠将点转义,以防止将其解释为. 语法:

$request->validate([
    'title' => 'required|unique:posts|max:255',
    'v1\.0' => 'required',
]);

显示验证错误信息

<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
<!-- Create Post Form -->

回填表单

当 Laravel 由于验证错误而生成重定向响应时,框架将自动将所有请求的输入闪存到 session 中。这样做是为了方便你在下一个请求期间访问输入,并重新填充用户尝试提交的表单。

$title = $request->old('title');

Blade 模板中直接使用old 来获取

<input type="text" name="title" value="{{ old('title') }}">

表单请求验证

创建表单请求

php artisan make:request StorePostRequest
在目录 app/Http/Requests
如果此目录不存在 运行 php artisan make:request 创建该目录
常用的就是前三种

class ew extends FormRequest
{
    /**
     * 确定用户是否有权提出此请求。
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * 获取应用于请求的验证规则。
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ];
    }
        //自定义验证错误信息
    public function messages(): array
    {
        return [
            'title,required'=>'标题移动要写',
        ];
    }
    //获取验证错误的自定义属性
    //重写 attributes 方法来指定自定义名称。此方法应返回属性 / 名称对的数组:
    public function attributes(): array
    {
        return [
            'email' => 'email address',
        ];
    }

    use Illuminate\Support\Str;

    /**
     * 准备验证数据。
     * 如果您需要在应用验证规则之前修改或清理请求中的任何数据,您可以使用
     */
    protected function prepareForValidation(): void
    {
        $this->merge([
            'slug' => Str::slug($this->slug),
        ]);
    }

    use Illuminate\Support\Str;

    /**
     * 处理已通过的验证
     */
    protected function passedValidation(): void
    {
        $this->replace(['name' => 'Taylor']);
    }
}


简单使用示例

使用依赖注入来实现自动验证 不需要在控制器中添加任何逻辑验证

/**
 * 存储新博客文章。
 */
public function store(StorePostRequest $request): RedirectResponse
{
    // 传入的请求有效...

    // 检索已验证的输入数据...
    $validated = $request->validated();

    // 检索已验证的输入数据的一部分。。。
    $validated = $request->safe()->only(['name', 'email']);
    $validated = $request->safe()->except(['name', 'email']);

    // 存储博客文章...

    return redirect('/posts');
}

在表单请求后添加钩子

use Illuminate\Validation\Validator;

/**
 * 配置验证实例。
 */
public function withValidator(Validator $validator): void
{
    $validator->after(function (Validator $validator) {
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });
}

配置选项

//表示验证器是否应在第一个规则失败时停止。
protected $stopOnFirstFailure = true;
// 如果验证失败,用户应重定向到的 URI。
protected $redirect = '/dashboard';
// 如果验证失败,用户应该重定向到的路由。
protected $redirectRoute = 'dashboard';

手动创建验证器

示例

use Validator;

public function store(Request $request): RedirectResponse
{
    $validateData = Validator::make($params, [
        //验证规则
        'username' => 'required|between:4,18',
        'password' => 'required|between:4,18|alpha_dash',
    ], [
        //错误信息
        'username.between' => '用户名要在4到18位',
        'password.between' => '密码要在4到18位',
    ]);

     if ($validateData->fails()) {
        //如果出现错误 跳转页面并返回错误信息
        return redirect('admin/login')
            ->withErrors($validateData)
            ->withInput();
    }
   // 获取验证后的输入...
        $validated = $validator->validated();

        // 获取验证后输入的一部分...
        $validated = $validator->safe()->only(['name', 'email']);
        $validated = $validator->safe()->except(['name', 'email']);

        // 存储博客文章...

        return redirect('/posts');
    
}

自动重定向

Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validate();

命名错误包

Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validateWithBag('post');

如果您在同一页上有多个表单,您可能希望为包含验证错误的 MessageBag 命名,以便检索特定表单的错误消息。为此,将名称作为第二个参数传递给 withErrors:
return redirect('register')->withErrors($validator, 'login');
你可以通过 $errors 变量访问命名后的 MessageBag 实例:
{{ $errors->login->first('email') }}

返回已验证的数据

$validated = $request->validated();
$validated = $validator->validated();
$validated = $request->safe()->only(['name', 'email']);
$validated = $request->safe()->except(['name', 'email']);
$validated = $request->safe()->all();
// 迭代验证数据...
foreach ($request->safe() as $key => $value) {
    // ...
}
// 访问验证数据数组...
$validated = $request->safe();
$email = $validated['email'];
// merge 方法可以给验证过的数据添加额外的字段:
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);
//方法以 collection 实例的形式来检索验证的数据:
$collection = $request->safe()->collect();

错误信息

//  first方法返回给定字段的第一条错误信息:
$errors = $validator->errors();
echo $errors->first('email');
// get检索一个给定字段的所有错误信息,返回值类型为数组
foreach ($errors->get('email') as $message) {
    // ...
}
//对于数组表单字段,可以使用 * 来检索每个数组元素的所有错误信息:
foreach ($errors->get('attachments.*') as $message) {
    // ...
}
//于检索所有字段的所有错误信息,返回值类型为数组:
foreach ($errors->all() as $message) {
    // ...
}
//方法可用于确定一个给定字段是否存在任何错误信息:
if ($errors->has('email')) {
    // ...
}

常用的验证规则

https://learnku.com/docs/laravel/10.x/validation/14856#189a36

required 
//不能为空
between:min,max
//待验证字段值的大小必须介于给定的最小值和最大值(含)之间。字符串、数字、数组和文件的计算方式都使用 size 方法。
boolean
//验证的字段必须可以转换为 Boolean 类型。 可接受的输入为 true, false, 1, 0, 「1」, 和 「0」。
confirmed
//用在确认密码
//验证字段必须与 {field}_confirmation 字段匹配。例如,如果验证字段是 password,则输入中必须存在相应的 password_confirmation 字段。
current_password
// 验证字段必须与已认证用户的密码匹配
date
//验证字段必须是 strtotime PHP 函数可识别的有效日期。
decimal:min,max
//验证字段必须是数值类型,并且必须包含指定的小数位数:
// 必须正好有两位小数(例如 9.99)...
'price' => 'decimal:2'
// 必须有 2 到 4 位小数...
'price' => 'decimal:2,4'

email
//验证的字段必须符合 e-mail 地址格式
'enum'
//规则是一种基于类的规则,用于验证被验证字段是否包含有效的枚举值
//Enum 规则的构造函数只接受枚举的名称作为参数:
image
//正在验证的文件必须是图像(jpg、jpeg、png、bmp、gif、svg 或 webp)
in:foo,bar,…
// 验证字段必须包含在给定的值列表中  由于此规则通常要求你 implode 数组
integer
//验证的字段必须是一个整数。
ip
//验证的字段必须是一个 IP 地址。
ipv4
////验证的字段必须是一个 IPv4 地址。
ipv6
//验证的字段必须是一个 IPv6 地址。
json
//验证的字段必须是一个有效的 JSON 字符串。
max:value
//验证的字段的值必须小于或等于最大值 value。字符串、数字、数组和文件的处理方式与 size 规则相同。
min:value
//验证的字段的值必须大于或等于最小值 value。字符串、数字、数组和文件的处理方式与 size 规则相同。
not_in:foo,bar,…
//验证的字段不能包含在给定值列表中。可以使用 Rule::notIn 方法流畅地构建规则:
regex:pattern
// 验证的字段必须匹配给定的正则表达式。

// 在内部,此规则使用 PHP 的 preg_match 函数。指定的模式应遵循 preg_match 所需的相同格式,并且也包括有效的分隔符。例如:'email' => 'regex:/^.+@.+$/i'。

size:value
// 验证的字段必须具有与给定的_value 相匹配的大小。
// 对于字符串数据,value 对应于字符数。
// 对于数字数据,value 对应于给定的整数值(该属性还必须具有 numeric 或 integer 规则)。
// 对于数组,size 对应于数组的 count。
// 对于文件,size 对应于文件大小(以千字节为单位)
string
// 验证的字段必须是一个字符串。如果您希望允许字段也可以为 null,则应将 nullable 规则分配给该字段。
unique:table,column
// 验证字段在给定的数据库表中必须不存在。
uppercase
// 验证字段必须为大写。
url
// 验证字段必须为有效的 URL。
ulid
// 验证字段必须为有效的通用唯一词典排序标识符(ULID)。
uuid
// 验证字段必须为有效的 RFC 4122(版本 1、3、4 或 5)通用唯一标识符(UUID)。


强制唯一规则忽略给定的 ID:

有时,您可能希望在唯一验证期间忽略给定的 ID。例如,考虑一个 “更新个人资料” 屏幕,其中包括用户的姓名、电子邮件地址和位置。您可能希望验证电子邮件地址是否唯一。但是,如果用户仅更改了名称字段而未更改电子邮件字段,则不希望因为用户已经拥有相关电子邮件地址而抛出验证错误。

要指示验证器忽略用户的 ID,我们将使用 Rule 类来流畅地定义规则。在此示例中,我们还将指定验证规则作为数组,而不是使用 | 字符来分隔规则:

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);
//不需要将模型键的值传递给 ignore 方法,您也可以传递整个模型实例。Laravel 将自动从模型中提取键:
Rule::unique('users')->ignore($user)
//如果您的表使用的是除 id 以外的主键列名,可以在调用 ignore 方法时指定列的名称:
Rule::unique('users')->ignore($user->id, 'user_id')
//默认情况下,unique 规则将检查与正在验证的属性名称匹配的列的唯一性。但是,您可以将不同的列名称作为第二个参数传递给 unique 方法:
Rule::unique('users', 'email_address')->ignore($user->id)
//您可以通过自定义查询并使用 where 方法来指定其他查询条件。例如,让我们添加一个查询条件,将查询范围限定为仅搜索具有 account_id 列值为 1 的记录:
'email' => Rule::unique('users')->where(fn (Builder $query) => $query->where('account_id', 1))

有条件添加规则

当字段具有特定值时跳过验证
有时,您可能希望在给定字段具有特定值时不验证另一个字段。您可以使用 exclude_if 验证规则来实现这一点。在下面的示例中,如果 has_appointment 字段的值为 false,则不会验证 appointment_date 和 doctor_name 字段:

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($data, [
    'has_appointment' => 'required|boolean',
    'appointment_date' => 'exclude_if:has_appointment,false|required|date',
    'doctor_name' => 'exclude_if:has_appointment,false|required|string',
]);

或者,您可以使用 exclude_unless 规则,除非另一个字段具有给定值,否则不验证给定字段:

$validator = Validator::make($data, [
    'has_appointment' => 'required|boolean',
    'appointment_date' => 'exclude_unless:has_appointment,true|required|date',
    'doctor_name' => 'exclude_unless:has_appointment,true|required|string',
]);

仅在字段存在时验证
在某些情况下,您可能希望仅在验证数据中存在该字段时才对该字段运行验证检查。要快速实现此操作,请将 sometimes 规则添加到您的规则列表中:

$v = Validator::make($data, [
    'email' => 'sometimes|required|email',
]);

加密和验证

$str = '123456'
//  哈希加密
$hash=\Hash::make($str);
//快速使用
$hash=bcrypt('$str');
//哈希验证
\Hash::check($str,$hash);


生成url

生成基础url

$post = App\Models\Post::find(1);

echo url("/posts/{$post->id}");

// http://example.com/posts/1

访问当前 URL

// 获取当前 URL 没有 query string...
echo url()->current();
// 获取当前 URL 包括 query string...
echo url()->full();
// 获取上个请求 URL
echo url()->previous();

use Illuminate\Support\Facades\URL;
echo URL::current();

route 函数

Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
    // ...
})->name('comment.show');

echo route('comment.show', ['post' => 1, 'comment' => 3]);

// http://example.com/post/1/comment/3

CSRF请求

页面中 ajax请求

<meta name="csrf-token" content="{{ csrf_token() }}">
<script>
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
</script>

表单

<form method="POST" action="/profile">
    @csrf

    <!-- 相当于。。。 -->
    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
</form>

模型关联

多对多

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Role extends Model
{
    /**
     * 拥有此角色的用户
     */
    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class);

        //第一个个参数  关联的表
        //第二个参数传递给 中间表的表名
        //第三个参数是定义此关联的模型在连接表里的外键名,
        //第四个参数是另一个模型在连接表里的外键名:
        return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
    }
}

访问

use App\Models\User;

$user = User::find(1);

foreach ($user->roles as $role) {
    // ...
    //中间表字段
    echo $role->pivot->created_at;
}

使用预加载访问

User::with('roles')->find(1)

使用自定义名称 访问中间表数据

$users = User::with('podcasts')->get();
foreach ($users->flatMap->podcasts as $podcast) {
    echo $podcast->subscription->created_at;
}

访问器 修改器 看文档

数据库操作

事务

use Illuminate\Support\Facades\DB;
//开启事务
DB::beginTransaction();
// 回滚
DB::rollBack();
// 提交
DB::commit();

transaction 可以自动进行提交和回滚
出错会抛出异常

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');

    DB::delete('delete from posts');
}, 5);

删除

//删除
use App\Models\Flight;
$flight = Flight::find(1);
$flight->delete();

//通过查询删除 不会报错
RolePrem::where('role_id',$id)->delete();

//通过主键删除 不存在会报错
Flight::destroy(1);
Flight::destroy(1, 2, 3);
Flight::destroy([1, 2, 3]);
//删除所有模型关联的数据库记录
Flight::truncate();

添加扩展

php artisan make:provider DBServiceProvider
文件路径在 app/provider

use Illuminate\Database\Query\Builder  as QueryBuilder;
public function boot(): void
{
    // 将数据的索引设置 $index
    QueryBuilder::macro('abbbc', function ($index) {
        // echo '扩展的方法';
        $res =   $this->get()->toArray();
        $result = [];
        foreach($res as $val){
            $result[$val->$index] = $val;
        }
        return $result;
    });
}

注册到 config\app里面

'providers' => ServiceProvider::defaultProviders()->merge([
//   ...
    App\Providers\DBServiceProvider::class,
])->toArray(),

使用示例

 $cates=DB::table('article_cate')->abbbc('id');
//  将数据的索引设置为 id ;

所有视图共享数据

在服务提供器的boot方法
在后面所有的视图都可以访问
或者在父控制器里面添加

view()->share('cate',$cate);

使用Redis缓存

安装
composer require predis/predis
配置 .env 文件
CACHE_DRIVER=redis
配置 config/databases 文件

'redis' => [
    'client' => env('REDIS_CLIENT', 'predis'),
    // ...
],

助手函数

cache($key) //获取缓存
cache([$key=>$value]) //设置缓存

简单示例

public function index()
{
    $cache_key = 'article_cid';
    $data=cache($cache_key);
    if($data){
        dump($data);
        return ;
    }
    $data=DB::table('article')->where('cid',21)->paginate(20);
    cache([$cache_key=>$data]);
    dump('数据已经缓存');
}

文件存储

保存文件$request->file("file")->store('public/imgs')

软连接 php artisan storage:link 会自动生成软连接
访问静态文件需要通过软链接来访问
配置文件 config\filesystems.php

'links' => [
    public_path('storage') => storage_path('app/public'),
],
// 软连接地址     

比如 真实地址在 app/public/123.png
实际请求要通过映射地址 storage/123.png 来访问

faker 批量添加用户

创建用户的数据填充文件
php artisan make:seeder UserSeeder
路径:
database/seeders/UserSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\User;
use phpDocumentor\Reflection\Types\ContextFactory;

class UserSeeder extends Seeder
{
    public function run()
    {
        //清空user数据
        User::truncate();
//        factory(User::class,100)->create();
//使用数据工厂填充100ci 
        User::factory()->count(100)->create();
        //将id为1的用户修改为admin
        User::where('id',1)->update(['username'=>'admin']);
    }
}

生成一个数据工厂
php artisan make:factory UserFactory -m Models/User
路径
database/factories/UserFactory.php

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class UserFactory extends Factory
{
    public function definition()
    {
        return [
            'username'=>$this->faker->userName,
            'truename'=>$this->faker->name(),
            'password'=>bcrypt('admin888'),
            'email'=>$this->faker->email,
            'phone'=>$this->faker->phoneNumber,
            'sex'=>['男','女'][rand(0,1)]
        ];
    }
}

路径
database/seeders/DatabaseSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Database\Seeders\UserSeeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
//         \App\Models\User::factory(10)->create();
        //调用生成管理员数据表
        $this->call([UserSeeder::class]);
        $this->call([ArticleSeeder::class]);
    }
}

执行填充

php artisan db:seed

注:迁移文件中字段可能设置有点短,可能填充不成功,此时,就需要修改一下数据字段长度,然后执行
php artisan migrate:refresh --seed

执行migrate 报错

SQLSTATE[42000]的解决方式
博客
https://blog.csdn.net/hj960511/article/details/106735377

auth登录

// 登录  返回true 或 false
auth()->attempt([数组 账号和密码]);
// 检查是否登录  true/false
auth()->check(); 
// 登录成功得到用户信息
auth()->user()  // 用户模型
// 退出就是清空session的过程
auth()->logout()//用户退出

laravel 10 下载好自带一个用户模型,里面有默认的配置,可以修改
修改用户模型的父类
Alt text
配置config/auth.php文件
Alt text

路由

Route::prefix('/admin/')->name('admin.')->group(function (){
    //登录页面
    Route::get('login',[LoginController::class,'index'])->name('login');
    //登录请求
    Route::post('login',[LoginController::class,'login'])->name('login');
        //资源路由
        //权限路由
//        Route::resource('roless',RoleController::class);
//        Route::resource('role', RoleController::class);
        Route::resource('role',RoleController::class);
        //节点管理
        Route::resource('node',NodeController::class);

});

中间件

文件夹
app/Http/Middleware
注册路径
app/Http/Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    //全局中间件
    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
    ];
    // 路由中间件 注册给单独的路由文件 相当于一整个路由文件都有
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
        ]
    ];
    //应用中间件可添加名称 可绑定给单个路由或者控制器
    protected $middlewareAliases = [
        'auth' => \App\Http\Middleware\Authenticate::class,
    ];
}

在控制器中绑定

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;

class LoginController extends Controller
{
    //
    public function __construct()
    {
        $this->middleware(['ckadmin']);
        //传参
        $this->middleware(['ckadmin:login']);
    }
}

//中间件获取传递的参数
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckAdminLogin
{
    public function handle(Request $request, Closure $next,$param=null): Response
    {
        dump($param);
        return $next($request);
    }
}

自定义验证规则

验证更复杂的内容 并且在 validate 方法里面统一校验的时候
在改路径上写代码
app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema; //第一处
use Validator;

class AppServiceProvider extends ServiceProvider
{

    public function register()
    {
        //
    }

    public function boot()
    {
        // 使用数据库迁移报错
        Schema::defaultStringLength(191);
        // 自定义验证规则
        // 参数1 规则名
        Validator::extend('phone', function ($attribute, $value, $parameters, $validator) {
//            返回 true/false
            $reg1 = '/^\+86-1[3-9]\d{9}$/';
            $reg2 = '/^1[3-9]\d{9}$/';

            return preg_match($reg1,$value) || preg_match($reg2,$value);
        });

    }
}

在语言文件中配置报错信息
resources/lang/zh_CN/validation.php

//添加改字段
return[
    'phone' => ':attribute 号码不合法',
    // 验证字段名称
    'attributes' => [
        // 自定义规则名称 对应的 中文
        'phone' => '手机',
    ]
]

软删除

第1条件:表中必须有一个软删除标识字段
migrations 文件下 一个简单的示例

<?php

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

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('role_id')->default(0)->comment('角色ID');
            $table->string('username',50)->comment('账号');
            $table->string('truename',50)->default('未知')->comment('真实姓名');
            $table->string('password',255)->comment('密码');
            //可以为空
            $table->string('email',50)->nullable()->comment('邮箱');
            $table->string('phone',15)->default('')->comment('手机号码');
            $table->enum('sex',['男','女'])->default('男')->comment('性别');
            $table->char('last_ip',15)->default('')->comment('登录ip');
            $table->timestamps();
            //软删除 生成一个 deleted_at字段
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

第2条件:模型中引入对就的操作 (trait) 实现多继承

第3条件:模型中指定软删除的标识字段

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as AuthUser;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends AuthUser
{
    use HasFactory;
 
    // 2 调用定义的trait类 和继承效果一样
    use SoftDeletes;
    // 3 软删除标识字段
    protected $dates = ['deleted_at'];
    // 设置添加的字段  create 添加数据有效的
    // 拒绝不添加的字段
    protected $guarded = [];
    //隐藏的字段
    protected $hidden = ['password'];
}

使用邮件功能

邮件发送类 Mail 类

文本
静态方法 raw();

富文本
静态方法 send()

实现发送邮件,必须一个发送邮件的账号,需要开启stmp协议,现在主流的邮件服务器都是支持,stmp默认端口25,但是它们默认没有打开,需要使用时,自行打开。
以QQ邮箱为例: https://mail.qq.com

Alt text

Alt text
Alt text

得到相关的配置信息
https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=371

Alt text

配置laravel发送邮件配置

.env文件

MAIL_MAILER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
MAIL_USERNAME=用户名
MAIL_PASSWORD=密码
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=用户名
MAIL_FROM_NAME="${APP_NAME}"
// 发送文本
/*  \Mail::raw('测试一下发邮件',function (\Illuminate\Mail\Message $message){
//                 获取回调方法中的形参数
    //dump(func_get_args());
    $message->to('779245779@qq.com');
    $message->subject('测试邮件');

});*/

//发送富文本邮件
//参数1 模板视图
//参数2 传给视图数据
\Mail::send('mail.adduser',['user'=>'张三'],function (\Illuminate\Mail\Message $message){
//发给谁
$message->to('779245779@qq.com');
//                主题
$message->subject('测试邮件');
});

搜索功能

使用模型查询中的when方法

    public function index(Request $request)
    {

       //分页
        // 有 name参数的时候查询 like name 没有的时候正常查询所有的表
        $name = $request->get('name');
        $data =Role::when($name,function ($query)use ($name) {
            $query->where('name','like',"%{$name}%");
        })->paginate($this->pagesize);

        //$data = Role::paginate($this->pagesize);

        return view('admin.role.index',compact('data','name'));

    }

使用querylist来实现文章的采集

官网:http://www.querylist.cc/

安装

composer require jaeger/querylist

设置计划任务

上传代码到服务器 linux
手动执行 php php文件

#crontab
# 分 时 日 月 星期 脚本
#每天凌晨1点抓取文章信息 /dev/null 黑洞
# 成功说失败都不显示

excel导出功能

批量将房东信息数据导出成excel下载到本地,在laravel使用第3方插件库来完成此项工作。
插件库:https://packagist.org/packages/maatwebsite/excel
官网:https://docs.laravel-excel.com/3.1/getting-started/
导出步骤:https://docs.laravel-excel.com/3.1/exports/

安装对应的phpexcel插件
composer require maatwebsite/excel

高德地图实现经纬度转换

添加房源需要和多张表有关联,模型关系一个要提前建立起来。前端使用jquery_validate进行表单有效性验证,后台使用laravel的表单验证进行数据服务器端有效性验证。
房源添加还需要接入第3方接口平台获取房源所在的经纬度,为日后在地图中标识有一个数据标识。本次使用高德开放平台来接入:https://lbs.amap.com/

后台人员填写完房源详情地址后,由此地址转为,电子地图中的经纬度。从而方便日后前台在电子地图中的标识显示。
高德地图开放平台:https://lbs.amap.com/

注:需要注册成为开发者,注册成功后就可以使用此开放平台。

注册成功后,登录开发放平台,进入后台。
需要创建一个新的应用

Alt text
Alt text
创建应用成功后,需要添加一个key
Alt text
得到请求的key
Alt text
注:此key是日后,请求api所用的key,一定要保存好
api地址:https://lbs.amap.com/api/webservice/guide/api/georegeo/
由此api,把地址转为经纬度
Alt text
实现地址转换
在config目录添加一个高德接口配置文件,配置地址转换的URL,把使用占位符.
Alt text

orm事件为生命周期

什么时机发送消息给两个客户?
添加入库成功后,发送消息给两个客户
在laravel在写控制中,还是写在别的地方?
 从业务代码可维护成本上来说,分离代码是是更好的维护,所以一般不写在控制器中.

 laravel提供orm操作中,就有一个模型事件,可以利用此事件,添加对应的操作代码。
 用前段话来说,可以理解orm事件为生命周期。


同步的发送还是异步的发送
同步: 添加入库成功后,就直接发送消息出去,消息发送成功后,才跳转到列表页面。
异步: 添加入库成功后,不一定直接就发送消息出去,等到服务器不太忙或者有一个别的程序监听,像这样发送消息的工作,交给监听程序来完成。 
php中如何来实现工作的异步执行?
	使用消息队列 

添加模型事件监听

使用artisan命令来添加模型观察事件

此命令是laravel5.5之后才有的,之前想要有此功能,手动创建目录和文件

php artisan make:observer NoticeObserver -m Models/Notice

生成的文件路由

app/Observers/NoticeObserver.php

里面有5个生命周期的方法 增,删,改,恢复,强制删除

需要注册到关联的的模型中

app/Models/Notice.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use App\Observers\NoticeObserver;
class Notice extends Model
{
    use HasFactory;

    protected static function boot()
    {
        parent::boot(); // TODO: Change the autogenerated stub
        //注册自定义观察类
        self::observe(NoticeObserver::class);
    }

}

此时在调用对应模型的方法时会触发生命周期

使用消息队列

根据上图,首先创建消息管道,来存储任务。本次使用mysql表来当消息管道。
创建容器数据表

php artisan queue:table   任务队列表
php artisan queue:failed-table  执行任务失败后,存储的表

php artisan migrate  执行迁移

在.env文件中设置框架异步

在config目录中查看laravel默认支持的消息队列驱动

设置database

Alt text

修改.env

Alt text

创建任务

php artisan make:job xxx

在文件中 app/Jobs/NoticeJob.php

写入要工作的内容

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class NoticeJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        // 写一个任务
        sleep(5);
        Log::info('------写日志-----');
    }
}

在 生命周期文件中调用

  dispatch(new NoticeJob());

成功后会在消息容器中有一个任务执行

Alt text

因为使用了laravel自带消息队列,所以消费者不需要写任务代码。

使用php artisan来消费它

php artisan queue:work

Alt text

配置passport 使用jwt

用passport实现接口的登录和jwt生成(生成token)

安装passport插件

composer require laravel/passport

执迁迁移文件,生成数据表,保存token数据

php artisan migrate

生成客户端授权码

php artisan passport:install

注:secret保存起来

修改接口账号模型
use Laravel\Passport\HasApiTokens;

Alt text

修改config/auth.php文件中的api配置

Alt text

令牌的有效期

在app/Proivders/AuthServiceProvide.php文件中的boot方法添加有效期

use Laravel\Passport\Passport;

// token认证有效期2小时
Passport::tokensExpireIn(now()->addHour(2));

// 刷新token认证有效期30天
Passport::refreshTokensExpireIn(now()->addDays(30));

Alt text

解决auth在接口中登录没有attempt问题

Alt text

实现登录,并且注意,如果登录不成功,数据返回符合restful规范。

Alt text

接口token生成

生成接口验证token在登录成功后生成。

Alt text

接口安全验证

使用了jwt进行验证
需要对接口路由绑定中间件,前提是auth.php文件中的一定要把api节点中的driver更换为passport

Alt text

在定义路由中绑定jwt认证中间件

Alt text

注:有的时候,不光光使用jwt来安全验证,还有时候还需要对内容进行加密,一般使用rsa加密。

用户访问自动清零

Alt text

前端插件

jquery.validate验证

前端验证,使用jquery.validate插件来验证
https://www.runoob.com/jquery/jquery-plugin-validate.html

Datatables是一款表格插件

使用datatables展示数据
Datatables是一款 jquery 表格插件,开源免费。Datatables是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能(分页、排序、搜索等等)。 datatables是一个操作dom的前端插件。
官网:https://datatables.net/
中文官网:http://datatables.club/

客户端分页
所有的数据给发给客户端,让客户端自己去分页
好处:服务器写代码少,简单
坏处:数据量有点大,有可能存在发送失败

一个用datatables 插件的响应数据 查询

 public function index(Request $request)
    {

        if($request->isXmlHttpRequest()){

            //获取排序 是升还是降序 和排序的列数
            ['column'=>$column,'dir'=>$dir]=$request->get('order')[0];
            //获取排序的 字段
            $orderField=$request->get('columns')[$column]['data'];

            //ajax请求
            //开启位置
            $start=$request->get('start',0);
            //开始时间
            $datemin = $request->get('datemin');
            //结束时间
            $datemax = $request->get('datemax');
            //搜索关键词
            $title = $request->get('title');

            //查询对象
            $query = Article::where('id','>',0);
            //当开始 时间跟结束时间都存在的时候
            if(!empty($datemin) && !empty($datemax)){
                //修改开始时间格式  添加 时分秒
                $datemin =  date('Y-m-d H:i:s',strtotime($datemin.' 00:00:00'));
                //修改开始时间格式  添加 时分秒
                $datemax =  date('Y-m-d H:i:s',strtotime($datemax.' 23:59:59'));


                //查询创建在创建时间中的信息
                $query->whereBetween('created_at',[$datemin,$datemax]);
            }

            //关键词存在 搜索关键词
            if(!empty($title)){
                $query->where('title','like',"%{$title}%");
            }
            //取个最小值 如果数量大于100 如果没有这个变量默认给个10
            $lenght=min(100,$request->get('length',10));
            //记录总数
            $count = $query->count();
            //获取数据
            $data= $query->orderBy($orderField,$dir)->offset($start)->limit($lenght)->get()->toArray();

            /*
            draw: 客户端调用服务器端次数标识
            recordsTotal: 获取数据记录总条数
            recordsFiltered: 数据过滤后的总数量
            data: 获得的具体数据
            注意:recordsTotal和recordsFiltered都设置为记录的总条数
            */
            $result = [
                'draw' => $request->get('draw'),
                'recordsTotal' => $count,
                'recordsFiltered' => $count,
                'data' => $data
            ];

            return json_encode($result);
        }
        //取出所有的文章数据
        $data=Article::all();

        return view('admin.article.index');
    }

ueditor来作为富文本工具

https://fex-team.github.io/ueditor/#server-php

webuploader文件上传

官网:https://fex.baidu.com/webuploader/

下载地址:https://github.com/fex-team/webuploader/releases

echarts可视

可视化的显示在登录成功后进入的欢迎页面中显示,使用echarts来显示图表。
官网:https://echarts.baidu.com/
下载对应的echarts源码包:https://www.echartsjs.com/zh/download.html

简单上手:https://www.echartsjs.com/zh/tutorial.html

posted on 2024-01-11 17:05  xirang熙攘  阅读(21)  评论(0编辑  收藏  举报