Laravel-admin框架的安装

一、Laravel-admin安装

1、系统环境
CentOS-7.4
Nginx1.11.5
Mysql5.7
PHP-7.2.5

2、Laravel版本
Laravel-5.6

3、Laravel安装
cd /var/www/html #进入网站根目录
composer create-project –prefer-dist laravel/laravel blog #blog是项目名称可以自己随意修改
vim .env #修改你配置文件的数据库连接参数

*数据库连接参数
DB_CONNECTION=mysql #连接数据库类型
DB_HOST=127.0.0.1 #数据库IP地址 一般本地是为127.0.0.1最好不要写localhost
DB_PORT=3306 #数据库端口
DB_DATABASE=database#数据库名 你要连接的数据库名称
DB_USERNAME= #数据库用户名
DB_PASSWORD= #数据库密码

4、Laravel-admin安装
cd /var/www/html/blog #这里的blog是你第三步建立的项目名称
composer require encore/laravel-admin “1.5.*” #用composer安装laravel-admin
php artisan vendor:publish –provider=”Encore\Admin\AdminServiceProvider” #发布资源
php artisan admin:install #安装laravel-admin并进行数据库迁移

到此laravel-admin安装完成,现在可以访问http://127.0.0.1/blog/public/admin

用户名:admin
密码:admin

5、常见问题
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQ
L: alter table `users` add unique `users_email_unique`(`email`))

解决办法:
看错误显示是字段的问题,修改数据库配置文件 config.php\databases.php
‘charset’ => ‘utf8’,
‘collation’ => ‘utf8_unicode_ci’,
‘prefix’ => ”,
‘strict’ => true,
‘engine’ => ‘InnoDB’,

修改完成后再次运行php artisan admin:install
———————

Nginx phpstudy 怎么配置隐藏index.php?
windows系统 phpstudy集成环境,nginx服务, 安装laravel后除了首页可以访问,make:auth后的注册和登录页面都不能访问,网上查找原因发现只要在域名后面把index.php写上就行,然后知道是pathinfo 的问题,在nginx的vhosts.conf文件上按照文档的指导加了一行
try_files $uri $uri/ /index.php?$query_string;

这个是我的vhost.conf配置文件内容,除了上面一行,其它都没动:

server {
listen 80;
server_name hctxi.com hctxi.com;
root “C:\PhpStudy\PHPTutorial\WWW\Now\laravel56\public”;
location / {
index index.html index.htm index.php;
#autoindex on;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include fastcgi_params;
}
}

0.0.0.0 account.jetbrains.com

K71U8DBPNE-eyJsaWNlbnNlSWQiOiJLNzFVOERCUE5FIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiIiwiYXNzaWduZWVFbWFpbCI6IiIsImxpY2Vuc2VSZXN0cmljdGlvbiI6IkZvciBlZHVjYXRpb25hbCB1c2Ugb25seSIsImNoZWNrQ29uY3VycmVudFVzZSI6ZmFsc2UsInByb2R1Y3RzIjpbeyJjb2RlIjoiSUkiLCJwYWlkVXBUbyI6IjIwMTktMDUtMDQifSx7ImNvZGUiOiJSUzAiLCJwYWlkVXBUbyI6IjIwMTktMDUtMDQifSx7ImNvZGUiOiJXUyIsInBhaWRVcFRvIjoiMjAxOS0wNS0wNCJ9LHsiY29kZSI6IlJEIiwicGFpZFVwVG8iOiIyMDE5LTA1LTA0In0seyJjb2RlIjoiUkMiLCJwYWlkVXBUbyI6IjIwMTktMDUtMDQifSx7ImNvZGUiOiJEQyIsInBhaWRVcFRvIjoiMjAxOS0wNS0wNCJ9LHsiY29kZSI6IkRCIiwicGFpZFVwVG8iOiIyMDE5LTA1LTA0In0seyJjb2RlIjoiUk0iLCJwYWlkVXBUbyI6IjIwMTktMDUtMDQifSx7ImNvZGUiOiJETSIsInBhaWRVcFRvIjoiMjAxOS0wNS0wNCJ9LHsiY29kZSI6IkFDIiwicGFpZFVwVG8iOiIyMDE5LTA1LTA0In0seyJjb2RlIjoiRFBOIiwicGFpZFVwVG8iOiIyMDE5LTA1LTA0In0seyJjb2RlIjoiR08iLCJwYWlkVXBUbyI6IjIwMTktMDUtMDQifSx7ImNvZGUiOiJQUyIsInBhaWRVcFRvIjoiMjAxOS0wNS0wNCJ9LHsiY29kZSI6IkNMIiwicGFpZFVwVG8iOiIyMDE5LTA1LTA0In0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMTktMDUtMDQifSx7ImNvZGUiOiJSU1UiLCJwYWlkVXBUbyI6IjIwMTktMDUtMDQifV0sImhhc2giOiI4OTA4Mjg5LzAiLCJncmFjZVBlcmlvZERheXMiOjAsImF1dG9Qcm9sb25nYXRlZCI6ZmFsc2UsImlzQXV0b1Byb2xvbmdhdGVkIjpmYWxzZX0=-Owt3/+LdCpedvF0eQ8635yYt0+ZLtCfIHOKzSrx5hBtbKGYRPFDrdgQAK6lJjexl2emLBcUq729K1+ukY9Js0nx1NH09l9Rw4c7k9wUksLl6RWx7Hcdcma1AHolfSp79NynSMZzQQLFohNyjD+dXfXM5GYd2OTHya0zYjTNMmAJuuRsapJMP9F1z7UTpMpLMxS/JaCWdyX6qIs+funJdPF7bjzYAQBvtbz+6SANBgN36gG1B2xHhccTn6WE8vagwwSNuM70egpahcTktoHxI7uS1JGN9gKAr6nbp+8DbFz3a2wd+XoF3nSJb/d2f/6zJR8yJF8AOyb30kwg3zf5cWw==-MIIEPjCCAiagAwIBAgIBBTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTE1MTEwMjA4MjE0OFoXDTE4MTEwMTA4MjE0OFowETEPMA0GA1UEAwwGcHJvZDN5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcQkq+zdxlR2mmRYBPzGbUNdMN6OaXiXzxIWtMEkrJMO/5oUfQJbLLuMSMK0QHFmaI37WShyxZcfRCidwXjot4zmNBKnlyHodDij/78TmVqFl8nOeD5+07B8VEaIu7c3E1N+e1doC6wht4I4+IEmtsPAdoaj5WCQVQbrI8KeT8M9VcBIWX7fD0fhexfg3ZRt0xqwMcXGNp3DdJHiO0rCdU+Itv7EmtnSVq9jBG1usMSFvMowR25mju2JcPFp1+I4ZI+FqgR8gyG8oiNDyNEoAbsR3lOpI7grUYSvkB/xVy/VoklPCK2h0f0GJxFjnye8NT1PAywoyl7RmiAVRE/EKwIDAQABo4GZMIGWMAkGA1UdEwQCMAAwHQYDVR0OBBYEFGEpG9oZGcfLMGNBkY7SgHiMGgTcMEgGA1UdIwRBMD+AFKOetkhnQhI2Qb1t4Lm0oFKLl/GzoRykGjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBggkA0myxg7KDeeEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4ICAQC9WZuYgQedSuOc5TOUSrRigMw4/+wuC5EtZBfvdl4HT/8vzMW/oUlIP4YCvA0XKyBaCJ2iX+ZCDKoPfiYXiaSiH+HxAPV6J79vvouxKrWg2XV6ShFtPLP+0gPdGq3x9R3+kJbmAm8w+FOdlWqAfJrLvpzMGNeDU14YGXiZ9bVzmIQbwrBA+c/F4tlK/DV07dsNExihqFoibnqDiVNTGombaU2dDup2gwKdL81ua8EIcGNExHe82kjF4zwfadHk3bQVvbfdAwxcDy4xBjs3L4raPLU3yenSzr/OEur1+jfOxnQSmEcMXKXgrAQ9U55gwjcOFKrgOxEdek/Sk1VfOjvS+nuM4eyEruFMfaZHzoQiuw4IqgGc45ohFH0UUyjYcuFxxDSU9lMCv8qdHKm+wnPRb0l9l5vXsCBDuhAGYD6ss+Ga+aDY6f/qXZuUCEUOH3QUNbbCUlviSz6+GiRnt1kA9N2Qachl+2yBfaqUqr8h7Z2gsx5LcIf5kYNsqJ0GavXTVyWh7PYiKX4bs354ZQLUwwa/cG++2+wNWP+HtBhVxMRNTdVhSm38AknZlD+PTAsWGu9GyLmhti2EnVwGybSD2Dxmhxk3IPCkhKAK+pl0eWYGZWG3tJ9mZ7SowcXLWDFAk0lRJnKGFMTggrWjV8GYpw5bq23VmIqqDLgkNzuoog==

Laravel 系列入门教程(五)【最适合中国人的 Laravel 教程】

本文是本系列教程的完结篇,我们将一起给 Article 加入评论功能,让游客在前台页面可以查看、提交、回复评论,并完成后台评论管理功能,可以删除、编辑评论。Article 和评论将使用 Laravel Eloquent 提供的“一对多关系”功能大大简化模型间关系的复杂度。最终,我们将得到一个个人博客系统的雏形,并布置一个大作业,供大家实战练习。

本篇文章中我将会使用一些 Laravel 的高级功能,这些高级功能对新手理解系统是不利的,但熟手使用这些功能可以大幅提升开发效率。

回顾 Eloquent

前面我们已经说过,Laravel Eloquent ORM 是 Laravel 中最强大的部分,也是 Laravel 能如此流行最重要的原因。中文文档在:https://d.laravel-china.org/docs/5.5/eloquent

