1. <s id="ykofe"></s>
      <object id="ykofe"><option id="ykofe"></option></object>

      <s id="ykofe"></s>

      Laravel - 為 WEB 藝術家創造的 PHP 框架。

      PHP THAT DOESN'T HURT. CODE HAPPY & ENJOY THE FRESH AIR.

      Laravel logo

      2016 版 Laravel 系列入門教程(三)

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

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

      在本篇文章中,我們將嘗試構建一個帶后臺的簡單博客系統。我們將會使用到 路由、MVC、Eloquent ORM 和 blade 視圖系統。

      簡單博客系統規劃

      我們在教程一中已經新建了一個 Eloquent 的 Model 類 Article,使用 migration 建立了數據表并使用 seeder 填入了測試數據。我們的博客系統暫時將只管理這一種資源:后臺需要使用賬號密碼登錄,進入后臺之后,可以新增、修改、刪除文章;前臺顯示文章列表,并在點擊標題之后顯示出文章全文。

      下面我們正式開始。

      搭建前臺

      前臺的搭建是最簡單的,我先帶領大家找找感覺。

      修改路由

      刪掉

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

      將 /home 那一行修改為 Route::get('/', 'HomeController@index');,現在我們系統的首頁就落到了 App\Http\Controllers\HomeController 類的 index 方法上了。

      查看 HomeController 的 index 函數

      learnlaravel5/app/Http/Controllers/HomeController.php 的 index 函數只有一行代碼: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-10 col-md-offset-1">
                  <div class="panel panel-default">
                      <div class="panel-heading">Dashboard</div>
      
                      <div class="panel-body">
                          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') 中進行輸出。

      訪問首頁

      訪問 http://fuck.io:1024 ,不出意外的話,你會看到這個頁面:

      為什么需要登錄呢?怎么去掉這個強制登錄呢?刪掉 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());
      }
      

      修改視圖文件

      修改視圖文件 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
      

      刷新

      如果你得到以上頁面,恭喜你,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.2.0/css/bootstrap.min.css" rel="stylesheet">
          <script src="//cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
          <script src="//cdn.bootcss.com/bootstrap/3.2.0/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 為如下代碼:

      <!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>Laravel</title>
      
          <link href="//cdn.bootcss.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
          <script src="//cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
          <script src="//cdn.bootcss.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
      </head>
      <body id="app-layout">
          <nav class="navbar navbar-default navbar-static-top">
              <div class="container">
                  <div class="navbar-header">
      
                      <!-- Collapsed Hamburger -->
                      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#app-navbar-collapse">
                          <span class="sr-only">Toggle Navigation</span>
                          <span class="icon-bar"></span>
                          <span class="icon-bar"></span>
                          <span class="icon-bar"></span>
                      </button>
      
                      <!-- Branding Image -->
                      <a class="navbar-brand" href="{{ url('/') }}">
                          Laravel
                      </a>
                  </div>
      
                  <div class="collapse navbar-collapse" id="app-navbar-collapse">
                      <!-- Left Side Of Navbar -->
                      <ul class="nav navbar-nav">
                          <li><a href="{{ url('/home') }}">Home</a></li>
                      </ul>
      
                      <!-- Right Side Of Navbar -->
                      <ul class="nav navbar-nav navbar-right">
                          <!-- Authentication Links -->
                          @if (Auth::guest())
                              <li><a href="{{ url('/login') }}">Login</a></li>
                              <li><a href="{{ url('/register') }}">Register</a></li>
                          @else
                              <li class="dropdown">
                                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
                                      {{ Auth::user()->name }} <span class="caret"></span>
                                  </a>
      
                                  <ul class="dropdown-menu" role="menu">
                                      <li><a href="{{ url('/logout') }}"><i class="fa fa-btn fa-sign-out"></i>Logout</a></li>
                                  </ul>
                              </li>
                          @endif
                      </ul>
                  </div>
              </div>
          </nav>
      
          @yield('content')
      
      </body>
      </html>
      

      接下來我們來著手搭建后臺。

      構建 Article 詳情頁

      搭建后臺

      生成控制器

      我們使用 Artisan 工具來生成控制器文件:

      php artisan make:controller Admin/HomeController
      

      成功之后,我們就可以看到 artisan 幫我們建立的文件夾及控制器文件了:

      增加路由

      我們要使用路由組來將后臺頁面置于“需要登錄才能訪問”的中間件下,以保證安全:

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

      上一篇文章中我們已經接觸到了路由組,這是 Laravel 的另一個偉大創造。路由組可以給組內路由一次性增加 命名空間、uri 前綴、域名限定、中間件 等屬性,并且可以多級嵌套,異常強大。路由組中文文檔在此:http://laravel-china.org/docs/5.1/routing#route-groups

      上面的三行代碼的功能簡單概括就是:訪問這個頁面必須先登錄,若已經登錄,則將 http://fuck.io:1024/admin 指向 App\Http\Controllers\Admin\HomeController 的 index 方法。其中需要登錄由 middleware 定義, /admin 由 prefix 定義,Admin 由 namespace 定義,HomeController 是實際的類名。

      構建后臺首頁

      新建 index 方法

      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">Dashboard</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/AuthController.php 中的相應代碼為:

      protected $redirectTo = 'admin';
      

      嘗試登錄

      訪問 http://fuck.io:1024/admin ,它會跳轉到登陸界面,輸入郵箱和密碼之后,你應該會看到如下頁面:

      恭喜你,后臺首頁搭建完成!下面我們開始構建 Article 的后臺管理功能。

      構建 Article 后臺管理功能

      讓我們先嘗試點一下 “管理文章”按鈕,不出意外你將得到一個 404 的報錯:

      進步之道

      很多新手看到這個報錯直接就慌了:什么鬼?全是英文看不懂呀。然后在文章下面把完整的錯誤棧全部粘貼出來。老實說我第一次見到 Laravel 報這個錯也是完全沒耐心去讀,不過我還是復制了最明顯的那個詞“NotFoundHttpException”去 Google 了一下,從此我就再也沒搜索過它了。

      我為我的浮躁感到羞愧。那句話說的太對了:大多數人的努力程度之低,完全沒有到拼天賦的程度。愿本教程的讀者都做“少數人”。

      添加路由

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

      刷新,錯誤變了:

      新建控制器

      上圖中的報錯是控制器不存在。我們使用 Artisan 來新建控制器:

      php artisan make:controller Admin/ArticleController
      

      刷新,錯誤又變了:

      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
      

      刷新,錯誤又變了:

      Article 類不存在?原因很簡單:Article 類和當前控制器類不在一個命名空間路徑下,不能直接調用。解決辦法就是主動導入 \App\Article 類:

      ... ...
      use App\Http\Requests;
      use App\Http\Controllers\Controller;
      
      use App\Article;
      
      class ArticleController extends Controller
      {
      ... ...
      

      如果你還不熟悉命名空間,可以參考《PHP 命名空間 解惑》

      檢查成果

      再次刷新,你應該能看到如下畫面:

      如果你沒到這個畫面也不用擔心,根據他的錯誤提示去 Google 吧,一定能解決的。

      新增、編輯、刪除功能怎么辦?

      這三個功能我將在下一篇教程與大家分享,這是目前的 2015 版 Laravel 教程做的不夠好的地方,其實這里才是最應該掰開揉碎仔細講解的地方。


      原文:https://github.com/johnlui/Learn-Laravel-5/issues/6


      關于作者 JohnLui
      PHP 框架 TinyLara 作者。
      国模吧私拍