{ Hello Magento 2 }

解决 Magento 2 应用问题,更注重深度挖掘。(ง •̀_•́)ง

0%

Laravel 5.5 Beginner Task List

博主认为,最好的教程一定是官方文档。而要快速建立关于某个语言或框架的知识结构,一定是直接上手做一个小项目。 Laravel 5.5 于今年 8 月份发布,是下一个 LTS 版本,从这个版本发布开始会停止对 Laravel 5.1 的 bug 修复,而对 5.1 的安全修复直到 2018 年 7 月份。 LTS 是指长期支持版本,是 Laravel 能提供的最长时间维护的版本,一般发行版只提供 6 个月的 Bug 修复支持,一年的安全修复支持。所以商业用途最好使用 LTS 版本。 关于 LTS 可参考 Laravel 的发布路线图 网上关于 Laravel 的教程很多,但是教程的基本内容无非是了解 laravel 的 MVC ,然后做数据的增删改查。 官方文档其实就很好,该 tutorials 中包括两个部分,一个是 Beginner Task List 另一个是 Intermediate Task List 。可惜的是 5.5 目前还没有这部分的内容。 但是差异也不是很大,原文地址 Beginner Task List 本文是以上面的 5.1 文档为参考,以 5.5 为开发框架,进行了实践后,记录下来的。 本文中使用的环境是 ubuntu + apache + mysql + php ,使用的 hyper-v 虚拟机,关于这部分,对读者可能没有价值,可跳过。但对博主个人有记录以备后查的作用,所以会写下来。

安装 Laravel

我同时安装了 Laravel 5.1 和 Laravel 5.5 ,一个给到 51 端口,一个给到 55 端口。

环境要求

Laravel 5.5 系统要求

Laravel 5.1 系统要求

PHP >= 7.0.0 OpenSSL PHP Extension PDO PHP Extension Mbstring PHP Extension Tokenizer PHP Extension XML PHP Extension

PHP >= 5.5.9 OpenSSL PHP Extension PDO PHP Extension Mbstring PHP Extension Tokenizer PHP Extension

通过 Laravel installer 安装 5.5 (最新的)

1
composer global require "laravel/installer"

如果此时输入 laravel 一定会提示 laravel: command not found 这是因为该命令不在环境变量中 查看环境变量:

1
2
$ echo $PATH
/home/thankit/bin:/home/thankit/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

一般情况下的 composer vendor bin 目录在:

  • MacOS: $HOME/.composer/vendor/bin
  • GNU / Linux Distributions: $HOME/.config/composer/vendor/bin

下面我们要将该变量添加到 $PATH 中

1
export PATH="~/.config/composer/vendor/bin:$PATH"

下面可以用 laravel 命令了。 切换到工作目录下,比如 todo55

1
laravel new

这样就会在当前目录下安装 laravel 下面我们查看下 laravel 的版本号

1
2
$ php artisan --version
Laravel Framework 5.5.20

通过 composer 安装 5.1

将 5.1 版本的放在目录 todo51 下 在 todo51 目录下

1
composer create-project laravel/laravel  ./ "5.1.*"

同样看下版本号:

1
2
$ php artisan --version
Laravel Framework version 5.1.46 (LTS)

设置权限

storagebootstrap/cache 目录, web 服务器必须具有可写权限。 对我来说,我需要给组 www-data 写权限

1
chmod g+w -R storage bootstrap/cache

设置虚拟目录 (可跳过)

确保 mod_rewrite 开启了,这样 public/.htaccess 就有作用了。 以下是针对 Apache 的 启用 Apache rewrite 模块 a2enmod rewrite 我将让 todo51 监听 51 端口,而 todo55 监听 55 端口 首先将 varnish 监听端口从 80 上改到 6082 其次修改 /etc/apache2/ports.conf 增加监听的端口 然后修改 /etc/apache2/sites-available/000-default.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<VirtualHost *:51>

DocumentRoot /home/thankit/www/laravel/todo51/public
<Directory /home/thankit/www/laravel/todo51/public>
AllowOverride all
# Options +FollowSymLinks
# RewriteEngine On
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteRule ^ index.php [L]
</Directory>

</VirtualHost>
<VirtualHost *:55>