learnlaravel5/app/Article.php 就是一个最简单的 Eloquent Model 类:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
//
}

 

若想进一步了解 Eloquent 推荐阅读系列文章:深入理解 Laravel Eloquent

构建评论系统

基础规划

我们需要新建一个表专门用来存放每一条评论,每一条评论都属于某一篇文章。评论之间的层级关系比较复杂,本文为入门教程,主要是为了带领大家体验模型间关系,就不再做过多的规划了,将“回复别人的评论”暂定为简单的在评论内容前面增加 @johnlui 这样的字符串。

建立 Model 类和数据表

创建名为 Comment 的 Model 类,并顺便创建附带的 migration,在 learnlaravel5 目录下运行命令:

php artisan make:model Comment -m

这样一次性建立了 Comment 类和 learnlaravel5/database/migrations/2017_11_11_151823_create_comments_table.php 两个文件。填充该文件的 up 方法,给 comments 表增加字段:

public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->string('nickname');
$table->string('email')->nullable();
$table->string('website')->nullable();
$table->text('content')->nullable();
$table->integer('article_id');
$table->timestamps();
});
}

之后运行命令:

php artisan migrate

去数据库里瞧瞧,comments 表已经躺在那儿啦。

建立“一对多关系”

在 Article 模型中增加一对多关系的函数:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
public function hasManyComments()
{
return $this->hasMany('App\Comment', 'article_id', 'id');
}
}

搞定啦!Eloquent 中模型间关系就是这么简单!

模型间关系中文文档:http://laravel-china.org/docs/5.1/eloquent-relationships
扩展阅读:深入理解 Laravel Eloquent(三)——模型间关系(关联)

构建前台 UI

让我们修改前台的视图文件,想办法把评论功能加进去。

创建前台的 ArticleController 类

运行命令:

php artisan make:controller ArticleController

增加路由:

Route::get('article/{id}', 'ArticleController@show');

此处的 {id} 指代任意字符串,在我们的规划中,此字段为文章 ID,为数字,但是本行路由却会尝试匹配所有请求,所以当你遇到了奇怪的路由调用的方法跟你想象的不一样时,记得检查路由顺序。路由匹配方式为前置匹配:任何一条路由规则匹配成功,会立刻返回结果,后面的路由便没有了响应的机会。

给 ArticleController 增加 show 函数:

public function show($id)
{
return view('article/show')->withArticle(Article::with('hasManyComments')->find($id));
}

别忘了在顶部引入 Model 类,否则会报类找不到的错误:

....
use App\Article;
class ArticleController extends Controller
{
....

创建前台文章展示视图

新建 learnlaravel5/resources/views/article/show.blade.php 文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Learn Laravel 5</title>
    <link href="//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
    <script src="//cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<div id="content" style="padding: 50px;">
    <h4>
        <a href="/"><< 返回首页</a>
    </h4>
    <h1 style="text-align: center; margin-top: 50px;">{{ $article->title }}</h1>
    <hr>
    <div id="date" style="text-align: right;">
        {{ $article->updated_at }}
    </div>
    <div id="content" style="margin: 20px;">
        <p>
            {{ $article->body }}
        </p>
    </div>
    <div id="comments" style="margin-top: 50px;">
        @if (count($errors) > 0)
            <div class="alert alert-danger">
                <strong>操作失败</strong> 输入不符合要求<br><br>
                {!! implode('<br>', $errors->all()) !!}
            </div>
        @endif
        <div id="new">
            <form action="{{ url('comment') }}" method="POST">
                {!! csrf_field() !!}
                <input type="hidden" name="article_id" value="{{ $article->id }}">
                <div class="form-group">
                    <label>Nickname</label>
                    <input type="text" name="nickname" class="form-control" style="width: 300px;" required="required">
                </div>
                <div class="form-group">
                    <label>Email address</label>
                    <input type="email" name="email" class="form-control" style="width: 300px;">
                </div>
                <div class="form-group">
                    <label>Home page</label>
                    <input type="text" name="website" class="form-control" style="width: 300px;">
                </div>
                <div class="form-group">
                    <label>Content</label>
                    <textarea name="content" id="newFormContent" class="form-control" rows="10" required="required"></textarea>
                </div>
                <button type="submit" class="btn btn-lg btn-success col-lg-12">Submit</button>
            </form>
        </div>
        <script>
            function reply(a) {
                var nickname = a.parentNode.parentNode.firstChild.nextSibling.getAttribute('data');
                var textArea = document.getElementById('newFormContent');
                textArea.innerHTML = '@'+nickname+' ';
            }
        </script>
        <div class="conmments" style="margin-top: 100px;">
            @foreach ($article->hasManyComments as $comment)
                <div class="one" style="border-top: solid 20px #efefef; padding: 5px 20px;">
                    <div class="nickname" data="{{ $comment->nickname }}">
                        @if ($comment->website)
                            <a href="{{ $comment->website }}">
                                <h3>{{ $comment->nickname }}</h3>
                            </a>
                        @else
                            <h3>{{ $comment->nickname }}</h3>
                        @endif
                        <h6>{{ $comment->created_at }}</h6>
                    </div>
                    <div class="content">
                        <p style="padding: 20px;">
                            {{ $comment->content }}
                        </p>
                    </div>
                    <div class="reply" style="text-align: right; padding: 5px;">
                        <a href="#new" onclick="reply(this);">回复</a>
                    </div>
                </div>
            @endforeach
        </div>
    </div>
</div>
</body>
</html>

 

构建评论存储功能

我们需要创建一个 CommentsController 控制器,并增加一条“存储评论”的路由。运行命令:

php artisan make:controller CommentController

控制器创建成功,接下来我们增加一条路由:

Route::post('comment', 'CommentController@store');

给这个类增加 store 函数:

public function store(Request $request)
{
if (Comment::create($request->all())) {
return redirect()->back();
} else {
return redirect()->back()->withInput()->withErrors('评论发表失败!');
}
}

此处 Comment 类请自己引入。

批量赋值

我们采用批量赋值方法来减少存储评论的代码,批量赋值中文文档

给 Comment 类增加 $fillable 成员变量:

protected $fillable = ['nickname', 'email', 'website', 'content', 'article_id'];

检查成果

前台文章展示页:

https://camo.githubusercontent.com/aa04e68f955c5e135cc886f80ec600f19d18a2a8/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333835343330393235362e6a7067

提交几条评论之后:

https://camo.githubusercontent.com/67cd24c3cdd674f8320c27f213f28bb3be077914/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333835353138303639392e6a7067

恭喜你,前台评论功能构建完成!

【大作业】构建后台评论管理功能

评论跟 Article 一样,是一种可以管理的资源列表。2015 版教程的最后,我风风火火地罗列了一堆又一堆的代码,其实对还没入门的人几乎没用。在此,我将这个功能作为大作业布置给大家。大作业嘛,当然是没有标准答案的,但有效果图:

https://camo.githubusercontent.com/a0d16e8d5ae651ce0034b14134995c45212155bb/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031362d30362d30332d31343634393636383832333234322e6a7067

https://camo.githubusercontent.com/2f0d0fb79507fc2afa43af6fcea8ae4f7ae201a5/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031362d30362d30332d31343634393636383934343330342e6a7067

在做这个大作业的过程中,你将会反复地回头去看前面的教程,反复地阅读中文文档,会仔细阅读我的代码,等你完成大作业的时候,Laravel 就真正入门啦~~

 

提示:摘自网络,如有侵权请联系博主删除。

Laravel 系列入门教程(四)【最适合中国人的 Laravel 教程】

本篇文章中,我将跟大家一起实现 Article 的新增、编辑和删除功能,仔细解读每一段代码,相信本篇文章看完,你就能够 get Laravel 使用之道。

RESTful 资源控制器

资源控制器是 Laravel 内部的一种功能强大的约定,它约定了一系列对某一种资源进行“增删改查”操作的路由配置,让我们不再需要对每一项需要管理的资源都写 N 行重复形式的路由。中文文档见:https://d.laravel-china.org/docs/5.5/controllers#resource-controllers

我们只需要写一行简单的路由:

Route::resource('photo', 'PhotoController');

就可以得到下面 7 条路由配置:

https://camo.githubusercontent.com/a480cb453e6b9e766be893d5ddfd883577022be6/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333732343432323536382e6a70673f743d32

左边是 HTTP 方法,中间是 URL 路径,右边是 控制器中对应的函数,只要某个请求符合这七行中某一行的要求,那么这条请求就会触发第三列的 function。这是 Laravel 对于 RESTful 的规范,它不仅仅帮我们省去了几行路由配置代码,更是如何合理规划 URL 的指路明灯,相信你会从中学到很多。

下面我们正式开始一项一项地实现 Article 的新增、编辑、删除功能:

开始行动

配置资源路由

将当前路由配置中的 Route::get(‘article’, ‘ArticleController@index’); 改成 Route::resource(‘articles’, ‘ArticleController’);,哦了。注意,article 单数变成了复数。

修改之前写好的视图文件

由于从单数变成了复数,后台首页及文章列表页的视图文件里的链接也需要修改。

