)什么是composer
|
就是一个专门管理PHP扩展包的工具 |
composer的介绍和laravel的关系
|
laravel 主要是以组件化的开发模式,也就是把整个框架拆分为不同的单独的零件。每一个零件实际上就是一个单独的组件,每一个组件你都可以在composer的资源包中查找到
|
Composer的组成 |
它主要由三个部分组成:命令行工具、包仓库、代码库 |
Composer的目录结构 |
|
直接引用第三方别人写好composer包的工具 |
$ composer global require "overtrue/package-builder" --prefer-source $ package-builder build [目标目录名]
|
laravel安装
|
1)Php版本要求7.1版本 2)Openssl秘钥的生成的扩展 3)composer create-project laravel/laravel laravel-composer(项目名)
Composer create-project xxxx (创建一个项目) Composer-builder build xxx
|
框架的主配置文件 |
laravel框架的主配置文件(数据库配置)
配置文件副本
命令行执行驱动文件 |
laravel访问
|
2)Laravel内置服务访问(php artisan server)(不推荐使用) |
Laravel执行流程
|
1)Url地址通过web.php的路由配置进行路由匹配 Route::get('winner', function () { return view('welcome'); });
2)业务逻辑分两种情况: 2.1)闭包函数,执行函数体
Route::get('winner', function () { return view('welcome',[‘name’=>’winer’] ); }); { { $name }}
2.2)控制器的操作
Route::get('hello1','Hello1@index'); Xxx/Public/hello1
Route::get(index,home\Index@index'); Xxx/home/index/index
2.3)返回视图 视图必须以.blade.php结尾 |
Artisan 快捷创建文件(控制器 模型 数据迁移等)
|
查看命令: Php artisan 创建控制器:Php artisan make:controller xxx 创建模型: Php artisan make:model xxx 创建自己的命令: php artisan make:command 文件名 --command = winner::command 执行自己的命令: php artisan command:winner |
laravel的生命周期(请求周期)
|
1)通过入口文件index.php 2)初始化整个laravel框架 (独自创立) $app = require_once __DIR__.’/../bootstrap/app.php’;
$kernel=、$app->make(Illuminate\Contracts\Http\Kernel::class); 5)处理用户的请求 $response = $kernel->handle( $request = Illuminite\Http\Request::capture() );
$response->send(); 6)结束中间件和laravel框架 $kernel->terminate( $request , $response );
|
Laravel路由文件的访问流程 |
1)在项目中,首先会通过index.php入口文件,由里面的bootstrap/app.php创建出applcation应用实例类 2)然后系统会根据route中所定义的路由生成对应的路由表 3)检测用户访问的请求路由是否合理。如果合理就会进入中间件组对请求做处理 4)然后会进入到控制器,执行用户的请求 5)请求可能会连接到数据库的操作 6)中间件有前置和后置的区分,所以在控制器返回的时候可能会有中间件组,然后经过视图渲染有index.php返回
Index.php -> Bootstrap -> Route路由-> 控制器 -> 数据库 -> 中间件 -> 视图 -> |
Tp5.2与laravel5.7的区别 对于框架的看法
|
3)路由的访问方式 (tp5:pathinfo+路由 laravel:需要先定义路由) 4)请求周期等
共同点: 1)都是mvc思想 2)扩展方便 3)ioc容器 4)aop思想
这个问题最主要的就是需要自己,在面试的时候能够清楚的描述你的观点,以及框架的主要功能点的作用 |
AOP思想(面向切面思想) |
把相同的执行操作单独提取出来 例如:短信发送,rbac
把一个共有的操作,单独抽离出来,需要用到的时候,再调用
以前会在基类中的构造函数定义一个这样的公有的方法,然后子类继承这个基类就可以使用 现在是单独提取出来 |
Laravel 核心思想
|
1)组件化开发(车间,很多小零件组成一个功能) 2)IOC容器(控制反转)(作用就是保存着运行的类的实例) 3)application (继承于容器,是laravel的心脏;是框架运行的核心,container离开laravel还可以使用,application离开的话就不行) 4)契约(通过接口的方式去约束服务,服务不规范,可以使用契约去规范) 5)门面(通过门面去介绍服务都有哪些) 6)中间件(管道机制,守护框架) |
中间件的理解 |
2)中间件分为 : 前置(进入,例如身份权限验证rbac) 后置(出去) 前置和后置中间件和 注册无关 只和``$response = $next($request);`` 代码的前后顺序有关
namespace App\Http\Middleware; use Closure; class CheckAge { public function handle($request, Closure $next) {
If( $request->age <= 200 ){ Return response(“年龄超标”) ; } // 在 $next($request)前执行的就是前置
$response = $next($request); // 闭包,controller
// 在 $next($request); 后置中间 return $response; } } ?> |
中间件的使用 |
1)定义中间件
namespace App\Http\Middleware; use Closure; class CheckAge { public function handle($request, Closure $next) { } } ?> 2)需要在 blog\app\Http\Kernel.php(核心) 进行注册 不同场景如下: 2.1)全局: Protected $middleware = { } 2.2)分组: Protected $middlewareGroup = { } 2.3)单独中间件,中间件标识,中间件类:Protected $routemiddleware = { } 2.4)中间件执行的顺序: Protected $middlewarePriority = { }
3)路由: Route::get( ‘char, function(){ Return “ 通过”; })->middleware( ‘route-char’ );
4)控制器中的使用: ```php
class UserController extends Controller { /** * Instantiate a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth');
// 允许哪些方法可以使用 $this->middleware('log')->only('index');
// 不允许哪些方法不可以使用 $this->middleware('subscribed')->except('store'); } } ?> |
服务提供者的理解 |
工具类 -- 项目中常用的方法 |
服务提供者使用 |
1)服务提供者的定义
app\http\Providers
public function register(){}
public function boot(){}
2)注册 config/app.php Providers |
容器的使用 |
1)定义 App\Util\CharUtil
Public function index(){}
2)注册 App\providers\RiakServiceProvider
美女在一个叫做 container 的app软件上注册了一个家庭地址信息 姓名 家庭地址 Public function register{ $this->app->singleton( ‘char’ , \app\Util\CharUtil :: class ) }
3)控制器使用 App\http\Controller App( ‘char’ )->char(); //给app()传递标识的时候就是 从容器中,根据标识获取到对应的服务实例 Char()就是方法 |
IOC容器 |
是什么:依赖注入 为什么需要容器:解耦
|
// 废弃 users 使用 admin类 class user{
}
// admin 功能比 user 强 class admin {
}
//使用IOC思想 class ioc { protected $bind = []; public function bind($key, $value) { $this->bind[$key] = [$value]; }
public function make($key) { return $this->bind[$key]; } }
$ioc = new ioc; $ioc->bind('admin', function (){ return new admin; });
// 控制反转 就是把一个类创建的过程,交给了第三者 class client{ protected $ioc; public function __construct() { $this->ioc = new ioc; } public function index() { $this->ioc->make('admin'); // user 创建的控制器权就归于 client 这个类 }
public function demo() { $this->ioc->make('admin'); // user 创建的控制器权就归于 index 这个类 } } //***********************************************************************
// di 方法中会以参数的方式传递 真正的实现就是通过反射机制 new index($ioc); class index{ protected $ioc;
public function __construct(ioc $ioc) // 泛型的约束;限制传递的参数的类型 { $this->ioc = $ioc; }
public function index() { $this->ioc->make('admin'); // user 创建的控制器权就归于 index 这个类 }
public function demo() { $this->ioc->make('admin'); // user 创建的控制器权就归于 index 这个类 } } |
|
进阶1:可以使用容器来存放服务类 |
Application 1)应用实例 2)项目/框架的核心 3)项目核心的应用 4)启动软件程序(需要有用户的信息,启动的方法) 5) Container只是提供的是初始方法 Application是对应用程序的注册,启动
|
Container关键点解析
|
(Application这个类继承与Container这个类) 1) $binds这是一个容器类,在里面会保存整个框架运行所需要的服务,本质上是通过key,value以数组的方式保存着实际类在里面 $binds = [ “标识” =>“实际类的对象” “route”=> new route(); ] 2) Class Container{ protected static $instance; // 单例模式 protected $instances = []; // 保存解析出来之后的实例(保存已经使用过的实例)
protected $bindings = []; // 容器绑定实例 不会立即使用 信息的注册 protected $aliases = []; // 记录类库定义的别名
public function bind(){} // 就是绑定到容器的方法
public function has(){} // 校验是否在容器中
public function getInstance(){} // 把解析出来之后的容器保存在实例中
public function make(){} // 从容器中解析 } |
门面 |
介绍服务类,这是一个可以快速从容器中调用实例类的方式 Facades 为应用的 服务容器提供了一个「静态」 接口 |
门面的使用 |
1)门面类的定义 app\Facade\char Class char extends Facade{ Protected static function getFacadeAccessor(){ Return \app\Util\CharUtil::class; } } 2)注册 app\Providers Public function register(){ $this->app->singleton( ‘char’ , \App\Util\CharUtil::class ); }
3)app\Http\Controller Use App\Facade\Char
Char::char(); //通过char门面找到app中绑定的charUtil的实例 |
契约 |
直白点就是一个接口类,形象点就是定义了一个规范
1)控制器 app\Http\Controllers Class IndexController extends Controller{ Public function test{ Return Char::char(); } }
2)注册 app\providers\RiakServiceProvider Public function register(){ //$this->app->singleton( ‘char’ , \App\Util\CharUtil::class ); $this->app->singleton( ‘char’ , \App\Util\SVIPCharUtil::class ); }
3)工具类 app\Util Use App\Contracts\CharUtil as contracts; Class SVIPCharUtil implements contracts{ // Publlic function char(){ // Return xxxxxxxxxxxxxxx; // } Public function demo(){ Return ‘this is app util SVIPChartUtil’; } }
app\Util; Use App\Contracts\CharUtil as contracts; Class CharUtil implements contracts{ Publlic function char(){ Return xxxxxxxxxxxxxxx; } }
app\Contracts Interface CharUtil{ Public function char(){} } |
进阶2:Contract契约的存在 |
// 方法的参数可能不一致 // 假设oracle -> mysql $app = new Application(); $db = $app->make('db'); echo $db->demo(); //mysql中有这个demo方法,而换了oracle方法变成desc并且有参数。
规范为什么会选择接口,而不选择抽象
|
自定义路由
|
(供应者) 1)先在一个控制器上写好路由 2)App\providers\RouteServiceProvider 中的Map()方法负责注册路由 |
路由不同的请求访问方式 |
Get , post , put , patch , delete , options , any , match
Route::get( ‘test’, ‘TestController@index’); Route::get( ‘test’, ‘Test\TestController@index’); Route::match( [‘get’ , ’put’ , ’post’] , ‘test’ , ‘TestController@index’)
// 1)允许自定义的方式 Route::match(['get', 'post' , ""], '/', function () {
});
// 2)允许全部的访问方式 Route::any('foo', function () {
}); */
// 3)根据某一些规则分组,前缀,中间件,命名空间 // Route::prefix('pre')->group(function () { // Route::get('/', function () { // return "pre ii "; // }); // // Route::get('user', function () { // return "pre ii user"; // }); // });
Route::group(["prefix"=>"fix"],function () { // Route::get('/', function () { // return "fix ii "; // }); // // Route::get('user', function () { // return "fix ii user"; // }); // });
// 根据请求方式定义路由 // Route::get($uri, $callback); // Route::post($uri, $callback); // Route::put($uri, $callback); |
Laravel核心框架文件 Vendor(卖主,销售公司) |
Vendor\laravel\framework\src\Illuminate
|
DB 和 model 区别 |
model返回的是一个当前模型对象,可以通过toArray()转化为数组输出 2)model 对数据表进行抽象的描述,数据表中的字段名就是模型中的属性 dd(Test::where('id',1)->first()->name);
\Illuminate\Database\DatabaseManager::class
|
普通一对一( has one() ) |
|
一对多( has many() ) |
|
预载入 |
|
预载入的理解 |
|
接口开发的两种方式 |
1)restful : http json 2)soap : 传输数据的协议 xml
用户 (传统接口) http://xxx.com.user/findUser http://xxx.com.user/addUser http://xxx.com.user/delUser
soap风格方式(简单 隐式 安全) http://xxx.com/user get请求 查询 http://xxx.com/user 更put请求新 http://xxx.com/user delete请求 删除
|
|
|
什么是Csrf |
1)Csrf:跨站点请求伪造 2)凡是非get方式请求的url都会进行csrf检测
Route::get( ‘csrf’ , function(){ Return “ get - csrf”; })
Route::post( ‘csrf’ , function(){ Return “ post - csrf”; })
|
Csrf解决(跳过检测) |
app\Http\Middleware verifyCsrfTokenMiddleware protected $exception = [ ] |
Csrf的工作流程 |
1)会生成两个token保存 2)一个通过session的方式保存在服务器端 3)另一个通过cookie的方式保存在客户端 4)如果是非get请求,两者会进行比较 |
|
|
行为控制器 |
2)例如:错误提示 受到攻击后发邮件
php artisan make:controller Only/ShilpController –invokable
|
资源控制器 |
php artsain make:controller Api/UserController --resourece
Route::resource(‘user’,’Api\UserController’)
|
获取Request对象
|
源码: 真正实现功能是里面的symfonyRequest
获取参数直接通过$request来接收请求参数。 $request->input(‘username’); $request->input(‘password’);
Method() Root() Url() Path() Input() All() Cookie() Session()
Has() Field()
|
Request |
在Request类继承SymfonyRequest,而对于这个类中的一些常用的获取请求参数的方法,实际在 Illuminate\Http\Concerns\InteractsWithInput类中。 |
Response响应 |
响应:就是返回结果 laravel框架提供了很多种的访问方式,可以返回一个字符串也可以返回数组,而laravel会自动把这些参数内容进行转化为json格式进行输出 这里我们主要会使用到Illuminate\Http\Response类做处理。
|
cookie |
因为cookie在客户端,你需要通过http请求把数据返回给请求的客户端。
1)设置cookie需要从响应来设置 Response()->cookie(name,value,time());
2)获取 Request()->cookie(name); Cookie::get(name);
3)删除 Cookie::forge(name);
|
session |
1)设置session Request()->session()->put(name , value);
Session( [ ‘name1’=>’value1’ , ‘name2’=>’value2’] )
2)获取 Request()->session()->all();
3)删除session 一个forge 多个flush |
|
|
数据库配置
|
Config\database.php
|
原生sql 预处理 |
1.占位符:? 2.按顺序传递值 :Name 按名称传递值。
增: DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']); 删: DB::delete('delete from users'); 改: DB::update('update users set votes = 100 where name = ?', ['John']); 查: DB::select('select * from users where id = :id', ['id' => 1]);
|
事务 |
DB::transaction(function(){ DB::update('update users set votes = 100 where name = ?', ['John']); }) 2)手动 DB::beginTransaction(); DB::rollBack(); DB::commit(); |
Sql监听 |
可以调用sql语句 Providers\AppServiceProvider.php Public function boot(){ DB::listen(function($query){ Echo $query->sql; }) } |
查询构造器 |
|
|
$result = DB::table('user_base')->get();
|
|
toArray 只是转化一维结果为数组
|
3.查找指定字段,不要用* 并且去重 |
$result = DB::table('user_base')->select(‘xxxx’ ,’xxxx’ ) ->distinct()->get();
|
4.Where方法的使用 写法
|
$rseult = DB::table('user')->where('uid', 63)->get(); $rseult = DB::table('user')->where('uid', '=', 63)->get(); |
5.多个条件查询:
|
$rseult = DB::table('user')->where([ ['uid' , '=', 63], ['role_id', '=', 1] ])->get();
$rseult = DB::table('user')->where([ 'uid' => 63, 'role_id' => 1 ])->get();
|
6.查询语句写原生条件需要用DB::raw
|
$result = DB::table('user_base')->where(DB::raw("user_name = 'linss' OR user_id > 1"))->get();
$result = DB::table('user_base')->where('user_id','>',3)->orWhere('user_name','winner')->get();
|
做大任务的时候
|
chunk 参数:1、分块的大小 2、闭合函数
$reuslt = DB::table('user_base')->orderBy('user_id')->chunk(2,function ($citys){ var_dump($citys); //终止分块处理 return false; }); var_dump($reuslt);
分块操作 分两次处理全部 如果你需要处理上千条数据库记录,你可以考虑使用 chunk 方法。该方法一次获取结果集的一小块,并将其传递给 闭包 函数进行处理。该方法在 Artisan 命令 编写数千条处理数据的时候非常有用。 DB::table('city')->orderBy('city_id')->chunk(100, function ($citys) { foreach ($citys as $city) { echo $city->city_id.' name : '.$city->city_name.' } });
|
8.join == inner join
|
$result = DB::table('user') ->join('user_role' , 'user.role_id', '=', 'user_role.role_id') ->first(); $result = DB::table('user') ->join('user_role' , 'user.role_id', '=', 'user_role.role_id') ->join('user_group' , 'user_role.group_id_array', '=', 'user_group.group_id') ->first(); $result = DB::table('user') ->join('user_role' , function($role){ $role->on('user.role_id', '=', 'user_role.role_id') ->where('user_role.group_id_array', 55); })->first(); dd($result);
|
9.Ordering, latest / oldest
|
$result = DB::table('user') ->orderBy('uid', 'desc') ->get();
// latest / oldest 默认使用 created_at 列作为排序依据可以传递自定义的列名: $result = DB::table('user') ->latest('uid') ->get(); dd($result);
|
10.严格模式
|
注意这里有一个问题 ,在使用这个方法的时候一定要把config/databases.php中的'strict' => false,修改一下 $result = DB::table('config') ->groupBy('key') ->get();
|
11.skip / take---》》 limit查询表示查询的数据量,或跳过指定数量的结果
|
$result=DB::table('config')->skip(10)->take(5)->get(); $result=DB::table('config')->offset(10)->limit(5)->get(); |
12.获取自增id
|
$id = DB::table('user_role')->insertGetId( ['role_name' => '测试','group_id_array' => 54, 'is_role' => 0,'role_status' => 1,'desc' => '测试'] ); dd($id);
$result = DB::table('user_role')->where('role_id', 5)->update([ 'role_name' => '管理员' ]); $result = DB::table('user_role')->where('role_id', 5)->delete(); dd($result);
|
13.联合查询(join==inner join)
|
|
first 查询单条
|
$resutl= DB::table('user_base')->join('users','user_base.user_id','=', 'users.id')->first();
|
联合查询闭包方式 (多个表的话,可以使用这个)
|
$data = DB::table('user_base')->join('users',function ($role){ $role->on('user_base.user_id','=','users.id')-> where('users.id',2); })->first(); var_dump($data);
|
子查询 子查询就是一个临时表
|
$last = DB::table ('user_base') ->select ('user_id',DB::raw('user_email as email')) ->where ('user_id','<=','2') ->orderBy ('user_id','desc');
joinsub 子查询 参数:1、结果集 2、临时表别名 3、闭包函数 $users = DB::table ('users') ->joinsub ($last, 'user_base2',function ($join){ $join->on('users.id','=','user_base2.user_id'); })->get(); var_dump($users);
|
order group limit
|
排序:latest降序 oldest 升序 默认按照created_at日期时间排序 select * from `user_base` order by `user_id` asc $result = DB::table('user_base') ->oldest('user_id')->get(); var_dump($result); 分组 $result = DB::table('user_base') ->groupBy('user_status') ->get(); var_dump($result);
限制结果集 limit 限制结果显示 offset 偏移量 $result1 = DB::table('user_base')->offset(2)->limit(2)->get();
//take 跳转指定数量 skip 偏移量 (这个效率比 limit offset快很多) $result = DB::table('user_base')->skip(2)->take(2)->get(); var_dump($result,$result1);
修改数据 $resurt = DB::table('user_base')->where('user_id',4)->update(['user_name'=>'小五老师']); var_dump($resurt); |
Laravel组件开发 |
|
对应的项目目录
|
Shinyork Src Web http Controller Resource View Middleware Model Route Composer.json Pc Mobile Composer.json |
Laravel组件的开发的步骤
|
1)composer require xxx 2)Composer-builder build xxx ********************************* 3)Composer init 交互的方式要求我们填写一些信息 4)Composer.json修改后,composer update 5)自定义服务类(数据库) 6)简单测试 引入服务类 new()->方法();
|
进阶1:可以使用容器来存放服务类 |
Application 1)应用实例 2)项目/框架的核心 3)项目核心的应用 4)启动软件程序(需要有用户的信息,启动的方法) 5) Container只是提供的是初始方法 Application是对应用程序的注册,启动
|
进阶2:Contract契约的存在 |
// 方法的参数可能不一致 // 假设oracle -> mysql $app = new Application(); $db = $app->make('db'); echo $db->demo(); //mysql中有这个demo方法,而换了oracle方法变成desc并且有参数。
规范为什么会选择接口,而不选择抽象
|
进阶3:Facade门面类的引入 |
// 快速调用 // 便于维护
|
Container关键点解析
|
(Application这个类继承与Container这个类) 1) $binds这是一个容器类,在里面会保存整个框架运行所需要的服务,本质上是通过key,value以数组的方式保存着实际类在里面 $binds = [ “标识” =>“实际类的对象” “route”=> new route(); ] 2) Class Container{ protected static $instance; // 单例模式 protected $instances = []; // 保存解析出来之后的实例(保存已经使用过的实例)
protected $bindings = []; // 容器绑定实例 不会立即使用 信息的注册 protected $aliases = []; // 记录类库定义的别名
public function bind(){} // 就是绑定到容器的方法
public function has(){} // 校验是否在容器中
public function getInstance(){} // 把解析出来之后的容器保存在实例中
public function make(){} // 从容器中解析 } |
原生代码诠释(简化版)
|
|