DocumentRoot /home/thankit/www/laravel/todo55/public
<Directory /home/thankit/www/laravel/todo55/public>
AllowOverride all
# Options +FollowSymLinks
# RewriteEngine On
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteRule ^ index.php [L]
</Directory>

</VirtualHost>

看看是否监听了端口

1
netstat -lntp

一切正常, 将通过 http://192.168.0.251:51/ 访问 5.1 的 todo laravel 5.1 安装成功 将通过 http://192.168.0.251:55/ 访问 5.5 的 todo laravel 5.5 安装报错 下面我们得看看 5.5 为什么报错了。 我们进入 todo5.5 的目录,修改 config/app.php 将 debug 打开

1
'debug'  => env('APP_DEBUG', true),

下面我们再刷新,看看错误是什么

1
2
RuntimeException
No application encryption key has been specified.

下面直接将 .env.example 拷贝一份重命名为 .env 然后运行命令

1
2
5$ php artisan key:generate
Application key [base64:aJqES8WcAQJJ0jjoMKeQojV0TWnae5ALs8JQnm/uW5w=] set successfully.

下面再打开网站看看,这次正常了:

Task List 创建

数据库迁移

首先对数据库帐密进行设置,有两处 config\database.php.env .env 是主配置文件,会覆盖 database.php 中的参数 我们设置好 .env 中关于 db 的部分 执行:

1
php artisan make:migration create_tasks_table --create=tasks

他将在 database/migrations/ 目录下创建类似 YYYY_M_DD_HHMMSS_create_tableName_table.php 的文件,就像2017_11_08_064436_create_tasks_table.php 其中的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTasksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('tasks');
}
}

该类包含了两个方法,up() (执行迁移命令时创建表结构)和 down() (执行回滚时删除表结构) 更多的参考 Database: Migrations 下面我们给他添加一个字段 name

1
2
3
4
5
6
7
8
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}

下面执行数据迁移:

1
php artisan migrate

然后我们进入数据库中看看,tasks 表被创建出来了 下面试一下回滚:

1
php artisan migrate:rollback

在看看数据库中的表都被删除了。 php artisan migrate:refresh 全部回滚重建

数据库填充

我们将创建一个 Task model 对应我们的表 tasks 默认规则是模型类名的复数作为与其对应的表名,除非在模型类中明确指定了其它名称。

1
php artisan make:model Task

他在 app 目录下创建了 Task.php 内容如下:

1
2
3
4
5
6
7
8
9
10
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
//
}

下面我们创建自动填充文件:

1
php artisan make:seeder TasksTableSeeder

他将在 database/seeds 目录下创建 TasksTableSeeder.php ,这个文件就是数据库填充文件了,他的命名规则是数据库表名加上 TableSeeder 并且首字母大写,表名一般是复数,所以我们有了 TasksTableSeeder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#File: database/seeds/TasksTableSeeder.php
<?php

use App\Task;
use Illuminate\Database\Seeder;

class TasksTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::table('tasks')->insert(['name' => str_random(10)]);
Task::create(['name' => 'thankit']);
}
}

然后将 DatabaseSeeder.php 添加内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// $this->call(UsersTableSeeder::class);
$this->call(TasksTableSeeder::class);
}
}

最后我们来运行命令:

1
php artisan db:seed

之后我们就可以在数据库中看看表中数据了:

路由

routes/web.php 文件用于定义 web 界面的路由。这里面的路由都会被分配给 web 中间件组,它提供了会话状态和 CSRF 保护等功能。定义在 routes/api.php 中的路由都是无状态的,并且被分配了 api 中间件组。 所以我们在 web.php 中添加以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
use Illuminate\Http\Request;
Route::get('/', function () {
return view('tasks');
});

/**
* Add A New Task
*/
Route::post('/task', function (Request $request) {
//
});

/**
* Delete An Existing Task
*/
Route::delete('/task/{id}', function ($id) {
//
});

创建父 blade 模版

File:resources/views/layouts/app.blade.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<title>Laravel Quickstart - Basic</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" crossorigin="anonymous">
<!-- CSS And JavaScript -->
</head>

<body>
<div class="container">
<nav class="navbar navbar-default">
<!-- Navbar Contents -->
</nav>
</div>

@yield('content')
</body>
</html>

子 blade 模版