  1. 修改 learnlaravel5/resources/views/admin/home.blade.php 中的 {{ url(‘admin/article’) }} 为 {{ url(‘admin/articles’) }}。
  2. 修改 learnlaravel5/resources/views/admin/article/index.blade.php 中的 {{ url(‘admin/article/create’) }} 为 {{ url(‘admin/articles/create’) }};修改 {{ url(‘admin/article/’.$article->id.’/edit’) }} 为 {{ url(‘admin/articles/’.$article->id.’/edit’) }};修改 {{ url(‘admin/article/’.$article->id) }} 为 {{ url(‘admin/articles/’.$article->id) }}。

新增 Article

新增一篇文章需要两个动作:第一步,获取“新增Article”的页面;第二步,提交数据到后端,插入一篇文章到数据库。我们使用下图中红框内的两条路由规则来实现这两步操作:

https://camo.githubusercontent.com/d409b30ba6f4ae12e86955e034fcec1bc5272eea/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333732363533323231332e6a70673f743d31

获取“新增Article”的页面

第一个红框里告诉我们应该使用 /admin/articles/create 对应“新增Article”的页面,浏览器使用 GET 方法从服务器获取,对应的是 ArticleController 中的 create() 方法,下面我们手动新建这个方法:

public function create()
{
return view('admin/article/create');
}

新增视图文件 learnlaravel5/resources/views/admin/article/create.blade.php:

@extends('layouts.app')
@section('content')
    <div class="container">
        <div class="row">
            <div class="col-md-10 col-md-offset-1">
                <div class="panel panel-default">
                    <div class="panel-heading">新增一篇文章</div>
                    <div class="panel-body">
                        @if (count($errors) > 0)
                            <div class="alert alert-danger">
                                <strong>新增失败</strong> 输入不符合要求<br><br>
                                {!! implode('<br>', $errors->all()) !!}
                            </div>
                        @endif
                        <form action="{{ url('admin/articles') }}" method="POST">
                            {!! csrf_field() !!}
                            <input type="text" name="title" class="form-control" required="required" placeholder="请输入标题">
                            <br>
                            <textarea name="body" rows="10" class="form-control" required="required" placeholder="请输入内容"></textarea>
                            <br>
                            <button class="btn btn-lg btn-info">新增文章</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

 

点击文章管理页面最上面的“新增”按钮,你将得到以下页面:

https://camo.githubusercontent.com/9e43f26a2de1bacbf31fae3fde0238d818ebf846/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333733333039373439382e6a7067

视图调用

上文中我使用 return view(‘admin/article/create’); 返回了视图文件。

view() 方法是 Laravel 中一个全局的方法,用于调用视图文件,他接受一个字符串参数,并会按照这个参数去调取对应的路由,这很容易理解。实际上 ‘admin/article/create’ 跟 ‘admin.article.create’ 是等价的,而且看起来后者更加优雅,不过我个人更推荐前者。代码优雅是好事儿,不过本质上代码是写给人看的,一切提高代码理解成本的行为都是不可取的。

提交数据到后端

“新增Article”的页面已经展示出来,下一步就是提交数据到后端了,理解提交数据,要从 HTML 表单开始。

表单

视图文件中有一个表单:

<form action="{{ url('admin/articles') }}" method="POST">
    {!! csrf_field() !!}
    <input type="text" name="title" class="form-control" required="required" placeholder="请输入标题">
    <br>
    <textarea name="body" rows="10" class="form-control" required="required" placeholder="请输入内容"></textarea>
    <br>
    <button class="btn btn-lg btn-info">新增文章</button>
</form>

这是一个非常普通的 HTML form(表单),只有两点需要我们费点心思去理解。

第一,表单的 action。form 是 HTML 规范,在点击了表单中的提交按钮后,浏览器会使用 method 属性的值(GET、POST等)将某些数据组装好发送给 action 的值(URL),这里我们动态生成了一个 URL 作为 action,并且指定了表单提交需要使用 POST 方法。

第二,csrf_field。这是 Laravel 中内置的应对 CSRF 攻击的防范措施,任何 POST PUT PATCH 请求都会被检测是否提交了 CSRF 字段。对应的代码为 learnlaravel5/app/Http/Kernel.php 里的 $middlewareGroups 属性里的 \App\Http\Middleware\VerifyCsrfToken::class 值。

{!! csrf_field() !!} 实际上会生成一个隐藏的 input:<input type=”hidden” name=”_token” value=”GYZ8OHDAbZICMcEvcTiS82qlZs2XrELklpEl159S”>

这一行也可以这么写:

<input type="hidden" name="_token" value="{{ csrf_token() }}">

如果你的系统有很多的 Ajax,而你又不想降低安全性,这里的 csrf_token() 函数将会给你巨大的帮助。

后端接收数据

我们在页面中随便填入一些数据,点击提交按钮,这条请求会被分配到那里呢?

https://camo.githubusercontent.com/d409b30ba6f4ae12e86955e034fcec1bc5272eea/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333732363533323231332e6a70673f743d31

第二个红框告诉我们,应该向 admin/articles 以 POST 方法提交表单,其对应的是 store() 方法。现在我们新建 store 方法:

public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique:articles|max:255',
'body' => 'required',
]);
$article = new Article;
$article->title = $request->get('title');
$article->body = $request->get('body');
$article->user_id = $request->user()->id;
if ($article->save()) {
return redirect('admin/articles');
} else {
return redirect()->back()->withInput()->withErrors('保存失败!');
}
}

 

检验成果

填入数据:

https://camo.githubusercontent.com/3863732f77d6feb98712346ee551481e7682069c/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333734313339313135382e6a70673f743d31

点击按钮,页面跳转到“文章管理”页,将此页面拉到最底部:

https://camo.githubusercontent.com/c104696e4e90a28f18b7ba892f42e4b183bb55c7/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333734333037353036392e6a7067

恭喜你,文章新增功能完成!

详细注释

下面我已注释的形式细细解析每一段代码的作用:

public function store(Request $request) // Laravel 的依赖注入系统会自动初始化我们需要的 Request 类
{
    // 数据验证
    $this->validate($request, [
        'title' => 'required|unique:articles|max:255', // 必填、在 articles 表中唯一、最大长度 255
        'body' => 'required', // 必填
    ]);

    // 通过 Article Model 插入一条数据进 articles 表
    $article = new Article; // 初始化 Article 对象
    $article->title = $request->get('title'); // 将 POST 提交过了的 title 字段的值赋给 article 的 title 属性
    $article->body = $request->get('body'); // 同上
    $article->user_id = $request->user()->id; // 获取当前 Auth 系统中注册的用户,并将其 id 赋给 article 的 user_id 属性

    // 将数据保存到数据库,通过判断保存结果,控制页面进行不同跳转
    if ($article->save()) {
        return redirect('admin/articles'); // 保存成功,跳转到 文章管理 页
    } else {
        // 保存失败,跳回来路页面,保留用户的输入,并给出提示
        return redirect()->back()->withInput()->withErrors('保存失败!');
    }
}

 

编辑 Article

这两行路由配置可以满足我们的需求:

https://camo.githubusercontent.com/32cc202ec3f070e7ec462d9266f9470bd37a9f77/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333830363539313030362e6a70673f743d31

上面一行:展示“编辑某一篇文章”的表单;下面一行:上传数据并到数据库更新这篇文章。

这个就当做第二个小作业留给你们,尝试自己去构建吧

删除 Article

删除某个资源跟新增、编辑相比最大的不同就是运行方式的不同:删除按钮看起来是一个独立的按钮,其实它是一个完整的表单,只不过只有这一个按钮暴露在页面上:

<form action="{{ url('admin/articles/'.$article->id) }}" method="POST" style="display: inline;">
    {{ method_field('DELETE') }}
    {{ csrf_field() }}
    <button type="submit" class="btn btn-danger">删除</button>
</form>

大家可能注意到了这句代码 {{ method_field(‘DELETE’) }},这是什么意思呢?这是 Laravel 特有的请求处理系统的特殊约定。虽然 DELETE 方法在 RFC2616 中是可以携带 body 的(甚至 GET 方法都是可以携带的),但是由于历史的原因,不少 web server 软件都将 DELETE 方法和 GET 方法视作不可携带 body 的方法,有些 web server 软件会丢弃 body,有些干脆直接认为请求不合法拒绝接收。所以在这里,Laravel 的请求处理系统要求所有非 GET 和 POST 的请求全部通过 POST 请求来执行,再将真正的方法使用 _method 表单字段携带给后端。上面小作业中的小坑便是这个,PUT/PATCH 请求也要通过 POST 来执行。

在控制器中增加删除文章对应的是 destroy 方法:

public function destroy($id)
{
    Article::find($id)->delete();
    return redirect()->back()->withInput()->withErrors('删除成功!');
}

点击删除按钮,检验效果:

https://camo.githubusercontent.com/744c63de0428c60eafdb41488b4201a59a7853b2/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31312d31353130333832323639363336332e6a7067

恭喜你,文章新增、编辑、删除功能构建成功!

 

提示:摘自网络,如有侵权请联系博主删除。

 

Laravel 系列入门教程(三)【最适合中国人的 Laravel 教程】

在本篇文章中,我们将尝试构建一个带后台的简单博客系统。我们将会使用到 路由、MVC、Eloquent ORM 和 blade 视图系统。

简单博客系统规划

我们在教程一中已经新建了一个继承自 Eloquent Model 类的 Article 类,使用 migration 建立了数据表并使用 seeder 填入了测试数据。我们的博客系统暂时将只管理这一种资源:后台需要使用账号密码登录,进入后台之后,可以新增、修改、删除文章;前台显示文章列表,并在点击标题之后显示出文章全文。

下面我们正式开始。

搭建前台

前台的搭建是最简单的,我先带大家找找感觉。

修改路由

删掉

Route::get('/', function () {
return date("Y-m-d H:i:s");
});

将Route::get(‘/home’, ‘HomeController@index’)->name(‘home’); 改为 Route::get(‘/’, ‘HomeController@index’)->name(‘home’);,现在我们系统的首页就落到了 App\Http\Controllers\HomeController 类的 index 方法上了。

查看 HomeController 的 index 函数

