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
安装
配置命令行工具
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>
展示效果
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 下载好自带一个用户模型,里面有默认的配置,可以修改
修改用户模型的父类
配置config/auth.php文件
路由
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
得到相关的配置信息
https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=371
配置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来实现文章的采集
安装
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/
注:需要注册成为开发者,注册成功后就可以使用此开放平台。
注册成功后,登录开发放平台,进入后台。
需要创建一个新的应用
创建应用成功后,需要添加一个key
得到请求的key
注:此key是日后,请求api所用的key,一定要保存好
api地址:https://lbs.amap.com/api/webservice/guide/api/georegeo/
由此api,把地址转为经纬度
实现地址转换
在config目录添加一个高德接口配置文件,配置地址转换的URL,把使用占位符.
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
修改.env
创建任务
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());
成功后会在消息容器中有一个任务执行
因为使用了laravel自带消息队列,所以消费者不需要写任务代码。
使用php artisan来消费它
php artisan queue:work
配置passport 使用jwt
用passport实现接口的登录和jwt生成(生成token)
安装passport插件
composer require laravel/passport
执迁迁移文件,生成数据表,保存token数据
php artisan migrate
生成客户端授权码
php artisan passport:install
注:secret保存起来
修改接口账号模型
use Laravel\Passport\HasApiTokens;
修改config/auth.php文件中的api配置
令牌的有效期
在app/Proivders/AuthServiceProvide.php文件中的boot方法添加有效期
use Laravel\Passport\Passport;
// token认证有效期2小时
Passport::tokensExpireIn(now()->addHour(2));
// 刷新token认证有效期30天
Passport::refreshTokensExpireIn(now()->addDays(30));
解决auth在接口中登录没有attempt问题
实现登录,并且注意,如果登录不成功,数据返回符合restful规范。
接口token生成
生成接口验证token在登录成功后生成。
接口安全验证
使用了jwt进行验证
需要对接口路由绑定中间件,前提是auth.php文件中的一定要把api节点中的driver更换为passport
在定义路由中绑定jwt认证中间件
注:有的时候,不光光使用jwt来安全验证,还有时候还需要对内容进行加密,一般使用rsa加密。
用户访问自动清零
前端插件
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