File:resources/views/tasks.blade.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@extends('layouts.app')

@section('content')

<!-- Bootstrap Boilerplate... -->

<div class="panel-body">
<!-- Display Validation Errors -->
<?php // @include('common.errors') ;?>

<!-- New Task Form -->
<form action="/task" method="POST" class="form-horizontal">
&#123;&#123; csrf_field() &#125;&#125;

<!-- Task Name -->
<div class="form-group">
<label for="task" class="col-sm-3 control-label">Task</label>

<div class="col-sm-6">
<input type="text" name="name" id="task-name" class="form-control">
</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-plus"></i> Add Task
</button>
</div>
</div>
</form>
</div>

<!-- TODO: Current Tasks -->
@endsection

解释,还是英文的说的好理解,所以附上: the @extends directive informs Blade that we are using the layout we defined at resources/views/layouts/app.blade.php. All of the content between @section('content') and @endsection will be injected into the location of the @yield('content') directive within the app.blade.php layout 起码看起来有点样子了 Laravel 5.5

验证输入并增加 tasks

修改 web.php 中的路由:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 这里不能少
use Illuminate\Http\Request;

Route::post('/task', function (Request $request) {

$validator = Validator::make($request->all(), [
'name' => 'requiredmax:255',
]);

if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}

// Create The Task...
});

这样去掉 resources/views/tasks.blade.php 中的注释

1
@include('common.errors')

补上模版: resources/views/common/errors.blade.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@if (count($errors) > 0)
<!-- Form Error List -->
<div class="alert alert-danger">
<strong>Whoops! Something went wrong!</strong>

<br><br>

<ul>
@foreach ($errors->all() as $error)
<li>&#123;&#123; $error &#125;&#125;</li>
@endforeach
</ul>
</div>
@endif

现在如果我们提交空值,就会有错误提示了。 Laravel 5.5 下面我们要增加 tasks 所以修改 web.php 的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use App\Task;
use Illuminate\Http\Request;
/**
* Display All Tasks
*/
Route::get('/', function () {
return view('tasks');
});

/**
* Add A New Task
*/
Route::post('/task', function (Request $request) {

$validator = Validator::make($request->all(), [
'name' => 'requiredmax:255',
]);

if ($validator->fails()) {
return redirect('/')
->withInput(['name' => 'reminder'])
->withErrors($validator);
}

// Create The Task...
$task = new Task;
$task->name = $request->name;
$task->save();

return redirect('/');
});
...

所以接下来我们测试提交一个 task ,发现已经添加到数据库表中了。

展示已经有的 tasks

File:routes/web.php

1
2
3
4
5
6
Route::get('/', function () {
$tasks = Task::orderBy('created_at', 'asc')->get();
return view('tasks', [
'tasks' => $tasks,
]);
});

File:resoures/views/tasks.blade.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@extends('layouts.app')

@section('content')
<!-- Create Task Form...这里有省略 -->

<!-- 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">

<!-- Table Headings -->
<thead>
<th>Task</th>
<th>&nbsp;</th>
</thead>

<!-- Table Body -->
<tbody>
@foreach ($tasks as $task)
<tr>
<!-- Task Name -->
<td class="table-text">
<div>&#123;&#123; $task->name &#125;&#125;</div>
</td>

<td>
<!-- TODO: Delete Button -->
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
@endsection

效果如下: Laravel 5.5

删除 tasks

上面的文件中我们留了一个删除按钮没有写 下面补上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<tr>
<!-- Task Name -->
<td class="table-text">
<div>&#123;&#123; $task->name &#125;&#125;</div>
</td>

<td>
<form action="/task/&#123;&#123; $task->id &#125;&#125;" method="POST">
&#123;&#123; csrf_field() &#125;&#125;
&#123;&#123; method_field('DELETE') &#125;&#125;

<button type="submit" class="btn btn-danger">Delete Task</button>
</form>
</td>
</tr>

注意这里的 &#123;&#123; method_field('DELETE') &#125;&#125; 等同于

1
<input type="hidden" name="_method" value="DELETE">

File:routes/web.php

1
2
3
4
Route::delete('/task/{id}', function ($id) {
Task::findOrFail($id)->delete();
return redirect('/');
});

最后的效果如下: Task List 最终效果