将 learnlaravel5/app/Http/Controllers/HomeController.php 的 index 函数我们之前加的 Exception 那行代码删除,就只剩一行代码了:return view(‘home’);,这个很好理解,返回名叫 home 的视图给用户。这个视图文件在哪里呢?在 learnlaravel5/resources/views/home.blade.php,blade 是 Laravel 视图引擎的名字,会对视图文件进行加工。

blade 浅析

blade 引擎会对视图文件进行预处理,帮我们简化一些重复性很高的 echo、foreach 等 PHP 代码。blade 还提供了一个灵活强大的视图组织系统。打开 home.blade.php:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Dashboard</div>

                <div class="panel-body">
                    @if (session('status'))
                        <div class="alert alert-success">
                            {{ session('status') }}
                        </div>
                    @endif

                    You are logged in!
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

@extends(‘layouts.app’)

这表示此视图的基视图是 learnlaravel5/resources/views/layouts/app.blade.php 。这个函数还隐含了一个小知识:在使用名称查找视图的时候,可以使用 . 来代替 / 或 \。

@Section(‘content’) … @endsection

这两个标识符之间的代码,会被放到基视图的 @yield(‘content’) 中进行输出。

访问首页

首先删除 learnlaravel5/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php 中 dispatch 函数里我们加的的 var_dump 代码,否则会出现奇怪的页面。
访问 http://fuck.io:1024 ,不出意外的话,你会看到这个页面:

https://camo.githubusercontent.com/79ce60a580a5a0da8d1c759b2775811f91cdceaa/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130323334383632313836332e6a7067

为什么需要登录呢?怎么去掉这个强制登录呢?删掉 HomeController 中的构造函数即可:

public function __construct()
{
    $this->middleware('auth');
}

这个函数会在控制器类生成对象后第一时间自动载入一个名为 auth 的中间件,正是这一步导致了首页需要登录。删除构造函数之后,重新访问 http://fuck.io:1024 ,页面应该就会直接出来了。这里要注意两点:① 一定要重新访问,不要刷新,因为此时页面的 url 其实是 http://fuck.io:1024/login ② 这个页面跟之前的欢迎页虽然看起来一毛一样,但其实文字是不同的,注意仔细观察哦。

向视图文件输出数据

既然 Controller – View 的架构已经运行,下一步就是引入 Model 了。Laravel 中向视图传数据非常简单:

public function index()
{
    return view('home')->withArticles(\App\Article::all());
}

2016 版教程里很多人看到这段代码都十分不解,这里解释一下:

  1. \App\Article::all() 是采用绝对命名空间方式对 Article 类的调用。
  2. withArticles 是我定义的方法,Laravel 并不提供,这也是 Laravel 优雅的一个表现:Laravel View 采用 __call 来 handle 对未定义 function 的调用,其作用很简单:给视图系统注入一个名为 $articles 的变量,这段代码等价于 ->with(‘articles’, \App\Article::all())。
  3. 展开讲一下,->withFooBar(100) 等价于 ->with(‘foo_bar’, 100),即驼峰变量会被完全转换为蛇形变量。

修改视图文件

修改视图文件 learnlaravel5/resources/views/home.blade.php 的代码为:

@extends('layouts.app')
@section('content')
    <div id="title" style="text-align: center;">
        <h1>Learn Laravel 5</h1>
        <div style="padding: 5px; font-size: 16px;">Learn Laravel 5</div>
    </div>
    <hr>
    <div id="content">
        <ul>
            @foreach ($articles as $article)
            <li style="margin: 50px 0;">
                <div class="title">
                    <a href="{{ url('article/'.$article->id) }}">
                        <h4>{{ $article->title }}</h4>
                    </a>
                </div>
                <div class="body">
                    <p>{{ $article->body }}</p>
                </div>
            </li>
            @endforeach
        </ul>
    </div>
@endsection

刷新,得到:

https://camo.githubusercontent.com/11ac6861a05b8f7cc0d8d3443eb8694138afee4e/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130333036303335383031362e6a7067

如果看到以上页面,恭喜你,Laravel 初体验成功!

调整视图

前台页面是不应该有顶部的菜单栏的,特别是还有注册、登录之类的按钮。接下来我们修改视图内容为:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Learn Laravel 5</title>

    <link href="//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
    <script src="//cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>

    <div id="title" style="text-align: center;">
        <h1>Learn Laravel 5</h1>
        <div style="padding: 5px; font-size: 16px;">Learn Laravel 5</div>
    </div>
    <hr>
    <div id="content">
        <ul>
            @foreach ($articles as $article)
            <li style="margin: 50px 0;">
                <div class="title">
                    <a href="{{ url('article/'.$article->id) }}">
                        <h4>{{ $article->title }}</h4>
                    </a>
                </div>
                <div class="body">
                    <p>{{ $article->body }}</p>
                </div>
            </li>
            @endforeach
        </ul>
    </div>

</body>
</html>

 

此视图文件变成了一个独立视图,不再有基视图,并且将 jQuery 和 BootStrap 替换为了国内的 CDN,更快更稳定了。

同理我们修改 learnlaravel5/resources/views/layouts/app.blade.php:

① 删除 <script src=”{{ asset(‘js/app.js’) }}”></script>
② 替换 <link href=”{{ asset(‘css/app.css’) }}” rel=”stylesheet”> 为

<link href="//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script src="//cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

接下来我们来着手搭建后台。

搭建后台

生成控制器

我们使用 Artisan 工具来生成控制器文件及代码:

php artisan make:controller Admin/HomeController

成功之后,我们就可以看到 artisan 帮我们建立的文件夹及控制器文件了:

https://camo.githubusercontent.com/6f36996b4c9258c9b2318abd5f0232ec5f295875/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031362d30362d30332d31343633373636303031343230332e6a7067

增加路由

我们要使用路由组来将后台页面置于“需要登录才能访问”的中间件下,以保证安全。在 web.php 里增加下面三行:

Route::group(['middleware' => 'auth', 'namespace' => 'Admin', 'prefix' => 'admin'], function() {
    Route::get('/', 'HomeController@index');
});

上一篇文章中我们已经接触到了路由组,这是 Laravel 的另一个伟大创造。路由组可以给组内路由一次性增加 命名空间、uri 前缀、域名限定、中间件 等属性,并且可以多级嵌套,异常强大。路由组中文文档在此:https://d.laravel-china.org/docs/5.5/routing#route-groups

上面的三行代码的功能简单概括就是:访问这个页面必须先登录,若已经登录,则将 http://fuck.io:1024/admin 指向 App\Http\Controllers\Admin\HomeController 的 index 方法。其中需要登录由 middleware 定义,/admin 由 prefix 定义,Admin 由 namespace 定义,HomeController 是实际的类名。

构建后台首页

新建 index 方法

在新生成的 learnlaravel5/app/Http/Controllers/Admin/HomeController.php 文件中增加一个 function:

public function index()
{
    return view('admin/home');
}

新建后台首页视图文件

在 learnlaravel5/resources/views/ 目录下新建一个名为 admin 的文件夹,在 admin 内新建一个名为 home.blade.php 的文件,填入代码:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">Learn Laravel 5 后台</div>

                <div class="panel-body">

                    <a href="{{ url('admin/article') }}" class="btn btn-lg btn-success col-xs-12">管理文章</a>

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

修改 Auth 系统登陆成功之后的跳转路径

修改 learnlaravel5/app/Http/Controllers/Auth/LoginController.php 中相应的代码为:

protected $redirectTo = '/admin';

尝试登录

访问 http://fuck.io:1024/admin ,它会跳转到登陆界面,输入邮箱和密码之后,你应该会看到如下页面:

https://camo.githubusercontent.com/d55bcb7ccf344849cd5eb6945c8e4566fd7dc638/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130333039303236373233352e6a70673f743d33

恭喜你,后台首页搭建完成!下面我们开始构建 Article 的后台管理功能。

构建 Article 后台管理功能

让我们先尝试点一下 “管理文章”按钮,不出意外你将得到一个报错:

https://camo.githubusercontent.com/2061e06364f51f062da5767c5ff429d446298692/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130333039313137323634352e6a7067

这是 Laravel 5.5 刚刚引入的新策略:404 错误不再报告详细信息,而是展示一个友好的 404 页面。

添加路由

404 错误是访问了系统没有监听的路由导致的。下面我们要添加针对 http://fuck.io:1024/admin/article 的路由:

Route::group(['middleware' => 'auth', 'namespace' => 'Admin', 'prefix' => 'admin'], function() {
    Route::get('/', 'HomeController@index');
    Route::get('article', 'ArticleController@index');
});

刷新,出现详细报错信息了:

https://camo.githubusercontent.com/06d5d53629a66cf49cd4013617e8f5ee6140356e/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130333135333335353032312e6a7067

进步之道

很多新手看到这个报错直接就慌了:什么鬼?全是英文看不懂呀。然后在文章下面把完整的错误栈全部粘贴出来。老实说我第一次见到 Laravel 报这个错也是完全没耐心去读,不过我还是复制了最明显的那句话“Class App\Http\Controllers\Admin\ArticleController does not exist”去 Google 了一下,从此我就再也没搜索过它了。

如果你遇到了奇怪的报错,不要慌,稳住,Google 一下,我们能赢。

新建控制器

上图中的报错是控制器不存在。我们使用 Artisan 来新建控制器:

php artisan make:controller Admin/ArticleController

刷新,错误又变了:

https://camo.githubusercontent.com/c140909ca6e11a092d043986d43e643639248a88/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130333135343939313933332e6a70673f743d35

index 方法不存在。让我们新增 index 方法:

public function index()
{
return view('admin/article/index')->withArticles(Article::all());
}

新建视图

