[该文章已设置加密,请点击标题输入密码访问]
用 composer安装
在app.php中进行注册
use Excel;
public function export()
{
$cellDate = [
['学号','姓名','成绩'],
['10001','aaa','99'],
];
Excel::create('学生成绩',function($excel) use ($cellData)
{
$excel->sheet('scroe',function($sheet) use ($cellData){
$sheet->rows($cellData);
});
})->export('xls');
}
public function import()
{
$filePath = 'Your uploaded file path';
Excel::load($filePath,function($reader)
{
$data = $reader->getSheet(0)->toArray();
});
}
主要要记住以下几个文件
Uploader.swf
webuploader.css
webuploader.js
webuploader.min.js
上传时侯引入其它参数
var uploader = new WebUploader.Uploader({
formData : { uid:123}
});
//上传后对返回值的处理
uploader.on('uploaderSuccess',function(file,response){
$('#'+file.id).addClass('upload-state-done');
console.log(response);
});
今天手滑了一下,在删除一个软链接时加了个 / 把这几年拍的公司所有设备的照片给清空了,把恢复过程记一下,长个记性。
1. extundelete使用说明
extundelete下载地址:
https://sourceforge.net/projects/extundelete/?source=typ_redirect
先说一下extundelete的使用及说明:
安装:
yum -y install e2fsprogs-devel e2fsprogs tar jxf extundelete-0.2.4.tar.bz2 cd extundelete-0.2.4 ./configure --prefix=/opt/extundelete make && make install
[root@UHDATA006 bin]# date -d "Dec 15 11:30 2016" +%s 1481772600
fdisk -l
/opt/extundelete/bin/extundelete --restore-all --after "1481776200" /dev/mapper/vghe-lvexport
extundelete /dev/sda1 --restore-all
config/app.php 里的aliases用来配置预加载的类
路由
route/web.php 配置文件
Route::请求方式('请求的URL',匿名函数或控制响应的方法)
Route::get('/',function(){
return view('welcome');
})
访问/home地址则路由可以写成
Route::get('/home',function(){
echo '当前访问的地址是/home';
});
有时候还需要注册路由响应多个HTTP请求--这可以通过match方法来实现,或用any方法注册一个路由来响应所有HTTP请求
Route::match(['get','post'],'/',function(){
});
Route::any('foo',function(){
});
路由参数
路由参数其实就是给路由传递参数
参数分为必选参数和可选参数。
必选
Route::get('/user/{id}',function($id)){
return '当前用户id是:'.$id;
});
可选
Route::get('/user2/{id?}',function($id=null){
return '当前用户id是:'.$id;
});
通过 ? 形式传递参数,可以不写路由
http://www.ndyih.com/user2?id=1111
路由别名
相当于在路由定义的时侯为路由起了一个别名。
Route::any('/test5/adsadfasdf/wersdfsdf/adsasd',function(){
echo '当前的用户id是'。$_GET['id'];
})->name('zhangsan');
调用该路由则可以写成:route("zhangsan");
查系统已经有的路由命令#php artisan route:list
路由群组
比如后台有如下路由
/admin/login
/admin/logout
/admin/index
/admin/user/add
/admin/user/del
//路由群组不需要权限判断
Route::group(['prefix'=>'admin'],function(){
Route::get('users',function(){
//匹配 "/admin/users" URL
});
});
//路由群组需要权限判断(路由保护)
Route::group(['prefix'=>'admin' , 'middleware' => 'auth'],function(){
Route::get('users',function(){});
});
//路由保护
含义:只在通过认证(符合某个条件)的用户才能访问指定的路由,该方式称之为路由保护。
例如:后台首页应该只有通过用户名和密码认证才能进行访问,因些需要给对应的页面去做上路由保护。
中间件:不是控制器文件,但也是一个类。中间件在laravel中有2大类:1、系统提供的,2、用户自己定义的。
路由 -> 中间件 -> 目标访问控制器
Route::get('profile' , function(){
})->middleware('auth');
控制器使用
控制器目录位于app/Http/Controllers
控制器的命名
大驼峰的控制器名+Controller.php
ForgotPasswordController.php
结构代码书写
php artisan make:controller 控制器名 (大驼峰)Controller 关键词
php artisan make:controller TestController
命名空间三元素:常量、方法、类
控制器路由即,如何使用路由规则调用控制器下的方法,而不再走回调。
路由设置格式基本相同,只是将匿名函数改成“控制器名@方法名”
Route::请求方法(路由表达式,控制器@方法)
编写路由规则
设定路由:/home/test/test1
Route::get('/home/test/test1','TestController@test1');
控制器分目录管理目录名首字母大写
php artisan make:controller Admin/IndexController
Route::get('/home/index/index','Home\TestController@test1');
接收用户输入
接收用户输入的类:Illuminate\Support\Facades\Input
Facades:“门面”的思想。门面是介于一个类的实例化与没有实例化中间的一个状态。其实是类的一个接口实现。在这个状态下可以不实例化类但是可以调用类中的方法。说白了就是静态方法。
Input::get('参数名字',‘如果参数没有被传递使用该默认值’);
Input::all();获取所有用户的输入
Input::get();获取单个用户的输入
Input::only(['id','name']);只获取 id和name 值
Input::except(['id','name']);获取除了 id和name 以外的值
Input::method();获取请求类型
Input::has('name');判断某个输入的参数是否存在
config/app.php用来定义别名路径
dd($all) ;//dump + die
DB类操作数据库
基本语法:DB::table("tableName");
数据库的配置在.env文件里面
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=qz04
DB_USERNAME=root
DB_PASSWORD=root
数据库也可以在config目录下面的database.php里配置。
DB 在 app.php 中已经定义别名 DB,可以直接 use ,不用写太长命名空间
定义增删改查需要的路由
增加: /home/test/add
删除: /home/test/del
修改: /home/test/update
查询:/home/test/select
Route::group( ['prefix' => 'home/test'],function(){
Route::get('add','TestController@add');
Route::get('del','TestController@del');
Route::get('update','TestController@update');
Route::get('select','TestController@select');
});
//增加信息 insert()和insertGetId()
insert();可以同时添加一条或多条,返回值是布尔类型
insertGetId();只能添加一条数据,返回自增的id
public function add()
{
$db = DB::table('member');
$result = $db->insert( [ 'name' => 'kevin' , 'age' => '120' , 'email' => 'asdlfksd@qq.com' ] , [ 'name' => 'jovin' , 'age' => '333' , 'email' => 'asdfsdf@gmail.com' ]);
dd($result);
}
public function add()
{
$db = DB::table('member');
$result = $db->insertGetId( [ 'name' => 'kevin' , 'age' => '120' , 'email' => 'asdlfksd@qq.com' ] );
dd($result);
}
//修改数据
update() 可以修改整个记录中的全部字段
increment() 修改数字字段的精值,递增或递减
decrement() 修改数字字段的精值,递增或递减
//where语法
where(字段,运算符,值)
{
$db = DB::table('member');
$rst = $db->where('id','=','1')->update(['name' => 'lion']);
dd($rst);
}
DB::table('member')->increment('votes');每次+1
DB::table('member')->increment('votes',5);每次+5
DB::table('member')->decrement('votes');每次-1
DB::table('member')->decrement('votes',5);每次-5
//查询数据
DB::table('member')->get(); //取得所有的数据,返回的是对象数组
DB::table('member')->where('id','>','3')->get();
where()->where()->where() //这种写法是and关系
where()->orWhere()->orWhere() //这个语法是或者关系语法
orWhere语法的参数与where一致
//取出单行数据
DB::table('member')->where('id','1')->first();//返回值是符合条件是第一条记录
//取出某个字段的值
DB::table('member')->where('id','1')->value('name');
//取出多个字段的值
DB::table('member')->select('name','email')->get();
DB::table('member')->select('name as user_name')->get();
//排序操作
DB::table('member')->orderBy('age','desc')->get();
//分页操作
DB::table('member')->limit(3)->offset(2)->get();
limit 表示限制输出的条数
offset表示从什么地方开始
//删除数据
DB::table('member')->where('id','1')->delete();
DB::table('member')->where('id','1')->truncate(); //删除整个表
//执行SQL语句
会影响记录的用statement
DB::statement( "insert into member values (null , '')" );
不影响记录的用select
DB::select( "select * from member" );
//视图
//视图可以分目录管理
目录:/resources/views
视图文件的命名与渲染
1.文件名习惯小写(建议小写)
2.文件名的后缀是.blade.php(因为laravel里面有一套模板引擎就是用blade,可以直接使标签语法{{$title}},也可以使用原生的PHP语法显示数据。)
3.需要注意的是也可以使用.php结尾,但是这样的话就不能使用laravel提供的标签{{$title}}语法显示数据,只能使用原生语法<?php echo $val ?>显示数据。
两个视图文件同时存在,则.blade.php后缀的优先显示。
展示视图的方法
Return view("视图文件的名称");
展示视图的方法(分目录)
Return view("home/test/test3")
Return view("home.test.test3")
//变量分配与展示
语法
view("模板文件名称",数组)
view("模板文件名称")->with(数组)
view(模板文件名称)-with(名称,值)->with(名称,值)
Return view("home/test/test3",['date ' => $date , 'day '=> $day ])
在视图中调用
{{$date}}
扩展 compact函数使用(传参)
compact函数,是PHP内置的函数,跟larvel没有关系,作用是用于打包数组的。
compact( '变量名1' , '变量名2' , '变量名3' )
Return view("home/test/test3",compact( 'date','day' ))
//在模板中使用函数的方式就是直接用
{{date('Y-m-d H:i:s',$time)}}
html中   代表4个@nbsp;
//模板内的循环
@foreach($variable as $key => $value)
{{$val->id}}
@endforeach
//模板内的判断
@if(条件语句)
语句1
@elseif(条件语句)
语句2
@elseif(条件语句)
语句3
@else
默认语句
@endif
//PHP的内置函数 date( 'N' ) 可以得到今天是星期几所对应的数字。
//模板继承
在父级模板中用 @yield( 'mainbody' ) 来占位,定义可变区域。//@yield( '自定义名称' )
在子级模板中用 @extends( 'home.test.parent' )继承父级模板,//@extends( 'home.test.parent' )
在子级模板中用
@section( 'mainbody' )
在父级模板中要展示的内容。
@endsection
//模板包含
@include( 'home.test.test4' )
//外部文件引入
给浏览器用的外部文件最好以 / 开头。
<link rel="stylesheet" type="text/css" href="/css/app.css">
<link rel="stylesheet" type="text/css" href="{{asset( 'css' )}}/app.css">
上面两种引入方式都可以。asset想用就用,不想用可以不用。
//CSRF攻击
CSCR是跨站请求伪造(Cross-site request forgery)的英文缩写
Larvel框架中避免CSRF攻击很简单,Laravel自动为每个用户session生成了一个CSRF Ttoken,该token可用于验证登录用户和发起请求者是否是同一人,如果不是则请求失败。【该原理和验证码原理是一致】
Laravel提供了一个全局帮助函数 csrf token来攻取token值,因此只需在视图表单中添加如下HTML代码即可在请求中带上Token
<input type="hidden" name ="_token" value="<?php echo csrf_token(); ?>">
针对csrf_token()的简化
{{csrf_field()}} //自动生成 <input type="hidden" name ="_token" value="<?php echo csrf_token(); ?>">
从csrf验证中排除例外路由(单个路由排除)
可以通过在VerifyCsrfToken(app/Http/Middleware/VerifyCsrfToken.php) 中间件中将要排除的请求URL添加到$except属性数组中。
protected $except = [ 'home/test/test7' , 'home/test/test8' ];
排除全部路由使用csrf 在app/Http/Middleware/VerifyCsrfToken.php
protected $except = [ '*' ];
//模型操作(AR模式)
每个数据表都对应一个与该表进行交互的“Model”模型,模型允许你在表中进行数据查询,以及插入、更新、删除等操作。
模型定义位置,默认是在APP目录下面,但为了管理方便,建议分目录进行创建:
模型命名规则
本身laravel对模型的命名没有严格要求,一般采用表名(首字母大写).php
创建模型:
php artisan make:model Admin/Member //Admin是分目录。
1、模型必须定义一个$table属性,值是不要前缀的表名,如果不指定则使用类名的复数形式作为表名。修辞词protected
2、定义$primaryKey属性,值是主键名称,如果需要使AR模式的find方法,则需要指定主键(Model::find(n))。修辞词protected
3、定义$timestamps属性,值是false,如果不设置为false,则默认会操作表中的created_at和updated_at字段,我们表中一般没有这两个字段,所以设置为false表示不操作这两个字段。修辞词public
4、定义$fillable属性,表示使用模型插入数据时,允许插入到数据库的字段信息。修辞词protected
注意:使用模型中create插入数据时,要设置$fillable允许入库的字段,使用$guarded是设置排除入库的字段。
例子:
<?php namespace App\Home use Illuminate\Database\Eloquent\Model class Member extends Model { protected $table = 'member'; protected $primaryKey = 'id'; public $timestamps = false; protected $fillable = [ 'id' , 'name' , 'age' , 'email' ]; } ?>
//模型控制器中调用
引入Member模型类:
use App\Home\Member
模型使用
1 、Member::get()
2、DB::table('member')->get()
3、$model = new Member();
$result = $model->get();
//添加数据
方式一(AR模式):使用AR模式必须要实例化模型
$member = new Member();
$member->name = 'value';
$member->save();
方式二:非AR模式
1、建立一个简易表单,并能够提交。
2、引入Request这个类 use Illuminate\Http\Request;(这个类在创建控制器的时侯就已经引入了)
request如果要用的话要以形参的方式传给方法,使用方式与Input方法差不多,但是Input调用的是静态方法。
public function test8(Request $request){
//$request->all();//$request->get('name');
$model = new Member();
$model->create($request->all());
//注意:如果使用create方法,则需要在模型中定义fillable属性,允许写入字段的定义,如果没有时间相关字段也需要禁用时间自动更新功能。
}
//查询操作
$data = Member::find(4);
如果需要在laravel中对象的结果集转化成数组,则需要在最终终添加方法的调用 “->toArray()”
获取符合指定条件的第一条记录
Member::where("id",">",4)->first();
查询多行并且指定字段
Member::all();//all 之前不能加其它方法
Member::all([字段1,字段2]);
按条件查询指定多个字段
Member::where("id",">",4)->get( ['字段1','字段2'] );
Member::where("id",">",4)->select( '字段1','字段2' )->get();
Member::where("id",">",4)->select( [ '字段1','字段2' ] )->get();
//AR模式修改操作要改之前必须先查出来
$user = User::find($id);
$user->title = $_POST['title'];
$user->content = $_POST['content'];
return $user->save() ? 'ok' : 'fail';
//非AR模式更新数据
$result = Member::where('id','7')->update( ['age' => 28] );
//AR模式删除数据
$user = User::find($id);
return $user->delete() ? 'ok' : 'fail' ;
//自动验证
public function check(Request $request)
{
$this->validate($request,[
'name' => 'required|min:2|max:20',
'age' => 'required|interger|min:1|max:100',
'email' => 'required|email',
]);
}
//显示验证后的错误信息
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
注:$errors变量会通过web中间件组中的Illuminate\View\Middleware\ShareErrorsFromSession中间件绑定到视图,如果使用了该中间件,那么$errors变量在视图中总是有效,从而方便你随时使用。
把验证后的错误信息转成中文
https://packagist.org composer主要的代码托管网站
在上面的网站搜索laravel-lang,综合该网站上的下载量和收藏量进行选择。
将下载的语言包laravel-lang\scr\zh-CN 目录复制laravel目录的resources\lang目录
将config/app.php文件中的locale选项改成locale改成新的语言包的目录名。
注:并不是所有字段者有对应的翻译,如果没有则要云修改语言包vaildation.php的文件代码。
//文件上传
获取上传的文件
可以用Illuminate\Http\Request实例提供的file方法或者动态属性来访问上传文件,file方法返回Illuminate\Http\UploadedFile类的一个实例,该类继承自PHP标准库中提供与文件交互方法的SplFileInfo类
$file = $request->file('photo');
$file = $request->photo;
$request->hasFile('photo');判断文件在请求中是否存在
$request->file('photo')->isValid();判断文件在上传过程中是否出错
$request->file('photo')->getClientOriginalName();获取文件名
$request->file('photo')->getClientSize();调用上传的文件大小
$request->file('photo')->getClientOriginalExtension();取得上传文件的后缀
$request->file('photo')->move('./upload','文件名');移动上传后的文件(如果路径是给php代码使用的,则路径建议用 ./ 形式,如果路径是给浏览器使用的则建议使用/形式。)
$request->file('photo')->getErrorMessage();获取上传错误。
PHP的ltrim()函数可以去除字符串左边的特定字符。
//数据分页
分页类所在位置/vendor/laravel/framework/src/Illuminate/Pagination/Paginator.php
基于Eloquent结果集进行分页,支持使用where以及orderBy等辅助查询方法。
$users = App\user::paginate(15);参数是每页显示的记录数
$users = User::where('votes','>',100)->paginate(15);带条件查询分页
$users = User::where('votes','>',100)->simplePaginate(15);简单分页,只显示“上一页、下一页”没有数字字符串。
模板中用 $user->links() 显示分页链接。
要改分页显示的样式需修改/vendor/laravel/framework/src/Illuminate/Pagination/resources/views/default.blade.php
results->count() //当前页数据条数
$results->currentPage() //当前页码
$results->firstItem() //当前页第一条数据的序号
$results->hasMorePages() //是否有后续页码
$results->lastItem() //当前页最后一条数据的序号
$results->lastPage() //最后页序号
$results->nextPageUrl() //下一页的链接地址
$results->perPage() //每一页显示的数据条数
$results->previousPageUrl() //上一页的链接地址
$results->total() //记录总条数
$results->url($page) //制作指定页码的链接地址
//验证码
生成验证码要经过:画画布、生成干扰线、生成噪点、生成验证码、生成验证码存入SESSION、输出图片
验证码依赖安装
在packagist.org搜索验证码安装(搜索captcha)用下载和收藏最多的一个安装(然后去啃说明文档)
//数据的迁移与填充
迁移:创建数据表的操作+删除数据表的操作
填充:往数据表里填充写入测试的数据(数据的插入操作)
迁移文件的目录/database/migrations (该目录下有两个文件,可以删掉)
创建迁移文件
假高数据表的名字叫做paper。迁移文件名:create_paper_table
创建的时侯可以通过自动代码生成工具artisan命令来执行迁移文件的生成。
php artisan make:migration 迁移文件名
php artisan make:migration create_paper_table
迁移文件不需要分目录管理,可以直接书写名称即可。
可以参考系统自带的文件
Schema::create('flights', function (Blueprint $table) {
$table->increments('id');
$table->string('name',100)->notNull();
$table->string('airline');
$table->timestamps();
});
//执行迁移文件
如果在项目中第一次执行迁移文件,则需要先执行
php artisan migrate:install //用于创建记录迁移文件的记录数据表
接下来执行up方法,则需要执行命令(注意:需要删除系统自带的迁移文件,只保留自己的)
php artisan migrate
Down方法执行:(回滚操作,删除数据表)
php artisan migrate:rollback //回滚最后一次的迁移操作 注意:删除(回滚)之后删除上一个批次的迁移记录,并且同批次建立的数据表也会删除,但是迁移文件依旧存在,方便后期继续迁移(创建数据表)。
//数据表填充器
填充器又称种子文件,目录位置:database/seeds/DatabaseSeeder.php
创建填充器
php artisan make:seeder 填充器名称 【约定俗成的写法:大写表名+TableSeeder】
php artisan make:seeder PaperTableSeeder
注:在填充器文件中可以使用DB去新增数据,但是要注意,DB在使用时侯不需要用户自己引入,一旦引入则报错,可以直接使用。
public function run()
{
$data = [ ['paper' => 'sdfasdf'] , ['paper' => 'sdfasdf'] , ['paper' => 'sdfasdf']];
DB::table('paper')->insert($data);
}
执行填充器文件
php artisan db:seed --class = 需要执行的种子文件名(不带.php)
项目初使化步骤
1、创建项目
composer create-project laravel/laravel=5.4.* --prefer-dist ./
2、建立数据库
修改.env文件,配置数据库的连接操作
3、设置网站本地化为中文
下载语言包:#composer require caouecs/laravel-lang:~3.0
将语言包复制到resources/lang内
修改config/app.php文件中的locale值
4、设置项目使用的时区
修改系统默认时区,修改配置文件:config/app.php配置项的:timezone值 Aisa/shanghai , Aisa/chongqing ,PRC
5、项目清理(删除系统不需要的文件)
app/Http/Controllers/Auth
database/migrations/2014_10_12_000000_create_users_table.php
database/migrations/2014_10_12_000000_create_password_resets_table.php
也可以删除seeds下的初始化文件
删除resources/views/welcome.blade.php
public目录下的js、css文件夹也可以删除
6、关闭Mysql的严格模式
编辑config/database.php将strict由true修改为flase
7、安装debugbar工具条(可选)
条件:PHP版本大于7.0
//填充器模拟生成数据faker(faker代码库不用安装laravel已经自带了)
$faker = \Faker\Factory::create('zh_CN'); //传的参数代表生成符合中国本地化的数据
$data = [];
for($i = 1;$i<=100;$i++)
{
$data[] = [
'username' => $faker->userName,
'password' => bcrype('123456'),//使用框架自带的密码加密函数
'gender' => rander(1,3),
'mobile' =>$faker->phoneNumber,
];
}
DB::table('manager')->insert($data);
//响应处理
展示视图
return view('welcome');
直接返回某个字符串
return 'hello world';
直接返回json数据
Return response()->json($data);
ajax请求的响应
常见的ajax响应数据类型:json和xml、text/html。
注:在laravel中布尔值不能直接被响应
//跳转响应
Return redirect(路由);
Return redirect()->to(路由);
Return redirect('路由地址')->withErrors(['loginError' => '用户名或密码错误']);//跳转带上错误信息
//会话控制
session默认存到文件中
session文件的目录:storage\framework\sessions
Session静态方法
use Illuminate\Support\Facades\Session
由于session静态方法在app.php中已经定义好别名,所以在控制中引入的时侯可以直接use Session;
Session::put('key',value);
$value = Session::get('key');
$value = Session::get('key','default');//Session获取一个变量或返回一个默认值(如果变量不存在)
$value = Session::get('key',function(){ return 'defalut'; });
Session::all();获取所有变量
Session::has('users');检查一个变量是否在Session中存在
Session::forget('key');Session中删除一个变量
Session::flush();Session中删除所有变量
注:session方法也可以在视图中使用,如:{{ Session::get('code')}}
//缓存操作
laravel为不同的缓存系统提供了统一的API,缓存配置位于config/cache.php。在该文件中你可以指定在应用中默认使用那个缓存驱动。laravel目前支持主流的缓存后端如Memcached和Redis等。
主要方法:
Cache::put('key','value','minutes') //如果该键已存在,则直接覆盖原来的值,有效期必须设置,单位是分钟
Cache::get('key','如果key不存在则使用的默认值,也支持回调函数')
Cache::add() //只会在缓存项不存在的情况下添加数据到缓存,如果数据被成功添加到缓存返回true,否则返回false;
Cache::pull('key') //从缓存中获取缓存后删除,如果缓存项不存在的话返回null,一般设置一次性的存储的数据。
Cache::forever('key','value') //用于持久化存储数据到缓存,这些值必须通过forget方法从缓存中移除。
Cache::forget() //从缓存中移除缓存项数据
Cache::flush() //清除所有缓存,并且删除对应的目录。
Cache::remember();
Cache::has() //判断某个值是否存在。
系统默认是使用文件缓存,其缓存文件存储的位置于(storage/framework/cache/data)
缓存数值增加/减少
increment和decrement方法可以用于调整缓存中的整形数值。这两个方法都可以接收第二个参数来指明缓存项数值增加和减少的数目。
Cache::increment('key','递增幅度');
Cache::increment('key',$amount);
Cache::decrement('key','递减幅度');
Cache::decrement('key',$amount);
获取并存储
Cache::remember('user','miniutes','默认值,也可以支持回调函数'); //获取的缓存项不存在时给它一个默认值,并创建缓存
Cache::rememberForever('user' , '默认值,也可以支持回调函数'); //持久化存储数据到缓存
//联表查询
联表要求至少要有2张表,并且还是存在关系的两张表。
先写原始SQL语句,再转成模型。
语法:DB::table('table')->join(关联的表名,表1的字段,运算符,表2的字段)
例子:DB::table('articel as t1')->select( 't1.id','t1.articel_name','t2.author_name' )
->leftJoin( 'author as t2','t1.author_id','=','t2.id' )
->get();
//关联模型(关联模型必须要创建模型)
关联模型就是绑定模型(表)的关系(关联表),后续需要使用联表的时侯就可以直接使用关联模型。
1、一对一关系
2、一对多关系
3、多对多关系
一对一关联模型的关联方法
public function 被关联的模型名小写(){
return $this->hasOne('被关联模型的命名空间','外键(属于被关联模型的字段)','本地键(本模型中的字段)');
}
一对一使用例子:
$data = \App\Home\Article::get();
foreach($data as $key => $value){
$value-> 1对1方法名 ->字段名;
}
一对多关系hasMany
public function 被关联的模型名小写(){
return $this->hasMany('被关联模型的命名空间','外键(属于被关联模型的字段)','本地键(本模型中的字段)');
}
一对多使用例子:
$data = \App\Home\Article::get();
foreach($data as $key => $value){
foreach($value->1对多方法名 as $k => $val){
$val->字段名;
}
}
//多对多关系
多对多的关系经过拆分之后其实就是两个一对多的关系。
由于是双向一对多的关系,因些光靠2张表是无法建立关系的,需要依靠第三张表建立关系。
简易模拟
关键词表 关系表
id 关键词 id 文章id 关键词id
1 芳华 1 1 1
2 冯小刚 2 1 2
3 2 1
注:不用给关系表创建模型(你要建也行,反正也不用)。
语法:
return $this->belongsToMany('被关联模型的空间路径',多对多模型关系表名,当前模型中的关系键,被关联模型的关系键);
return $this->belongsToMany('App\Home\Keyword','relation','article_id','key_id');
$data = \App\Home\Article::get();
foreach($data as $key => $value){
foreach($value->多对多方法名 as $k => $val){
$val->字段名;
}
}
//自己关联自己
select t1.* ,t2.auth_name as parent_name from auth as t1 left join auth as t2 on t1.pid = t2.id;
DB::table('auth as t1')->select('t1.*','t2.auth_name as parent_name')
->leftJoin('auth as t2','t1.pid','=','t2.id')
->get();
//Auth静态方法用户认证(app.php中已经引入别名)
Auth::attempt(['email'=>$email,'password'=>$password]){
return redirect()->intended('dashboard');
}
attempt 方法接收键值数组作为第一个参数,数组中的值被用于从数据表中查找用户,因此,在上面的例子中,用户将会通过email的值获取,如果用户被找用,经哈希运算后存储在数据中的密码将会和传递过来的经哈希运算处理的密码值进行比较,如果两个经哈希运算的密码相匹配那么将为这个用户开启一个认证Session
Auth还提供了记住我的功能。
如果你想要在应用中提供“记住我”的功能,可以传递一个布尔值作为第二个参数到attempt方法,这样用户登录认证状态就会一直保持直到他们手动退出。当然,你的users表必须包含remember_token字段,该字段用于存储“记住我”令牌。
if(Auth::attempt(['email'=>$email,'password'=>$password)],$remember){
}
指定guard实例
你可以用Auth类的guard方法指定想要使用的guard实例,这种机制允许你在同一个应用中对不同的认证模型或用户表实现完全独立的用户认证。
传递给guard方法的guard名称对应配置文件auth.php中的guards配置的某个键。
Auth::guard('admin')->attempt($credentials)
定义guard ,在config/auth.php文件中定义。
//获取认证用户
$user = Auth::user();
Auth::guard('admin')->user()->username;
//退出的操作
Auth::logout();
Auth::guard('admin')->logout();
trait是PHP5.4之后的新特性,主要作用是为了提高代码复用,语法与class类似,区别class是能够被实例化,而trait不行。trait可以被使用,使用方法use trait名。
list,default是个关键词不要用来做方法名
//RBAC权限管理
1、介绍
RBAC:Role-ased Access Control,基于角色的访问控制。是一个比较完善的权限控制机制。目前有2套权限控制方案:
1)基于用户的权限控制
2)基于角色的权限控制
RBAC方式体现,目前有2种方式:三表方式、五表方式。不管是三表还是五表,其原理是一致的。
出现三表(用户表、角色表、权限表)和五表(用户表、用户与角色表的关系表、角色表、角色与权限的关系表、权限表)的原因就是设计规范要求(三范式)。
三表:优点表少,维护起来数据方便,理解起来也方便,;缺点就是不遵循范式要求;
五表:优点遵循范式要求;
app/http/Kernel.php是框架的核心文件。$routeMiddleware定义了中间件。
//判断文件上传
Request()->hasFile('filename');
Request()->file('filename')->isValid();
在laravel中除了在上传的时侯可以使用move和store方法【都是reuqest实例封装的】之外,还可以使用高级的上传文件保存方法【由storage门面提供的】
use Storage;
在storage门面中,有一个“磁盘”的概念,“磁盘”一共有三种:本地磁盘,公共磁盘,第三方磁盘。
“磁盘”实质上就是一个目录。
本地磁盘:local磁盘,存放在local磁盘中的文件是不能被浏览器使用的,其中的代码一般都是PHP代码自身使用。(位置:/storage/app目录)
公共磁盘:public磁盘,存储在该磁盘中的文件一般是允许浏览器进行访问。(位置:/storage/app/public目录)
第三方磁盘:驱动形式的一种,允许开发者将文件上传到第三方服务器上。
补允:默认情况下,浏览器是无法访问到public目录,但是其又想让浏览器访问,所以需要做一个“软链接”的操作
php artisan storage:link
//例子
//put的第二个参数是文件内容,直接用file_get_contents函数获取。
Storage::disk('public')->put($filename,file_get_contents($request->file('file')->path()))
声明字符编码:#-*- coding:utf-8 -*- (python3不用声明)
所有代码不是子集的话都要顶格写
输出: print(变量名)
单行注释: #
多行注释:
''''''
/---------------------------------------------------------/
name="alex li"
msg = '''
name = name
print("my name is",name,name2)
name= "paoche ge"
'''
print(msg)
输出结果:
name = name
print("my name is",name,name2)
name= "paoche ge"
/---------------------------------------------------------/
python中单引号和双引号是一样的
用户交互:
username = input("username:")
print(username)
字符串拼接用 + 号(一般不用会在内存中开辟多块空间)
格式化输出:
import getpass #引用标准库使用密文密码
name = input("username:")
password= getpass.getpass("password:")
age = int(input("userage:")) #强制数据类型转换,强制转成数字
job = input("userjob:")
salary = input("salary:")
info = '''
----------- info of %s -----------
name:%s
age:%d
job:%s
salary:%s
'''%(name,name,age,job,salary)
info2 = '''
----------- info of {_name} -----------
name:{_name}
age:{_age}
job:{_job}
salary:{_salary}
'''.format( _name = name , _age = age , _job = job , _salary = salary )
info3 = '''
----------- info of {0} -----------
name:{0}
age:{1}
job:{2}
salary:{3}
'''.format( name , age , job , salary )
print(info)
print(info2)
print(info3)
%s代表字符串
%d代表数字
%f浮点数
打印数据类型print(type(age))
变量数据类型转换:int(),str()
条件判断:
if _username = username and _password == password:
print( "welcome user {name} login .....".format( name=username ) )
else:
print("invalid username or password")
多级条件判断:
if guess_age == age:
print("yes,you got it")
elif guess_age > age:
print("think smaller...")
else:
print("think bigger!")
/---------------------------------------------------------/
循环执行
while count < 3:
print("count:",count)
count = count + 1
if count == 1000 : break
while count < 3:
guest_age = int(input("guess age:"))
if guess_age == age_of_oldboy :
print("yes,you got it");
break
elif guess_age > age_of_oldboy :
print("think smaller....")
else :
print("think bigger!")
count += 1
else :
print("you have tried too many times..fuck off");
count += 1 //计数
/------------------for循环--------------------------------/
for i in range(10) :
print("loop," i);
#range(起始数,结束数,步长)
for i in range(0,10) :
if i < 5:
print("loop",i)
else:
contine #跳出本次循环进入下次循环
print("hehe...")
for i in range(3) :
guess_age = int(input("guess age:"))
if guess_age == age_of_oldboy :
print("yes,you got it.")
break
elif guess_age > age_of_oldboy:
print("think smaller...")
else:
print("think bigger!")
else: #如果上面正常过完没有执行到break才会执行这个else语句
print("you have tried too many times..fuck off")
/------------------for循环嵌套--------------------------------/
for j in range(10) :
print(j)
if j > 5:
break
/------------------模块初识--------------------------------/
print(sys.path) #打印环境变量
print(sys.argv) #取得当前脚本的路径和参数 python sys_mod
print(sys.argv[2]) #取得传进来的第三个参数
import os #跟操作系统进行交互
os.system("dir") #执行windows的dir命令直接输出到屏幕上,不保存结果
cmd_res = os.popen("dir").read() #执行windows的dir命令保存到cmd_res变量上
print(cmd_res)
os.mkdir("new_dir") #创建目录
/------------------自建模块--------------------------------/
新建 一个.py文件
在新建另一个.py文件,import上一步生成的文件
/------------------.pyc是什么东西--------------------------------/
是python解释后的中间文件
type(2**32) #是查看变量的数据类型 ‘2**32’代表2的32次方
python3里没有长整形,只有整形。
一个赋值的方法:a,b,c = 1,3,5
三元运算: result = a if a > b else c
python2里bytes和字符串不区分
python3里bytes和字符串有区分,二进制是bytes,python3不会以任意隐式的方式混用str和bytes。
msg = '我爱北京天安门'
print(msg.encode(encoding = 'utf-8')) #如果没有指定编码,python就使用系统默认的编码
print(msg.encode(encoding = 'utf-8').decode(encoding = 'utf-8'))
/------------------列表和元组--------------------------------/
names = ["zhangyang","guyun","xiangpeng","xuliangchen"]
print(names[2]) #取得xiangpeng
print(names[0:3]) #取得头3个值
print(names[:3]) #取得头3个值
print(names[1:3]) #取得guyun 和 xiangpeng 顾头不顾尾
print(names[-1]) #取得最后一个
print(names[-2]) #取得倒数第二个
print(names[-3:-1]) #取得倒数2个值
print(names[-2:]) #取得倒数2个值
print(names[0:-1:2]) #跳着取值
#取得下标
product_list = [ ( 'mac book' , '1000' ) , ( 'bike' , '800' ) , ( 'surface' , '2000' ) ]
for item in product_list :
print( product_list.index(item) , item )
另一种方式
for index , item in enumerate( product_list ) :
print( index , item )
追加
names.append("leihaidong")
插到guyun前面
names.insert(1,"chengronghua")
改guyun
name[2] = "xiedi"
删
names.remove(“xuliangchen”)
del names[3]
names.pop() #删除最后一个
names.pop(1) #删除下标1对应的值
清空
names.clear()
找
print(names.index("xiangpeng")) #找出xiangpeng对应的下标
print(names[names.index("xiangpeng")]) #通过找出xiangpeng对应的下标,打印出xiangpeng
统计
print(names.count("xiangpeng")) #统计xiangpeng的数量
反转
names.reverse() #将列表的值进行反转
排序
name.sort()
扩展
names2 = [1,2,3,4]
names.extend(names2) #将names2并入names
浅拷备(只会拷备列表的第一层,如果列表里有子列表并不会拷备)
name2 = names.copy()
深拷备
import copy
name2 = copy.deepcopy(names)
列表循环
for i in names
print(i)
删除变量
del names2
浅copy的三种方式
person = [ 'name' , ['a' , 100] ]
p1 = copy.copy( person )
p2 = person[:]
p3 = list(person)
元组(又叫只读列表,只能查不能改)
names = ("alex" , "jack" , "eric")
判断是否为一个整数
salary = input("input your salary :")
if salary.isdigit() :
salary = int( salary ) #将salary转为整数
字符串操作
name = "xielon\tg"
print( name.capitalize() ) #首字母大写
print( name.count( "a" ) ) #字符统计
print( name.center( 50,"-"))
print( name.endswith("ex") ) #判断是否是以ex结尾
print( name.expandtabs() )
没有看出问题来呀?
<IfModule mod_rewrite.c>
也没看出异常来呀~~~~ 赶紧找资料。。。原来是 httpd.conf 配置文件少了东西,修改 /usr/local/apache/conf/httpd.conf
再上面虚拟主机的上面加上内容,结果如下:
<VirtualHost *:80></VirtualHost>
嘿嘿,重启apache,再测试,能访问了。
</Directory>
menu标签使用例子
<span contextmenu="candan">右键单击我试试</span> <menu type="context" id="candan"> <menuitem label="菜单一" onclick="alert('我是一个寂寞')" icon="http://www.baidu.com/img/baidu_sylogo1.gif"></menuitem> </menu>进度条标签使用例子
<meter min="0" max="10" value="5" low="3" high="7" ></meter> <progress max="100" value="0" id="pro"></progress> <script> var pro =document.getElementById('pro'); setInterval(function(){ pro.value+=1; },100); </script>
ruby标签例子
<ruby>夼<rp>(</rp><rt>kuang</rt><rp>)</rp></ruby>