本篇概要:
1. 框架目录结构;
1.1 官方演示程序的获取;
参考文档:https://github.com/laravel/quickstart-basic
- 下载演示程序到本地
cd /usr/local/src
git clone https://github.com/laravel/quickstart-basic quickstart
- 用 Composer 获取依赖库文件
cd quickstart
composer install
- 完成后设置
chmod -R 777 /data/project/test/quick/storage/
- 对环境变量文件里的数据库相关进行配置
cd quickstart
vim .env
# 对以下内容进行修改
# DB_DATABASE 为自己设置的数据库名称
DB_HOST=127.0.0.1
DB_DATABASE=quickstart
DB_USERNAME=root
DB_PASSWORD=asdf
- 保存退出,创建数据表(确保数据库 quickstart 已经创建)
php artisan migrate
- 创建虚拟主机配置文件
# 进入 Nginx 的虚拟主机配置存放文件夹
cd /usr/local/nginx/conf/conf.d
# 新建 quickstart 项目对应的虚拟主机配置文件
vim quickstart.conf
- 写入如下内容(重点是 Laravel Url 重写)
server {
listen 1000; # 端口,一般http是80
server_name localhost; # 一般是域名,本机就是localhost
index index.php index.html; # 默认可以访问的页面,按照写入的先后顺序去寻找
root /data/project/test/quickstart/public; # 项目根目录
# 防止访问版本控制内容
location ~ .*.(svn|git|cvs) {
deny all;
}
# Laravel Url 重写
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 去除末尾的斜杠,SEO 更加友好
if (!-d $request_filename) {
rewrite ^/(.+)/$ /$1 permanent;
}
# 去除 index action
# if ($request_uri ~* index/?$) {
# rewrite ^/(.*)/index/?$ /$1 permanent;
# }
# 根据laravel规则进行url重写
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
# 下面是所有关于 PHP 的请求都转给 php-fpm 去处理
location ~ \\.php {
# 注意:unix sock 和 ip,两种方式只能选择一种
# 基于 unix sock 访问,Ubuntu Apt 方式安装的 PHP 默认是以 sock 方式启动
# fastcgi_pass unix:/run/php/php7.0-fpm.sock;
#基于 IP 访问
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
fastcgi_intercept_errors on;
# 日志保存目录,一般按照项目单独保存
# access_log logs/localhost_access.log access;
}
- 保存退出,重启 Nginx,官方演示程序配置完成
/usr/local/nginx/sbin/nginx -s reload
# 或者
systemctl restart nginx
1.2 演示程序的运行;
- Url 跳转不带 index.php,说明虚拟主机配置文件 Url 重写部分代码正确生效
- 能正常添加删除 Task,数据库连接操作正确
1.3 Laravel 目录框架结构;
2. 路由初探;
2.1 Laravel 路由简介;
- 路由主要是指网络上的一个包,它要到达它的目的地。在路由器上,会进行一个路径的选择,然后将它转发到它要到达的目的地。
- 访问一个网页,除了它的域名之外,后面还有可能跟着很多东西。比如说 https://github.com/laravel/quickstart-basic 。
- 在最简单的一个 HTTP 服务器上,“
/laravel/quickstart-basic
” 是指根目录下有个目录叫 laravel,然后在 laravel 目录下还有一个目录叫 “quickstart-basic”。 - 随着 WEB 的慢慢的发展,以上所提到的不仅仅是代表目录的一种格式了。 比如说在 github 的网站上,根本没有 “laravel” 这个目录。它主要是有一个机制,这个请求会访问到某个页面,这个页面的处理程序会将整个 URL 进行一个解析,然后用过解析的结果去把请求指向一个特定的方法或者类。然后由这个方法或者类去处理这个请求。这个请求完成之后,再将页面返回给浏览器。
- 在 Laravel 中,就是使用了这样一种机制。所有的请求都会访问到 public 目录里的 index.php,然后框架会对 URL 进行解析,指向特定的方法。解析的过程需要进行路由的配置。
2.2 路由基本用法;
- 官方演示程序的 Laravel 版本是 5.2.20,路由文件的路径:
quickstart/app/Http/routes.php
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| This route group applies the "web" middleware group to every route
| it contains. The "web" middleware group is defined in your HTTP
| kernel and includes session state, CSRF protection, and more.
|
*/
use App\Task;
use Illuminate\Http\Request;
// group 相当于一个函数,这个函数是“路由组”的意思,在这里面所有的路由都会遵循一种相似的处理方式
// 在这个组里面定义了 middleware 中间件,使用了“web”这个中间键。
// 定义在这个组里面所有的解析方式,都需要执行一个名称为“web”的相同的中间件。
Route::group(['middleware' => ['web']], function () {
// “/”意思就是输入完整的 URL 后,只要“/”后面不输内容,就算不输入“/”也会匹配到这里。
// *调用了路由 route 里面的 get 函数,这个函数有两个参数。
// 第一个参数就是要匹配的路由,这个路由除了最简单的 URL 之外,还支持正则匹配方式。
// 第二个参数是一个方法,用来处理请求。
// 除了这个方式,还会有一种类 Controller,会在里面会有各种处理请求的方法。
// 举例说明:可以直接指定 UserController 里面的 Login() 来请求。
// 这个应用比较简单,没有使用 Controller 的方式
// 如果把 “/” 改成 “/dash”,那只有域名+/dash 才能访问
// 最简单的理由使用方式,先定义 URL,再写处理函数
/**
* Show Task Dashboard
*/
Route::get('/', function () {
return view('tasks', [
'tasks' => Task::orderBy('created_at', 'asc')->get()
]);
});
// 和上面不同的是,这里使用了 post 网络请求方式。
// 如果不想限制访问方式,使用 match 方法:Route::match(['get', 'post'], '/task', function(){});
// 还有一个 any 方法,任何请求方式都可以:Route::any('/task', function(){});
/**
* Add New Task
*/
Route::post('/task', function (Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}
$task = new Task;
$task->name = $request->name;
$task->save();
return redirect('/');
});
// 带参数的路由,id 作为变量,传给后面的方法
/**
* Delete Task
*/
Route::delete('/task/{id}', function ($id) {
Task::findOrFail($id)->delete();
return redirect('/');
});
});
3. 视图初探;
3.1 视图的调用;
- 视图就是一个页面文件,放到 WEB 来说就是一个 HTML 文件,会与后端有一定的交互,就是视图传递一定的数据来让用户看到。通过这样的方式,后端就可以和页面进行交互。
- 官方直接使用模板对视图进行构建。
- 视图存放路径:
quickstart/resources/view/
- 官方视图:
tasks.blade.php
、welcome.blade.php
- 如果使用模板,视图就要命名为 xxx.blade.php。如果不使用模板,命名为 xx.php 就行
- 官方视图:
3.2 向视图传递数据;
- 在 “
quickstart/resources/view/
” 下创建一个admin/hello.php
文件。PHP 是可以直接内嵌在 HTML 里面的,所以说模板也是一样的,本质上是一个 HTML 文件,在需要的地方插入 PHP 代码就可以。
<html>
<head>
<title>Hello Laravel</title>
</head>
<body>
<h1>Hello Laravel!</h1>
<h1>Hello <?php echo $name . $age;?></h1><!-- 路由定义的参数在这里可以当变量使用 -->
</body>
</html>
- 去如何访问到以上视图?访问
quickstart/app/Http/routes.php
<?php
use App\Task;
use Illuminate\Http\Request;
Route::group(['middleware' => ['web']], function () {
// 添加一条新的路由,定义一个 URL 为 /hello,再定义一个 function
// function 里面之间调用 view() 方法,Laravel 会自动处理渲染然后返回给用户
// view() 也有参数,第一个参数指定模板名称 admin.hello
// 第二个参数为数组类型。定义的参数在视图层可以当变量使用
/**
* Hello Laravel
*/
Route::get('/hello', function(){
return view('admin.hello', [
'name' => 'hualaoshuan',
'age'=> 10
]);
});
/**
* Show Task Dashboard
*/
Route::get('/', function () {
return view('tasks', [
'tasks' => Task::orderBy('created_at', 'asc')->get()
]);
});
/**
* Add New Task
*/
Route::post('/task', function (Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}
$task = new Task;
$task->name = $request->name;
$task->save();
return redirect('/');
});
/**
* Delete Task
*/
Route::delete('/task/{id}', function ($id) {
Task::findOrFail($id)->delete();
return redirect('/');
});
});
3.3 模板基本介绍;
- 使用和不使用模板差距不是非常大,因为 PHP 本身就可以内嵌在 HTML 里面,实现控制、输出功能。
- Lavarel 使用的模板是 blade 模板。视图文件名称命名为
xxx.blade.php
就行。在使用的过程中,就会自动通过 blade 模板引擎对这个视图文件进行渲染,完成后再显示给用户。如果想在 blade 模板里进行输出的话,就用{{ }}
将输出的变量括起来就行。 - 查看
quickstart/resources/view/tasks.blade.php
模板,和 HTML 最主要的区别是:HTML 输出用echo
,模板简化了输出,使用{{ $task->name }}
这种输出格式。在这里我们就认为 task 是一个类,类里面有一个角 name 的属性。用两个大括号包住。 - 两个大括号中间可以直接写变量的名字,也可以调用 PHP 的函数或者方法, 比如:
{{ csrf_field() }}
。这个是在表单中自动添加一个field(域)。Laravel 默认开启了对于 csrf 攻击的防范,在提交表单的时候会进行 csrf 的token 校验,所以直接调用函数 csrf_field() 会自动在页面生成 input 标签,里面包含着 token。 {{ method_field('DELETE') }}
和上面的 csrf_field() 相似。会生成一个方法的 field(域),指明请求是什么方法。有的浏览器它是不支持在 HTML 里面 form 的 method 属性里面去直接指明 delete 的,所以这里会伪造出一个 delete 请求,也就是在 form 里面标签的内部加上{{ method_field('DELETE') }}
这样的一条语句会自动生成一个 method field ,通过这个字段,Laravel 就会将它解析成一个 delete 请求(虽然写的是 method=“POST”)
4. 数据库初探;
4.1 数据库配置;
- 数据库的配置主要在
quickstart/.env
配置,也可以在quickstart/config/database.php
里进行配置。 - 数据库的使用方式:
quickstart/app/Http/routes.php
<?php
use App\Task;
use Illuminate\Http\Request;
Route::group(['middleware' => ['web']], function () {
Route::get('/hello', function(){
// 数据库的使用方式
// DB 类有很多静态方法:
DB::insert('INSERT INTO tasks (name) VALUES(?)', ['Laravel']);
return view('admin.hello', [
'name' => 'hualaoshuan',
'age'=> 10
]);
});
/**
* Show Task Dashboard
*/
Route::get('/', function () {
return view('tasks', [
'tasks' => Task::orderBy('created_at', 'asc')->get()
]);
});
/**
* Add New Task
*/
Route::post('/task', function (Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}
$task = new Task;
$task->name = $request->name;
$task->save();
return redirect('/');
});
/**
* Delete Task
*/
Route::delete('/task/{id}', function ($id) {
Task::findOrFail($id)->delete();
return redirect('/');
});
});
4.2 Eloquent ORM 的简介。
- 定位到
quickstart/app/Task.php
文件,这个文件就是 ORM 的 Model 的文件。 - 这个文件初始只定义了一个空的类,但是这个类继承了 Model 这个类,Model 里面定义了 PHP 各种操作数据库的方法便于使用。
- 一个 Task 这样的类,对应在数据库中的一条记录。Laravel 会自动在数据库中将所有的字段都自动的生成出来。不用在 Task 这个类里面定义字段(不用手动的去写 id,name 等字段),它或自动的从数据库中去获取到内容。
- 所有的 Model 类,它都有 save()、delete() 这样的方法,用来进行数据的插入,数据的删除等等,包括修改各种各样的操作。
- Task 类是怎么样和数据库中的 tasks 表对应?默认是对于一个 Task 来说的话,如果类名称是首字母大写的 Task,在数据库里面对应的表是就是首字母小写的 task 加 s,也就是 tasks。
- 当然也可以自己指定。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
//
// 指定所对应的数据表
protected $table = 'tasks';
// 指定主键
protected $primaryKey = 'id';
}
- 所有对 Tasks 类进行的操作都会反映到数据库里面的 tasks 表的某一条记录上。
- 然后再看
quickstart/app/Http/routes.php
,官方演示程序是怎么操作的。
<?php
use App\Task;
use Illuminate\Http\Request;
Route::group(['middleware' => ['web']], function () {
/**
* Show Task Dashboard
*/
Route::get('/', function () {
return view('tasks', [
// 加入了一个参数 tasks,就是要操作的数据表名称。
// 把 tasks 表里面的所有数据都取出来,然后按顺序排好。
// 再通过 get() 函数返回
'tasks' => Task::orderBy('created_at', 'asc')->get()
]);
});
/**
* Add New Task
*/
Route::post('/task', function (Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}
// 创建一个 Task 实例
// 对 name 进行赋值
// $request->name 是传进来的
// 调用 Task 的 save() 函数保存
$task = new Task;
$task->name = $request->name;
$task->save();
return redirect('/');
});
/**
* Delete Task
*/
Route::delete('/task/{id}', function ($id) {
// 这个方法根据主键(id)去查找表里有没有这样一条记录
// 如果有的话,就返回一个 task 类的实例、对象
// 这个对象调用了一个 delete() 函数,删除这条记录。
// Task 类没有 delete() 这条函数,但继承了 Model 这个类会给我们提供各种函数来进行处理
Task::findOrFail($id)->delete();
return redirect('/');
});
});
- 查看
quickstart/resources/view/tasks.blade.php
模板
@extends('layouts.app')
@section('content')
<div class="container">
<div class="col-sm-offset-2 col-sm-8">
<div class="panel panel-default">
<div class="panel-heading">
New Task
</div>
<div class="panel-body">
<!-- Display Validation Errors -->
@include('common.errors')
<!-- New Task Form -->
<form action="{{ url('task')}}" method="POST" class="form-horizontal">
{{ csrf_field() }}
<!-- Task Name -->
<div class="form-group">
<label for="task-name" class="col-sm-3 control-label">Task</label>
<div class="col-sm-6">
<input type="text" name="name" id="task-name" class="form-control" value="{{ old('task') }}">
</div>
</div>
<!-- Add Task Button -->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-btn fa-plus"></i>Add Task
</button>
</div>
</div>
</form>
</div>
</div>
<!-- Current Tasks -->
@if (count($tasks) > 0)
<div class="panel panel-default">
<div class="panel-heading">
Current Tasks
</div>
<div class="panel-body">
<table class="table table-striped task-table">
<thead>
<th>Task</th>
<th> </th>
</thead>
<tbody>
<!-- 使用 foreach 取出 $tasks 所有记录 -->
<!-- 首先输出 $task->name,它是哪里来的,本来是没有 name 属性的-->
<!-- 这是 Eloquent ORM 自动给类添加的,你甚至都不要管数据表里有什么 -->
@foreach ($tasks as $task)
<tr>
<td class="table-text"><div>{{ $task->name }}</div></td>
<!-- Task Delete Button -->
<td>
<form action="{{ url('task/'.$task->id) }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button type="submit" class="btn btn-danger">
<i class="fa fa-btn fa-trash"></i>Delete
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
</div>
</div>
@endsection