上面我们已经新建过视图,现在应该已经轻车熟路了。在 learnlaravel5/resources/views/admin 下新建 article 文件夹,在文件夹内新建一个 index.blade.php 文件,内容如下:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <div class="panel panel-default">
                <div class="panel-heading">文章管理</div>
                <div class="panel-body">
                    @if (count($errors) > 0)
                        <div class="alert alert-danger">
                            {!! implode('<br>', $errors->all()) !!}
                        </div>
                    @endif

                    <a href="{{ url('admin/article/create') }}" class="btn btn-lg btn-primary">新增</a>

                    @foreach ($articles as $article)
                        <hr>
                        <div class="article">
                            <h4>{{ $article->title }}</h4>
                            <div class="content">
                                <p>
                                    {{ $article->body }}
                                </p>
                            </div>
                        </div>
                        <a href="{{ url('admin/article/'.$article->id.'/edit') }}" class="btn btn-success">编辑</a>
                        <form action="{{ url('admin/article/'.$article->id) }}" method="POST" style="display: inline;">
                            {{ method_field('DELETE') }}
                            {{ csrf_field() }}
                            <button type="submit" class="btn btn-danger">删除</button>
                        </form>
                    @endforeach

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

刷新,错误又变了:

https://camo.githubusercontent.com/2ecbb6331dabc1a160e16d0ed84d35a0a720eaab/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130333135363730353035302e6a70673f743d30

Article 类不存在?原因很简单:Article 类和当前控制器类不在一个命名空间路径下,不能直接调用。解决办法就是主动导入 \App\Article 类:

<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Article;
class ArticleController extends Controller
{
....

如果你还不熟悉命名空间,请阅读《PHP 命名空间 解惑》

检查成果

再次刷新,你应该能看到如下画面:

https://camo.githubusercontent.com/29b700f01f397271b268bb72922783359ba1d5fc/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d31302d31353130333135383433363434312e6a7067

如果你没到这个画面也不用担心,根据错误提示去 Google 吧,一定能解决的。

新增、编辑、删除功能怎么办?

这三个功能我将在下一篇教程与大家分享,这是 2015 版 Laravel 教程做的不够好的地方,其实这里才是最应该掰开揉碎仔细讲解的地方。

 

提示:摘自网络,如有侵权请联系博主删除。

Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】

本篇文章中,我将跟大家一起体验 Laravel 框架最重要的部分——路由系统。

如果你读过 2015 版的教程,你会发现那篇文章里大书特书的 Auth 系统构建已经被 Laravel 捎带手给解决了。在更早的 2014(Laravel 4)版教程中,实际上我是通过让大家自己手动构建高难度的 Auth 系统来提高短期学习曲线的斜率,以便大家能更快地感受到 Laravel 运行的原理。但是很遗憾,现在的 Auth 系统实在是太强大了,执行几句命令就激活了这个功能,新手其实还是云里雾里。为了弥补这个缺憾,我决定赤膊上阵,手刃路由系统,直接给大家展示 Laravel 是如何组织 MVC 架构而控制网站运行的。

初识路由

路由系统是所有 PHP 框架的核心,路由承载的是 URL 到代码片段的映射,不同的框架所附带的路由系统是这个框架本质最真实的写照,一丝不挂,一览无余。Laravel 路由中文文档:http://laravel-china.org/docs/5.5/routing

Laravel 5.3 之后就把路由放到了 learnlaravel5/routes 文件夹中,一共有四个文件。

我们先看一下web.php中仅存的几行代码:

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

中间的一行代码 Auth::routes(); 就是 Auth 系统自动注入的路由配置,我们不用深究,我们的注意力主要集中头三行和最后一行代码上。

命名空间

我一直认为 Laravel 5 除了性能大幅提升之外相对于 4 最大的进步就在于新的命名空间规划:更清晰,更合理,更有利于新手。

Laravel 4 失败的简洁

Laravel 4 时代,大量的代码都运行在根命名空间下,路由、Controller、Model 等等。看起来这么做可以少写几行枯燥的 use xxxx;,实则是对于命名空间的误使用,而且对于新手学习命名空间是有毒的。

绝对类名

Laravel 5 全面引入了 psr-4 命名空间标准:命名空间和实际文件所在的文件夹层级一致,文件夹首字母大写,并自动成为此文件的约定命名空间。举个小栗子:learnlaravel5/app/Http/Controllers/HomeController.php 的绝对类名为:\App\Http\Controllers\HomeController,learnlaravel5/app/User.php 的绝对类名为:\App\User。(实际上 psr-4 是自动加载标准,用在这里故称其为命名空间标准。)

“绝对类名”是我自创的:在启用了命名空间的系统中,子命名空间下的类有一个全局都可以直接访问的名称,这个名称就是该类的命名空间全称。虽然命名空间在“实用主义”的 PHP 语言里看起来十分古怪,不过他也还是 PHP 嘛,依然遵循 PHP 的运行原理和哲学。同理,Laravel 无论多么强大,他都是 PHP 代码写成的,所以当你苦于 Laravel 没有提供某个你需要的功能时,不要惊慌不要着急,just write your PHP code。

psr-4 的官方英文文档在这里:http://www.php-fig.org/psr/psr-4/

好用的资料

命名空间其实没什么特别难的地方,我曾经写过一篇文章专门扒光命名空间的秘密:《PHP 命名空间 解惑

基础路由解析

闭包路由

路由文件中前三行即为闭包路由:

Route::get('/', function () {
return view('welcome');
});

闭包路由使用闭包作为此条请求的响应代码,方便灵活,很多简单操作直接在闭包里解决即可。例如“输出服务器当前时间”:

Route::get('now', function () {
return date("Y-m-d H:i:s");
});

如果你想得到北京时间,请在 learnlaravel5/config/app.php 第 68 行左右把 timezone 设置为上海:

‘timezone’ => ‘Asia/Shanghai’,

这时候访问 http://fuck.io:1024/now 可以得到如下结果:

https://camo.githubusercontent.com/8f3f7c3a5594a30acc4cc0e63607edc7eb8ce240/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d30382d31353130313330333332313535352e6a7067

控制器@方法 路由

闭包路由虽然灵活强大,不过大多数场景下我们还是需要回归到 MVC 架构的:

Route::get('/home', 'HomeController@index')->name('home');

这行路由代码的意思想必大家都能猜到一二了:当以 GET 方法访问 http://fuck.io:1024/home 的时候,调用 HomeController 控制器中的 index 方法(函数)。同理,你可以使用 Route::post(‘/home’, ‘HomeController@indexPost’); 响应 POST 方法的请求。最后的->name()不是必须的,感兴趣可以自己了解。

控制器@方法 调用原理浅析

Laravel 的路由跟所有 PHP 框架的路由一样,都是用的最简单直接的 PHP 方式来调用控制器中的方法的:使用字符串初始化类得到对象,调用对象的指定方法,返回结果。下面我简单罗列几步对 Laravel 路由调用过程的探测,感兴趣的话可以自己研究。

learnlaravel5/app/Providers/RouteServiceProvider.php

全局搜索 routes.php,我们找到了这个文件。此文件最后的 mapWebRoutes 方法,给所有的路由统一加进了一个路由组,定义了一个命名空间和一个中间件:

protected function mapWebRoutes()
{
    Route::middleware('web')
         ->namespace($this->namespace)
         ->group(base_path('routes/web.php'));
}

顺着这个函数往上看,你会发现命名空间定义的地方:

protected $namespace = 'App\Http\Controllers';

之后命名空间、类、方法是如何传递的呢?

learnlaravel5/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php

经过简单的追踪,我们找到了这个文件。让我们在 dispatch 方法中增加一行 var_dump($controller);,刷新http://fuck.io:1024/home就可以看到页面上如下的输出:

 

开头的App\Http\Controllers\HomeController就是我们要调用的控制器类的“绝对类名”,注意这里是不带\根命名空间符号的。

最后一步

Laravel 使用了完整的面向对象程序架构,对控制器的调用进行了超多层封装,所以最简单地探测方式其实是手动抛出错误,这样就可以看到完整的调用栈:

在 HomeController 的 index 方法里的 return 之前增加一行 throw new \Exception(“我故意的”, 1);,刷新页面,你将看到以下画面:

https://camo.githubusercontent.com/53da86b917f9010f6d6bd2781d40f06a8b82a856/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d31312d30382d31353130313331303034383433362e6a70673f743d32

我们可以看到,是 learnlaravel5/vendor/laravel/framework/src/Illuminate/Routing/Controller.php 第 54 行最终驱动起了 HomeController:

public function callAction($method, $parameters)
{
    return call_user_func_array([$this, $method], $parameters);
}

具体的细节不再详解,大家如果感兴趣的话,把这些方法一个一个地都看一遍吧,相信对于你理解 Laravel 运行原理很有帮助。其实 PHP 跟字符串结合的紧密程度已经紧逼 js 和 JSON 了。结尾分享一个小彩蛋:这个laravel路由怎么写?

 

提示:摘自网络,如有侵权请联系博主删除。

Laravel 系列入门教程(一)【最适合中国人的 Laravel 教程】

本教程示例代码见:https://github.com/johnlui/Learn-Laravel-5

在任何地方卡住,最快的办法就是去看示例代码。

 

热烈庆祝 Laravel 5.5 LTS 发布! 实际上 Laravel 上一个 LTS 选择 5.1 是非常不明智的,因为 5.2 增加了许许多多优秀的特性。现在好了,大家都用最新的长期支持版本 5.5 吧!

Laravel 5.5 中文文档:https://d.laravel-china.org/docs/5.5

默认条件

你应该懂得 PHP 网站运行的基础知识,并且拥有一个完善的开发环境。跟随本教程走完一遍,你将会得到一个基础的包含登录、后台编辑、前台评论的简单 blog 系统。

Tips

