本人第一个laravel项目~
基本流程如下:
- 编写前端(用作测试)
- 创建并model,migration,seeder类
- 编写路由
- 编写控制器
- 编写详细逻辑
- 部署到服务器(本篇不讲)
- 上传项目到GitHub
那么我们现在就开始吧
编写前端
实际中请求后端需要设置跨域和CSRF验证.但由于我还不会(我是群里最弱的玩家.jpg),可以先进行如下设置跳过验证:
打开app/Http/Middleware/VerifyCsrfToken.php
,其中的$except
数组中储存的是可以跳过验证的url
我们可以在其中直接填上'*'
让所有请求跳过验证
protected $except = [
'*'
];
前端使用了一些laravel自带的样式,引了react的外链,使用fetch异步请求后端.前后端交互一般都是使用json形式的post请求.
由于需要加载react的外链,使用时需要联网
没什么好说的,毕竟我的作业主要是后端部分,就直接贴代码了吧
注意文件名一定要是*.blade.php
,放到resource/views下或其次级目录下
下面这份代码我自己是保存为baoming.blade.php
,放到了resource/views/baoming
目录下
后端响应的信息都显示在控制台(懒得写更多样式了)
@extends('layouts.app')
@section('content')
<meta name="csrf-token" content="{{ csrf_token() }}">
<div style="margin-left:35%;width: 25%">
<form action="javascript:judge();" id="baoming" >
<div class="form-group">
<label class="col-md-4 control-label"><span style="color:red">*</span>姓名</label>
<input class="form-control" name="name" />
</div>
<div class="form-group">
<label class="col-md-4 control-label"><span style="color:red">*</span>性别</label><br/>
<input type="radio" name="sex" value="male" checked />男
<input type="radio" name="sex" value="female" style="margin-left:50px" />女
</div>
<div class="form-group">
<label class="col-md-4 control-label"><span style="color:red">*</span>电话号码</label>
<input class="form-control" name="phone"/>
</div>
<div class="form-group">
<label class="col-md-4 control-label"><span style="color:red">*</span>邮箱</label>
<input class="form-control" name="email" />
</div>
<div class="form-group">
<label class="col-md-4 control-label"><span style="color:red">*</span>学号</label>
<input class="form-control" name="xuehao" />
</div>
<div class="form-group">
<label class="col-md-4 control-label"><span style="color:red">*</span>学院</label>
<input class="form-control" name="college" />
</div>
<div class="form-group">
<label class="col-md-4 control-label"><span style="color:red">*</span>专业</label>
<input class="form-control" name="major" />
</div>
<div class="form-group">
<label class="col-md-4 control-label"> 备注</label>
<input class="form-control" name="beizhu" />
</div>
<div style="text-align:center;">
<button type="submit" class="btn btn-primary">
提交
</button>
</div>
</form>
<div style="text-align:center;">
<button type="submit" class="btn btn-primary" onclick="showTable();" >
获取整个表
</button>
</div>
</div>
@endsection
<script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
<script type="text/babel">
function judge(){
let Form = document.getElementById("baoming");
let form_data = {};
let inputs = Form.getElementsByTagName('input');
for(let i = 0;i < inputs.length; ++i){
form_data[inputs[i].name] = inputs[i].value;
}
fetch('baoming',{
method: 'POST',
headers: {
"Content-Type": "text/json"
},
body: JSON.stringify(form_data),
}).then(function(res){
if(res.status != 200){
console.log("Error, status: " + res.status);
return;
}else{
console.log("Success, status: " + res.status);
return res;
}
}).then(function(res){
console.log(res.json());
}).catch(function(err){
console.log("Fetch error: " + err);
})
}
function showTable() {
fetch('baoming/show',{
method: 'POST',
}).then(function(res){
if(res.status != 200){
console.log("Error, status: " + res.status);
return;
}else{
console.log("Success, status: " + res.status);
return res;
}
}).then(function(res){
console.log(res.json());
}).catch(function(err){
console.log("Fetch error: " + err);
})
}
</script>
创建并使用Model和Migration类
在项目目录的命令行窗口下,依次输入以下指令
# php artisan make:model Baoming
# php artisan make:migration create_baomings_table
然后找到database/migrations
目录下你刚刚创建的名字中含有create_baomings_table.php
的文件
在其中的up
方法内填入以下内容来创建指定格式的数据表
extra:由于Model类默认的数据表为派生的Model类名+s
,所以创建的数据表名为baomings
Schema::create('baomings', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('sex');
$table->string('phone');
$table->string('email');
$table->string('xuehao');
$table->string('college');
$table->string('major');
$table->string('beizhu')->nullable();
$table->timestamps();
});
完成后保存退出,在项目目录命令行下使用以下命令来启用镜像
artisan migrate
在mysql命令行下使用desc baomings
可以看到刚刚创建的表的结构
mysql> desc baomings;
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| sex | varchar(255) | NO | | NULL | |
| phone | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | | NULL | |
| xuehao | varchar(255) | NO | | NULL | |
| college | varchar(255) | NO | | NULL | |
| major | varchar(255) | NO | | NULL | |
| beizhu | varchar(255) | YES | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+------------------+------+-----+---------+----------------+
11 rows in set (0.00 sec)
即以int型数字id
排序,后面跟上8个字符串,其中beizhu
可以为空,再后面跟上时间戳
id和时间戳会在插入数据时自动生成
如果你想插入一些假数据用作测试,可以使用seeder:
在命令行下输入
php artisan make:seeder BaomingSeeder
然后在database/seeds
目录下的BaomingSeeder
中的run
函数中填入插入数据逻辑
$selectSex = function($n){
return ($n % 2 ? 'male' : 'female');
};
$writeBeizhu = function($n){
if($n < 5){
return 'WD牛逼啊!'.$n;
}else{
return null;
}
};
for($i = 0; $i < 10; ++$i){
\App\Baoming::create([
'name' => 'TestName'.$i,
'sex' => $selectSex($i),
'phone' => '123456'.$i,
'email' => 'TestEmail'.$i.'@email.com',
'xuehao' => '2017000'.$i,
'college' => 'WD第'.$i.'牛逼学院',
'major' => 'WD第'.$i.'牛逼专业',
'beizhu' => $writeBeizhu($i),
]);
}
完成后保存,在同一目录下的DataBaseSeeder.php
的run
方法中注册播种机
public function run()
{
$this->call(BaomingSeeder::class);
}
完成后回到项目目录,在命令行中运行以下命令来启用播种机
artisan db:seed
运行完成后可以在数据库中查看刚才生成的假数据
编写路由
首先打开routes/web.php
这里我使用的是资源路由.资源路由自带了一些各种方式的http请求的操作处理,可以避免我们编写重复的路由
资源路由的写法如下:
Route::resource('baoming', 'BaomingController');
资源路由中自带的各种操作处理如下:
photos替换为你在资源路由中写入的第一个参数,这里是baoming
第一行是http请求方法,第二行是对应的URL路径,第三行是控制器中对应的方法
不过我需要两个不同的POST请求操作,然而资源路由只自带了一个POST请求的操作,所以还要在下面添加一个post路由.
所以我们填写的路由就变为了:
Route::resource('baoming', 'BaomingController');
Route::post('baoming/show', 'BaomingController@showTable');
编写控制器
首先使用以下命令来创建一个控制器
artisan make:controller BaomingController
生成的控制器在app/Http/Controllers
下
接下来要编写控制器逻辑
考虑待会要实现三个功能:
1.显示前端页面,由GET方法请求
2.接收前端发送的用户填好的表单,由POST方法请求
3.用户点击按钮后返回数据表中的所有数据,个人使用POST方法请求,GET也可
所以我们需要编写三个方法待路由调用,顺便待会编写详细逻辑时还需要引用自定义的BaomingAPI
类,需要用绝对命名空间引用它
写好的整个控制器文件如下
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
//注意这里引用了BaomingAPI
use App\BaomingAPI\BaomingAPI;
class BaomingController extends Controller
{
//显示前端页面
public function index(){
return view('baoming/home');
}
//增改数据
public function store(Request $request){
$bm = new BaomingAPI();
//如果前端发送的是一个post表单,使用$request->all()会得到一个键值对数组
return response($bm->handle($request->all()));
}
//返回所有数据
public function showTable(Request $request){
$bm = new BaomingAPI();
return response($bm->showTable());
}
}
编写详细逻辑
laravel会自动加载app
目录下的所有类,所以自定义类一般放在这个目录下的合适位置,并使用从这个目录开始
的绝对命名空间
现在我们就在app目录下创建一个名为BaomingAPI
的目录,接着在里面创建一个名为BaomingAPI.php
的php文件
并在里面先填上它的命名空间:
<?php namespace App\BaomingAPI;
然后待会需要使用DB
类来进行数据库操作,先绝对命名空间引用它吧
use Illuminate\Support\Facades\DB;
然后是创建一个BaomingAPI
类,使得控制器调用方便
class BaomingAPI{};
然后我们就可以在这个类里愉快地填上详细逻辑啦
首先考虑一下我们需要什么:
1.两个接口,其中一个用于增改数据,其中一个用于返回整个数据表
2.判断表单是否合法,虽然主要是在前端判断,但是后端也要判断一下防止恶意请求
3.进行数据库操作来实现增改数据
4.一个用于返回各种信息(报错,是否成功等)的键值对数组
在实现的过程中再增加一些细节,最终我们就可以写出如下代码啦~(以下为整个BaomingAPI.php文件)
<?php namespace App\BaomingAPI;
use Illuminate\Support\Facades\DB;
class BaomingAPI{
private $table = 'baomings'; //数据表名
private $return_arr = array(); //要返回的键值对数组(最后要转换成json对象再返回)
private $receive_arr; //得到的json转换成的键值对数组
private $should_have = [ //判断数据是否合法时使用,'beizhu'并非必须项所以在此没有
'name', 'sex', 'phone', 'email', 'xuehao' , 'college', 'major'
];
private function judge(){
//判断
foreach ($this->should_have as $key){
if(!isset($this->receive_arr[$key])){
$this->return_arr = array_merge($this->return_arr, ['code' => '-1','message' => $key.'_not_set']);
return false;
}else if(mb_strlen($this->receive_arr[$key]) > 30){
$this->return_arr = array_merge($this->return_arr, ['code' => '-2','message' => $key.'too_long']);
return false;
}
}
if(isset($this->receive_arr['beizhu'])){
if(mb_strlen($this->receive_arr['beizhu']) > 256){
$this->return_arr = array_merge($this->return_arr, ['code' => '-2','message' => 'beizhu_too_long']);
return false;
}
}
return true;
}
private function write(){
try {
$name = DB::table($this->table)->where('name','=',$this->receive_arr['name'])->first();
if($name != null){
DB::table($this->table)->where('name','=',$this->receive_arr['name'])->update([
'sex' => $this->receive_arr["sex"],
'phone' => $this->receive_arr["phone"],
'email' => $this->receive_arr["email"],
'xuehao' => $this->receive_arr["xuehao"],
'college' => $this->receive_arr["college"],
'major' => $this->receive_arr["major"],
'beizhu' => $this->receive_arr["beizhu"],
]);
return;
}
$phone = DB::table($this->table)->where('phone','=',$this->receive_arr['phone'])->first();
if($phone != null){
DB::table($this->table)->where('phone','=',$this->receive_arr['phone'])->update([
'name' => $this->receive_arr['name'],
'sex' => $this->receive_arr["sex"],
'email' => $this->receive_arr["email"],
'xuehao' => $this->receive_arr["xuehao"],
'college' => $this->receive_arr["college"],
'major' => $this->receive_arr["major"],
'beizhu' => $this->receive_arr["beizhu"],
]);
return;
}
DB::table($this->table)->insert([
'name' => $this->receive_arr['name'],
'sex' => $this->receive_arr["sex"],
'phone' => $this->receive_arr["phone"],
'email' => $this->receive_arr["email"],
'xuehao' => $this->receive_arr["xuehao"],
'college' => $this->receive_arr["college"],
'major' => $this->receive_arr["major"],
'beizhu' => $this->receive_arr["beizhu"],
]);
}catch(Exception $e){
$this->return_arr = array_merge($this->return_arr,
['code' => '-3', 'message' => '写入数据库失败'.$e->getMessage()]);
}
}
private function returnJson(){
return json_encode($this->return_arr);
}
/**
* 增改数据
* @return array(json)
*/
public function handle($request){
$this->receive_arr = $request;
if($this->judge()){
$this->write();
if(!isset($this->return_arr['code'])){
$this->return_arr = array_merge($this->return_arr,["code" => "0","message" => "ok"]);
}
}
return $this->returnJson();
}
/**
* 查询整个表
* @return array(json)
*/
public function showTable(){
$this->return_arr = DB::table($this->table)->get();
return $this->returnJson($this->return_arr);
}
};
然后就可以开启服务,访问域名/baoming
看看效果啦
将项目上传到GitHub
安装git
首先安装好Git
然后在任意位置右键,选择Git Bash Here
打开git命令行
设置账户
先使用以下两行命令设置好你的GitHub账户($不用打,下面都是)
$ git config --global user.name 'yourAccountName'
$ git config --global user.email 'your@email.com'
yourAccountName
为你的账户名,your@email.com
为你的私人邮箱(即可以用来登录的邮箱)
设置SSH密钥
首先使用以下两行命令来看你本机有没有设置ssh密钥
$ cd ~/.ssh
$ ls
如果出现了以下输出,则说明安装过了
id_rsa id_rsa.pub known_hosts
否则使用以下命令来创建(注意要改成你自己的邮箱)
$ ssh-keygen -t rsa -C "your@email.com"
然后再ls
,看看有没有创建成功
id_rsa
文件里的是你的私钥,id_rsa.pub
里的是你的公钥,我们接下来需要将公钥上传给GitHub
那么就先来获取一下公钥,使用以下指令
$ cat id_rsa.pub
会获得一长串输出,类似如下(已打码处理
ssh-rsa AAAAB3NzaC1ycxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEAW0rKrpHc35fSZNAuKkDLGT4F9JfkMeR2jJa4nV/sOYndVC0TNvaKsDB2V3ihGmsHrPeEb/L elatis@Dwdnba
把得到的所有输出先复制下来
然后在网页上登录你的GitHub,按如下操作
title是为了你自己区分,随意填
创建本地仓库
打开你的项目目录,先把里面的vendor
文件夹移出去,因为这个文件夹里的都是项目依赖,可以通过composer install
重新安装,不需要上传
然后在里面运行git bash
使用以下命令初始化
$ git init
添加项目下所有文件到本地仓库
$ git add .
创建并关联云端仓库
在GitHub中创建一个仓库(repository):
创建完成后进入仓库,可以看到箭头所指的url,将它复制下来
然后执行以下命令将本地仓库管理到云端仓库:
$ git remote add origin http://github.com/elatisy/mylaravel_-_-.git
注意后面的url要改成你自己的
如果出现错误:fatal: remote origin already exists
,那么就先删除关联再重新关联:
$ git remote rm origin
$ git remote add origin http://github.com/elatisy/mylaravel_-_-.git
上传文件
首先输入本次提交说明,每次提交前都要输入,否则git不会开始准备提交暂存区中的已更改文件
$ git commit -m "layout"
其中layout
可以替换成本次提交的说明内容
最后执行
$ git push origin master
即可将本地文件上传到云端仓库的master
分支
如果出现failed to push som refs to…
,可能是云端的文件和本地不同步,它不允许你直接覆盖
就先执行以下命令拉取云端文件
$ git pull origin master
然后再次上传
$ git push origin master
如果还是不行,就使用-f
强行上传,当然首先你得先确认云端仓库上的文件你都不需要了
$ git push -f origin master
最后重新进入云端仓库,就可以看到你刚才上传的文件了
总结
本次虽然大致完成了布置的作业,但水平与一个良好的项目还相差甚远
对比学长做的项目可以看出我的架构能力还是不行
而且还有以下几点没有完成:
1.验证请求
2.进行csrf验证
3.设置好跨域
待周末试着完成一下以上三点
评论