  1. 环境要求:PHP 7.0+,MySQL 5.1+
  2. 本教程不推荐完全不懂 PHP 与 MVC 编程的人学习,Laravel 的学习曲线不仅仅是陡峭,而且耗时很长,请先做好心理准备。
  3. 这不是 “一步一步跟我做” 教程。本教程需要你付出一定的心智去解决一些或大或小的隐藏任务,以达到真正理解 Laravel 运行逻辑的目的。
  4. 我使用 Safari 截图是为了好看,你们在开发时记得选择 Chrome 哦~

开始学习

1. 安装

许多人被拦在了学习 Laravel 的第一步:安装。并不是因为安装有多复杂,而是因为【众所周知的原因】。在此我推荐一个 composer 全量中国镜像:http://pkg.phpcomposer.com 。启用 Composer 镜像服务作为本教程的第一项小作业请自行完成哦。

镜像配置完成后,在终端(Terminal 或 CMD)里切换到你想要放置该网站的目录下(如 C:\wwwroot、/Library/WebServer/Documents/、/var/www/html、/etc/nginx/html 等),运行命令:

composer create-project laravel/laravel learnlaravel5 ^5.5

然后,稍等片刻,当前目录下就会出现一个叫 learnlaravel5 的文件夹,安装完成啦~

2. 运行

为了尽可能地减缓学习曲线,推荐大家使用 PHP 内置 web server 驱动我们的网站。运行以下命令:

cd learnlaravel5/public
php -S 0.0.0.0:1024

这时候访问 http://127.0.0.1:1024 就是这个样子的:

我在本地 hosts 中绑定了 fuck.io 到 127.0.0.1,所以截图中我的域名是 fuck.io 而不是 127.0.0.1,其实他们是完全等价的。跟过去几年比,有一件大快人心的大好事,fonts.googleapis.com 网站已经转移到了墙内,不会再“白屏”了。

至于为什么选择 1024 端口?因为他是 *UNIX 系统动态端口的开始,是我们不需要 root 权限就可以随意监听的数值最小的端口。

另外,如果你不熟悉 PHP 运行环境搭建的话不要轻易尝试使用 Apache 或 Nginx 驱动 Laravel,特别是在开启了 SELinux 的 Linux 系统上跑这俩货。关于 Laravel 在 Linux 上部署的大坑,我可能要单写一篇长文分享给宝宝们。(说了一年了也没见写呀)

3. 体验牛逼闪闪的 Auth 系统

Laravel 利用 PHP5.4 的新特性 trait 内置了非常完善好用的简单用户登录注册功能,适合一些不需要复杂用户权限管理的系统,例如公司内部用的简单管理系统。

激活这个功能非常容易,运行以下命令:

php artisan make:auth

访问 http://fuck.io:1024/login,看到以下页面:

https://camo.githubusercontent.com/e9430971b93d0b952b972c617c6aa01c5a3ba15f/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d30392d30362d31353034363031363333383633382e6a70673f743d31

4. 连接数据库

接下来我们要连接数据库了,请自行准备好 MySQL 服务哦。

a. 修改配置

不出意外的话,learnlaravel5 目录下已经有了一个 .env 文件,如果没有,可以复制一份 .env.example 文件重命名成 .env,修改下面几行的值:

DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel5
DB_USERNAME=root
DB_PASSWORD=password

推荐新建一个名为 laravel5 的数据库(编码设置为 utf8mb4),并且使用 root 账户直接操作,降低学习数据库的成本。

数据库配置好之后,在登录界面填写任意邮箱和密码,点击 Login,你应该会得到以下画面:

https://camo.githubusercontent.com/1c174c5f74deb13707ca009b220979392bc57ab5/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d30392d30362d31353034363033373238383339322e6a70673f743d31

它说 users 表不存在,接下来我们将见识 Laravel 另外一个实用特性。

tip:如果你下载了我的示例代码,默认是跑不起来的,还需要生成 .env,运行 composer update 填充 vendor 文件夹等操作,如果部署在 Linux 上,用的 Apache 或 Nginx,还需要设置文件夹权限:chmod 777 -R storage bootstrap/cache

b. 进行数据库迁移(migration)

运行命令:

php artisan migrate

我们得到了如下结果:

» php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table

数据库迁移成功!赶快打开 http://fuck.io:1024/home 点击右上角的注册按钮注册一个用户试试吧~

下图是本宝宝注册了一个 username 为 1 用户:

c. migration 是啥?

打开 learnlaravel5/database/migrations/2014_10_12_000000_create_users_table.php 文件,你肯定能一眼看出它的作用:用 PHP 描述数据库构造,并且使用命令行一次性部署所有数据库结构。

5. 使用 Laravel 的“葵花宝典”:Eloquent

Eloquent 是 Laravel 的 ORM,是 Laravel 系统中最强大的地方,没有之一。当初 Laravel 作者在开发第一版的时候花了整整三分之一的时间才搞出来 Eloquent。当然,“欲练此功,必先自宫”,Eloquent 也是 Laravel 中最慢的地方,迄今无法解决。(路由、自动载入、配置分散、视图引发的性能问题都通过缓存几乎彻底解决了,Composer Autoload 巨量的性能消耗也被 PHP7 手起刀落解决了)

当然,我们还是要承袭第一版教程中对 Eloquent ORM 的描述:鹅妹子英!

如果你想深入地了解 Eloquent,可以阅读系列文章:深入理解 Laravel Eloquent(一)——基本概念及用法

a. Eloquent 是什么

Eloquent 是 Laravel 内置的 ORM 系统,我们的 Model 类将继承自 Eloquent 提供的 Model 类,然后,就天生具备了数十个异常强大的函数,从此想干啥事儿都是一行代码就搞定。

经过了三年多的大规模使用,我发现 Eloquent 另辟蹊径采用和 Java 技术完全不同的思路解决了多人开发耦合过重的问题:数据库相关操作全部用一句话解决,Model 中不写共用函数,大幅降低了 bug 几率。什么?你说性能?软件工程研究的对象是人,性能的优先级比代码格式规范都低好嘛。我时刻谨记:代码是写给人看的,只是恰好能运行。

b. 怎么用?

我们使用 Artisan 工具新建 Model 类及其附属的 Migration 和 Seeder(数据填充)类。

运行以下命令:

php artisan make:model Article

去看看你的 app 目录,下面是不是多了一个 Article.php 文件?那就是 Artisan 帮我们生成的 Model 文件:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
//
}

如此简洁有力的代码,隐藏了背后极高的难度和巨大的复杂度,让我们闭上眼睛,静静地感受 Laravel 的优雅吧 (~ ̄▽ ̄)~

下面是几个简单的例子:

找到 id 为 2 的文章打印其标题

$article = Article::find(2);
echo $article->title;

查找标题为“我是标题”的文章,并打印 id

$article = Article::where('title', '我是标题')->first();
echo $article->id;

查询出所有文章并循环打印出所有标题

$articles = Article::all(); // 此处得到的 $articles 是一个对象集合,可以在后面加上 ‘->toArray()’ 变成多维数组。

foreach ($articles as $article) {
echo $article->title;
}

查找 id 在 10~20 之间的所有文章并打印所有标题

$articles = Article::where('id', '>', 10)->where('id', '<', 20)->get();
foreach ($articles as $article) {
echo $article->title;
}

查询出所有文章并循环打印出所有标题,按照 updated_at 倒序排序

$articles = Article::where('id', '>', 10)->where('id', '<', 20)->orderBy('updated_at', 'desc')->get();
foreach ($articles as $article) {
echo $article->title;
}

6. 使用 Migration 和 Seeder

接下来我们生成对应 Article 这个 Model 的 Migration 和 Seeder。

a. 使用 artisan 生成 Migration

在 learnlaravel5 目录下运行命令:

php artisan make:migration create_articles_table

成功之后打开 learnlaravel5/database/migrations,你会发现有一个名为 2*****_create_articles_table 的文件被创建了。我们修改他的 up 函数为:

public function up(){
Schema::create('articles', function (Blueprint $table){
$table->increments('id');
$table->string('title');
$table->text('body')->nullable();
$table->integer('user_id');
$table->timestamps();
});
}

这几行代码描述的是 Article 对应的数据库中那张表的结构。Laravel Model 默认的表名是这个英文单词的复数形式,在这里,就是 articles。接下来让我们把 PHP 代码变成真实的 MySQL 中的数据表,运行命令:

php artisan migrate

执行成功后,articles 表已经出现在数据库里了:

https://camo.githubusercontent.com/3d10c6992ee1f1c3a7d685bde77e1dfe17dc75bd/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d30392d30362d31353034373031393633343333322e6a7067

上图中的软件叫 Sequel Pro,是一个开源的 MAC 下 MySQL GUI 管理工具,超好用,推荐给用 MAC 的同学。

b. 使用 artisan 生成 Seeder

Seeder 是我们接触到的一个新概念,字面意思为播种机。Seeder 解决的是我们在开发 web 应用的时候,需要手动向数据库中填入假数据的繁琐低效问题。

运行以下命令创建 Seeder 文件:

php artisan make:seeder ArticleSeeder

我们会发现 learnlaravel5/database/seeds 里多了一个文件 ArticleSeeder.php,修改此文件中的 run 函数为:

public function run()
{
    DB::table('articles')->delete();

    for ($i=0; $i < 10; $i++) {
        \App\Article::create([
            'title'   => 'Title '.$i,
            'body'    => 'Body '.$i,
            'user_id' => 1,
        ]);
    }
}

上面代码中的 \App\Article 为命名空间绝对引用。如果你对命名空间还不熟悉,可以读一下 《PHP 命名空间 解惑》,很容易理解的。

接下来我们把 ArticleSeeder 注册到系统内。修改 learnlaravel5/database/seeds/DatabaseSeeder.php 中的 run 函数为:

public function run()
{
$this->call(ArticleSeeder::class);
}

由于 database 目录没有像 app 目录那样被 composer 注册为 psr-4 自动加载,采用的是 psr-0 classmap 方式,所以我们还需要运行以下命令把 ArticleSeeder.php 加入自动加载系统,避免找不到类的错误:

composer dump-autoload

然后执行 seed:

php artisan db:seed

你应该得到如下结果:

» php artisan db:seed
Seeding: ArticleSeeder

这时候刷新一下数据库中的 articles 表,会发现已经被插入了 10 行假数据:

https://camo.githubusercontent.com/c3ed7f1f733f21bf60e31bb326d44ffc8e105057/68747470733a2f2f646e2d6c7677656e68616e2d636f6d2e71626f782e6d652f323031372d30392d30362d31353034373031393136393935352e6a70673f743d34

提示:摘自网络,如有侵权请联系博主删除。

CentOS7.4部署laravel环境

CentOS7.4部署laravel框架

1. 安装前准备

1. 安装screen
yum install screen
2. 安装wget
yum install wget
3. 更新yum
yum update
4. 安装额外资源库
yum install epel-release
5. 下载最新ius
wget https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/ius-release-1.0-15.ius.centos7.noarch.rpm
6. 安装ius
rpm -ivh ius-release-1.0-15.ius.centos7.noarch.rpm
7. 新建www用户
adduser www
8. 设置密码(可不设置)
passwd www
9. 添加到组
usermod -aG wheel www

2. 安装nginx

1. 安装
yum install nginx
2. 启动nginx
systemctl start nginx
3. 设置为开机启动
systemctl enable nginx.service

注: 项目目录默认在 /usr/share/nginx/html 下,配置文件在 /etc/nginx/ 下

3. 安装mysql

由于laravel5.4以后,数据库默认使用utf8mb64,

mysql版本太低时,在运行php artisan migrate 会报错,原因就是utf8和utf8mb4造成的

mysql5.7以后的版本没有 utf8 和 utf8mb64 的问题,

1. 安装5.7.x的mysql源
yum -y localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
2. 安装mysql
yum -y install mysql-community-server install mysql-community-devel
3. 启动mysql
systemctl start mysqld.service
4. 设置mysqld服务开机自启动
systemctl enable mysqld.service

注:使用yum安装,启动会系统会自动生成一个随机的密码.

查看mysql的随机密码

grep 'temporary password' /var/log/mysqld.log

使用查询得到的随机密码在终端登录

mysql -u root -p 更改密码(mysql文档规定,密码必须包括大小写字母数字加特殊符号>8位)

ALTER USER 'root'@'localhost' IDENTIFIED BY '你要设置的密码';

退出mysql客户端,用刚才修改的密码登录确保密码修改成功

mysql -uroot -pxxxxx

4.安装PHP7(7.1)

1. 安装php71的源
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
2. 安装php71
yum -y install php71w php71w-fpm
3. 安装常用拓展
yum -y install php71w-mbstring php71w-common php71w-gd php71w-mcrypt
yum -y install php71w-mysql php71w-xml php71w-cli php71w-devel
yum -y install php71w-pecl-memcached php71w-pecl-redis php71w-opcache
4. 重新加载php
systemctl reload php-fpm
5. 验证php是否安装成功
php -v
6. 验证对应的扩展是否安装成功
php -m
7. 启动php-fpm
systemctl start php-fpm.service
8. 设置开机自启动
systemctl enable php-fpm.service

5. 安装Composer

依次执行
php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

全局安装
sudo mv composer.phar /usr/local/bin/composer

6. 安装iptables防火墙,开放3306端口

1. 关闭默认的firewall
systemctl stop firewalld.service
systemctl disable firewalld.service
systemctl mask firewalld.service
2. 安装iptables防火墙
yum install iptables-services -y
3. 启动设置防火墙
systemctl enable iptables
systemctl start iptables
4. 查看防火墙状态
systemctl status iptables
5. 编辑防火墙,增加端口
vi /etc/sysconfig/iptables #编辑防火墙配置文件(配置要开放的端口)
端口开放的配置代码如下:
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
:wq! #保存退出
注:
iptables默认配置文件里有两行设置:
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
这两行设置一定要写在其他 端口开放 配置代码的 下面,不然会导致端口开放失败
6. 重启配置,重启系统
systemctl restart iptables.service #重启防火墙使配置生效
systemctl enable iptables.service #设置防火墙开机启动

6. 安装git

1. 下载安装git
yum -y install git
2. 检查是否安装成功
git --version

7. 下载或克隆laravel项目到/usr/share/nginx/html目录下

一、网站项目根目录是/usr/share/nginx/html/
1. 进入/usr/share/nginx/html/下
2. 给文件权限
二、以上操作针对的都是root用户,需要开放网站访问用户权限
1. 给 /usr/share/nginx/html/项目名 设置权限
chown -R :www /usr/share/nginx/html/项目名
2. 给项目下的storage目录写的权限
chmod -R 775 /usr/share/nginx/html/项目名/storage
3. 如果给完775权限扔不能访问,那么给整个项目777权限
chmod -R 777 /usr/share/nginx/html/项目名/

8. 设置nginx配置文件

1. 进入nginx目录下的conf.d文件夹

cd /etc/nginx/conf.d/

2. 新建一个自己网站的配置文件

vim yourwebsite.com.conf

文件以.conf结尾,名字一般为自己网站的名,这样方便辨识

3. 在新建的配置文件中写入如下内容:

server {
    listen  80;
    server_name yourwebsite.com;
    set $root_path 'your project path/public';
    root $root_path;

    index index.php index.html index.htm;

    try_files $uri $uri/ @rewrite;

    location @rewrite {
        rewrite ^/(.*)$ /index.php?_url=/$1;
    }

    location ~ \.php {

        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index /index.php;

        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;
    }

    location ~* ^/(css|img|js|flv|swf|download)/(.+)$ {
        root $root_path;
    }

    location ~ /\.ht {
        deny all;
    }
}

 

4. 配置完毕,重启nginx服务

systemctl restart nginx

 

 

 

编译安装Mysql

编译安装Mysql

1.准备工作

首先需要准备mysql的源码包,最新版本是5.7.20

下载地址为:

https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.20.tar.gz

 

同时,mysql 5.7需要boost 1.59以及以上版本,需要在sourceforge上下载。地址为:

http://www.boost.org/users/download/

 

  1. 安装之前最好检查一下是否已安装了mysql和boost
rpm -qa | grep mysql //查看系统自带mysql
yum -y remove mysql-* //卸载mysql
rpm -e --nodeps mysql-5.1.73-3.el6_5.x86_64 //卸载mysql
rpm -qa | grep boost //查看系统自带boost
yum -y remove boost-* //卸载boost
rpm -e --nodeps boost-filesystem-1.41.0-11.el6_1.2.x86_64 //卸载boost

 

  1. 然后安装其它得依赖包:
yum install gcc gcc-c++ ncurses ncurses-devel bison libgcrypt perl cmake

 

2.准备安装

  1. 首先将boost库解压出来
wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
tar -zxvf boost_1_59_0.tar.gz

 

  1. 然后拷贝到一个目录中
mv boost_1_59_0 /usr/local/boost

 

  1. 然后创建用户组以及用户
cat /etc/group | grep mysql //查看是否存在mysql用户组
cat /etc/passwd | grep mysql //查看是否存在mysql用户
groupadd mysql //创建用户组
useradd -r -g mysql mysql //创建用户

上面得工作完成以后,就可以开始编译mysql了,当然,先将mysql的源码解压出来:

3.开始编译安装

wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.20.tar.gz
tar xzvf mysql-5.7.20.tar.gz
cd mysql-5.7.20/

 

使用cmake和make命令来进行编译

cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/usr/local/mysql/data -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DMYSQL_TCP_PORT=3306 -DMYSQL_USER=mysql -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_MEMORY_STORAGE_ENGINE=1 -DENABLE_DOWNLOADS=1 -DDOWNLOAD_BOOST=1 -DWITH_BOOST=/usr/local/boost

 

关于参数的一些解释:

CMAKE_INSTALL_PREFIX:指定MySQL程序的安装目录,默认/usr/local/mysql
DEFAULT_CHARSET:指定服务器默认字符集,默认latin1
DEFAULT_COLLATION:指定服务器默认的校对规则,默认latin1_general_ci
ENABLED_LOCAL_INFILE:指定是否允许本地执行LOAD DATA INFILE,默认OFF
WITH_COMMENT:指定编译备注信息
WITH_xxx_STORAGE_ENGINE:指定静态编译到mysql的存储引擎,MyISAM,MERGE,MEMBER以及CSV四种引擎默认即被编译至服务器,不需要特别指定。
WITHOUT_xxx_STORAGE_ENGINE:指定不编译的存储引擎
SYSCONFDIR:初始化参数文件目录
MYSQL_DATADIR:数据文件目录
MYSQL_TCP_PORT:服务端口号,默认3306
MYSQL_UNIX_ADDR:socket文件路径,默认/tmp/mysql.sock
DDOWNLOAD_BOOST=1 :下载boost库
DWITH_BOOST=/usr/local/boost 安装boost库

 

编译:make

======================================================================

mysql编译安装过程,执行make命令时报错:

c++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See http://bugzilla.redhat.com/bugzilla for instructions.
make[2]: * [sql/CMakeFiles/sql.dir/item_geofunc.cc.o] Error 4
make[1]: * [sql/CMakeFiles/sql.dir/all] Error 2
make: * [all] Error 2

原因解析:

内存不足,mysql5.9以上的版本,编译安装需要1G内存,而我的云主机刚好1G内存。

解决方案

内存不足当然加内存,加内存太贵?那就把硬盘当内存来用把

dd if=/dev/zero of=/data/swap_add bs=1M count=2048
mkswap /data/swap_add
swapon /data/swap_add
swapon -s

======================================================================

编译时间非常长,我都困了,我先创建几个目录,因为我们指定编译参数得时候,指定了mysql得数据存储的目录,因此,这个时候可以先把目录都创建出来:

mkdir /usr/local/mysql
mkdir /usr/local/mysql/data
mkdir /usr/local/mysql/logs
mkdir /usr/local/mysql/pids

最后还有重要得一步,需要将目录得所有权交给mysql用户

chown -R mysql:mysql /usr/local/mysql //需要root权限

编译完成后执行make install 安装即可

随后,我们需要配置/etc/my.cnf文件:

vim /etc/my.cnf

然后写入参数,最终如下;

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/usr/local/mysql/logs/mysqld.log
pid-file=/usr/local/mysql/pids/mysqld.pid

 

3.性能调优

由于编译的时间是在太长了,这个地方的性能调优不涉及任何的sql优化,只针对一点:使用jemalloc来替换默认的内存管理

首先我们需要从网站上下载jemalloc,官网地址:

http://www.canonware.com/jemalloc/

从github上可以下载最新的源码:

https://github.com/jemalloc/jemalloc/releases

编译jemalloc:

./configure --libdir=/usr/local/lib
make
make install

为了保证能够找到jemalloc库,我们需要设置一下库路径,

echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf

ldconfig //执行这个命令可以刷新库路径

我们有两种方式来使用jemalloc来优化mysql

在编译的时候加入参数:

-DCMAKE_EXE_LINKER_FLAGS="-ljemalloc" -DWITH_SAFEMALLOC=OFF

然后重新编译一遍。

也可以修改 /usr/local/mysql/bin/mysqld_safe

在# executing mysqld_safe 下面加上

LD_PRELOAD=/usr/local/lib/libjemalloc.so

4.其它配置

通常我们需要重启服务器,最好在重启服务器的时候就启动mysql

cp support-files/mysql.server /etc/init.d/mysqld
chmod a+x /etc/init.d/mysqld //需要root权限

然后将mysql添加到环境变量,修改/etc/profile文件

vim /etc/profile //需要root

//在文件的最后面加入

#mysql path
export PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH

最后执行 source /etc/profile

随后我们也需要多数据库进行初始化操作。自 mysql5.7 开始,初始化系统表不再使用 mysql_install_db 工具, 而是使用 mysqld –initialize-insecure –user=mysql , 其中 –initialize 表示默认生成一个安全的密码, –initialize-insecure 表示不生成密码, 密码为空

mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data

现在可以启动mysql 服务器:

chkconfig mysqld on

最后我们将root密码修改一下:

mysql -u root
mysql> use mysql;
mysql>update user set authentication_string=password('123456') where user='root' and Host = 'localhost';
mysql> FLUSH PRIVILEGES;

特别提醒注意的一点是,新版的mysql数据库下的user表中已经没有Password字段了

而是将加密后的用户密码存储于authentication_string字段

完成,真实很困的一场编译啊。

 

 

 

 

 

 

 

 

编译安装PHP

准备工作

1.进入要安装的目录 下载PHP7

cd /usr/local
wget -O php7.tar.gz http://cn2.php.net/get/php-7.1.1.tar.gz/from/this/mirror

2.因为php安装需要编译,所以服务器应该保证gcc和g++环境的安装

yum -y install zlib zlib-devel openssl openssl-devel pcre-devel
yum -y install gcc gcc-c++ autoconf automake

首先释放安装包:

tar -xvzf php7
cd php-7.1.1/

接下来进行参数配置,配置前如果没有libxml2和libxml2-devel会报错,所以应该更新libxml2并安装libxml2-devel,使用在线安装:

yum -y install libxml2
yum -y install libxml2-devel

补充,因为不同的操作系统环境,系统安装开发环境包的完整程度也不相同,所以建议安装操作系统的时候做必要选择,也可以统一执行一遍所有的命令,将没有安装的组件安装好,如果已经安装了可能会进行升级,版本完全一致则不会进行任何操作,命令除上面2个之外,还要安装:

yum -y install openssl
yum -y install openssl-devel
yum -y install curl
yum -y install curl-devel
yum -y install libjpeg
yum -y install libjpeg-devel
yum -y install libpng
yum -y install libpng-devel
yum -y install freetype
yum -y install freetype-devel
yum -y install pcre
yum -y install pcre-devel
yum -y install libxslt
yum -y install libxslt-devel
yum -y install bzip2
yum -y install bzip2-devel

编译安装

以上这些包基本上够用了,如果发现问题再补充,安装完成之后,执行配置:

./configure \
--prefix=/usr/local/php \
--with-curl \
--with-freetype-dir \
--with-gd \
--with-gettext \
--with-iconv-dir \
--with-kerberos \
--with-libdir=lib64 \
--with-libxml-dir \
--with-mysqli \
--with-openssl \
--with-pcre-regex \
--with-pdo-mysql \
--with-pdo-sqlite \
--with-pear \
--with-png-dir \
--with-jpeg-dir \
--with-xmlrpc \
--with-xsl \
--with-zlib \
--with-bz2 \
--with-mhash \
--enable-fpm \
--enable-bcmath \
--enable-libxml \
--enable-inline-optimization \
--enable-gd-native-ttf \
--enable-mbregex \
--enable-mbstring \
--enable-opcache \
--enable-pcntl \
--enable-shmop \
--enable-soap \
--enable-sockets \
--enable-sysvsem \
--enable-sysvshm \
--enable-xml \
--enable-zip

实际上这里的配置项比上述还多,可以使用 ./configure –help 命令查看所有选项,这里注意在php7中–with-mysql原生支持已经不存在了,操作都变成mysqli或者pdo了;以上这些选项在正常的php开发中完全够用了,后期如果需要,可以选择手动开启相应的模块

然后执行编译安装:

make&&make install

编译安装时间可能会有点长稍等一会吧!

php的默认安装位置上面已经指定为/usr/local/php,接下来配置相应的文件:

cp php.ini-development /usr/local/php/lib/php.ini
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
cp sapi/fpm/php-fpm /usr/local/bin

然后设置php.ini,使用: vim /usr/local/php/lib/php.ini 打开php配置文件找到cgi.fix_pathinfo配置项,这一项默认被注释并且值为1,根据官方文档的说明,这里为了当文件不存在时,阻止Nginx将请求发送到后端的PHP-FPM模块,从而避免恶意脚本注入的攻击,所以此项应该去掉注释并设置为0

设置完毕保存并退出

另外注意一个地方就是php.ini配置文件的位置可以在编译前配置参数中设置,编译参数可以写成:–with-config-file-path=/usr/local/php 这样的话php就回去指定的目录下读取php.ini配置文件,如果不加这个参数默认位置就是php安装目录下的lib目录,具体也可以在phpinfo()输出界面查看,如果php.ini放到其他位置,php读取不到,那么所有的配置修改后都是不生效的,这点要注意

此时首先应该创建web用户:

groupadd www-data
useradd -g www-data www-data

然后网上一些教程说让修改php-fpm.conf添加以上创建的用户和组,这时候使用 vim /usr/local/etc/php-fpm.conf 打开文件后找不到官方所提示的位置:

如果此时随便在一个位置添加,那么接下来启动php-fpm的时候,会报目录找不到的错误,所以不要在php-fpm.conf中添加用户和组,这个时候翻到php-fpm.conf最后一行会发现如下内容(如果编译时添加–prefix选项以下位置会自动补全,默认是下面是空的,要注意):

这里引入了php-fpm.d目录下所有的conf配置文件,但是NONE需要修改为我们的实际目录:/usr/local

默认情况下etc/php-fpm.d/下有一个名为www.conf.defalut的配置用户的文件,执行下面命令复制一个新文件并且打开:

cp /usr/local/php/etc/php-fpm.d/www.conf.default  /usr/local/php/etc/php-fpm.d/www.conf
vim /usr/local/php/etc/php-fpm.d/www.conf

 

默认user和group的设置为nobody,将其改为www-data

修改完成之后,保存并退出,然后执行以下命令启动php-fpm服务:

/usr/local/bin/php-fpm

启动完毕之后,php-fpm服务默认使用9000端口,使用 netstat -tln | grep 9000 可以查看端口使用情况:

9000端口正常使用,说明php-fpm服务启动成功

然后执行 vim /usr/local/nginx/nginx.conf 编辑nginx配置文件,具体路径根据实际的nginx.conf配置文件位置编辑,下面主要修改nginx的server {}配置块中的内容,修改location块,追加index.php让nginx服务器默认支持index.php为首页:

然后配置.php请求被传送到后端的php-fpm模块,默认情况下php配置块是被注释的,此时去掉注释并修改

这里面很多都是默认的,root是配置php程序放置的根目录,主要修改的就是fastcgi_param中的/scripts为$document_root

修改完上面的,回到nginx.conf第一行,默认是#user nobody;  这里要去掉注释改为user www-data;或者user www-data www-data;表示nginx服务器的权限为www-data

修改完这些保存并退出,然后重启nginx:

/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx/sbin/nginx

接下来编辑一个测试的php程序,在nginx下的html目录下创建index.php文件,打印一下php配置:

<?php
    phpinfo();
?>

 

 

 

 

什么?你想更了解我?

点击联系点击联系