欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          30分鐘用 Laravel 實現(xiàn)一個博客

          30分鐘用 Laravel 實現(xiàn)一個博客

          介紹

          • Laravel 是一款 MVC架構(gòu)、 目前最流行的 PHP框架。
          • Laravel的優(yōu)點在于: 豐富的composer類庫支持, 優(yōu)雅的代碼, 未來的主流框架(目前市場占有率最高的框架)
          • Laravel的缺點在于: 過于優(yōu)雅(我們只需要編寫極少的代碼即可實現(xiàn)功能,意味著底層極其復(fù)雜的封裝)導(dǎo)致程序的執(zhí)行效率略低, 和thinkphp等國內(nèi)主流框架相比,上手難度略高(因為它為我們集成了很多其他的功能,甚至你還需要學(xué)習(xí)nodeJS相關(guān)的知識)。
          • 本項目,是完全使用 Laravel框架 內(nèi)的所提供的最基礎(chǔ),但是又是最有用(能顯著提升我們開發(fā)效率)的工具而開發(fā)出來的。在學(xué)習(xí)過程中,你只需要操作一次數(shù)據(jù)庫,不需要自己構(gòu)建html視圖模板(當(dāng)然還是要寫一些html和js代碼的),不需要考慮外部的css、js。本教程的目的完全為向各位 phper 以及對 laravel 有興趣的小伙伴推薦這款我相信是未來主流的php框架。

          推薦教程:2019年最新的五個Laravel視頻教程推薦

          準(zhǔn)備工作

          • 確保你了解 php面向?qū)ο缶幊?的基礎(chǔ)知識, 會html和簡單的js, 在css方面: 我們使用laravel內(nèi)置的 bootstrap4, 最后,一定要會使用 composer。
          • 唯一一次操作數(shù)據(jù)庫: 創(chuàng)建用戶、數(shù)據(jù)庫,授權(quán)

          如果你愿意用root用戶,你甚至只需要 create 一個 database 即可。 (不過不推薦,我的習(xí)慣是一個項目 對應(yīng) 一個用戶 + 一個數(shù)據(jù)庫,root則只用來管理他們)

          # 創(chuàng)建用戶 blog, 密碼自定義 CREATE USER 'blog'@'%' IDENTIFIED BY '密碼'; # 創(chuàng)建數(shù)據(jù)庫 blog, 設(shè)置默認(rèn)編碼為utf8 CREATE DATABASE `blog` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; # 授權(quán) 授予 blog庫下所有表的 所有權(quán)限 給 用戶blog GRANT ALL on blog.* to 'blog'@'%';
          • 使用 composer 創(chuàng)建一個 laravel 項目 取名叫blog
          # 進入你本地服務(wù)器用于存放網(wǎng)站文檔的目錄,輸入命令 composer create-project --prefer-dist laravel/laravel blog
          • 你還需要配置一個虛擬主機以提升開發(fā)效率(直接訪問url,不需要 “l(fā)ocalhost/項目/public” 訪問 ),你可以選擇手動配置,或者選擇集成開發(fā)環(huán)境創(chuàng)建項目(推薦:mac=>mamp 、 windows=>phpstudy。)。

          下文中,“/” 即表示 laravel 框架的根目錄

          • 配置 /.env 文件
          # 數(shù)據(jù)庫配置 DB_CONNECTION=mysql #類型 DB_HOST=127.0.0.1 #ip DB_PORT=3306 #端口 DB_DATABASE=數(shù)據(jù)庫名 DB_USERNAME=用戶名 DB_PASSWORD=密碼
          • 下載中文包 composer require caouecs/laravel-lang 然后將 /vendor/caouecs/src/zh-CN/ 放入 /resources/lang/ 下
          • 配置一下 /config/app.php
          # 時區(qū) 'timezone' => 'Asia/Shanghai', # 語言 'locale' => 'zh-CN',

          準(zhǔn)備工作總結(jié)

          • 1、創(chuàng)建用戶、數(shù)據(jù)庫,然后授權(quán)。
          • 2、使用 composer 創(chuàng)建項目。
          • 3、配置 laravel 的環(huán)境 ./env 。 然后使用 composer 安裝了漢化包,并且在 /config/app.php 中設(shè)置時區(qū)并且讓中文包生效。

          第一階段: Migration、Factory、Seeder

          你可能沒有見過上面3個名詞,不過和他們有關(guān)的文件都存放在 /database/ 下: 通過這個文件夾的名稱,你大概已經(jīng)猜到:這三個文件都是用來操作數(shù)據(jù)庫的。


          • 上文中,我們只是創(chuàng)建了數(shù)據(jù)庫,并沒有創(chuàng)建數(shù)據(jù)表,現(xiàn)在來確定一下我們的數(shù)據(jù)表

            • 一個用戶表 users
            • 一個博客表 blogs
            • 一個評論表 comments

            項目是一個個人博客,因此只有博主可以發(fā)布、刪除、修改博客。其他用戶則可以查看博客和發(fā)布評論。

          • 使用 Migration 創(chuàng)建這3張數(shù)據(jù)表

            • 打開命令行,創(chuàng)建 migrations
              php artisan make:migration create_blogs --create=blogs 博客表,
              php artisan make:migration create_comments --create=comments 評論表

            php aritsan 是laravel內(nèi)置的命令 你可以直接在控制臺輸入它,則會在控制臺提示你接下來你能輸入的命令。
            上文我們就使用 make:migration 幫我們創(chuàng)建了遷移文件, –create 是參數(shù),即告訴這條命令,幫我們創(chuàng)建一個用于創(chuàng)建數(shù)據(jù)表的遷移文件

          • 為什么不創(chuàng)建用戶表呢? 打開 /database/migrations/ 你會發(fā)現(xiàn)有一個2014年就創(chuàng)建好的 針對 users 和 password_resets 表。這是框架自帶的。

          • 編輯這兩個遷移文件

            • create_blogs
            // 首先類定義中,有兩個方法,up()可以理解為正向操作:創(chuàng)建表,而 down()可以理解為回滾操作:刪除表。 // up() Schema::create('blogs', function (Blueprint $table) {     $table->increments('id');     $table->string('title');     $table->text('content');     $table->timestamps(); }); // down() 已經(jīng)自動幫我們寫好了。
            • create_comments
            // up() Schema::create('comments', function (Blueprint $table) {         $table->increments('id');         $table->string('content');         $table->integer('blog_id'); //這條評論是針對哪一篇博客的?         $table->integer('user_id'); //這條評論是哪一位用戶發(fā)送的?         $table->timestamps();     });
          • 執(zhí)行遷移: 1、確保你的 /.env 配置正確 2、確保你的數(shù)據(jù)庫可以正常使用 3、確保數(shù)據(jù)庫中沒有數(shù)據(jù)表或者沒有和users blogs comments重名的數(shù)據(jù)表 php artisan migrate

          • 打開數(shù)據(jù)庫(你可以任選一款數(shù)據(jù)庫管理工具,或者直接使用mysql的命令行),打開數(shù)據(jù)庫 blog ,你會發(fā)現(xiàn)有以下表

            • blogs => 我們創(chuàng)建的博客表
            • comments => 我們創(chuàng)建的評論表
            • migrations => 系統(tǒng)創(chuàng)建的遷移記錄表
            • password_resets => 框架自帶遷移文件生成的重置密碼用表
            • users => 框架自帶的用戶表
          • 主要解釋一下 migrations 表:

            • 這是一個記錄你的遷移文件名稱和批次的表。它的主要作用是通過記錄批次,方便你對數(shù)據(jù)庫進行版本控制:打開 migrations表,你會發(fā)現(xiàn),當(dāng)前記錄了4張表的遷移文件名,而他們的batch都是1,你可以理解為當(dāng)前數(shù)據(jù)庫是第一批,版本1。
            • 如果你執(zhí)行 php artisan migrate:rollback 即回滾數(shù)據(jù)庫,將會執(zhí)行批次batch最大的記錄的那些遷移文件的 down() 方法。
          • migration 的作用:1、幫我們省略了去寫sql語句的麻煩,2、讓我們對數(shù)據(jù)庫可以進行有效的版本控制。


          • 使用模型工廠 Factory 來插入虛構(gòu)的數(shù)據(jù)

          在日常的開發(fā)中,我們需要很多模擬的數(shù)據(jù)進行測試,模型工廠的作用就是幫我們快速的,隨機的生成這些數(shù)據(jù)。

          • 創(chuàng)建模型工廠 php artisan make:factory BlogFactory --model=Blog , 關(guān)于評論表的模型工廠請自己寫。
          • 注意此時我們其實沒有模型 Blog 和模型 Comment,我們只是創(chuàng)建了數(shù)據(jù)表而已。因此我們再創(chuàng)建兩個模型。
            php artisan make:model Blog, 關(guān)于評論表的模型請自己寫。

          細(xì)心的你可能發(fā)現(xiàn)了,我們的數(shù)據(jù)表和模型的名字是有區(qū)別的:數(shù)據(jù)表為“小寫復(fù)數(shù)形式”,而模型名為“大寫單數(shù)形式”。 創(chuàng)建的模型都存在于 /app/ 下。

          • 編輯模型工廠 /database/factories
            • BlogFactory
            // 使用 Faker 類為我們提供的生成隨機偽造數(shù)據(jù)的方法生成數(shù)據(jù)   return [       'title' => $faker->name,          'content' => $faker->text, ];
            • CommentFactory
            return [     'content' => $faker->text,         'blog_id' => 1,         'user_id' => 1,  ];
          • 使用 tinker 模式調(diào)試代碼
            • 進入 “修補匠模式” php artisan tinker , 當(dāng)命令提示符變?yōu)?">>>" 時,你就處于tinker模式下了,此時你可以輸入php代碼,或者調(diào)用laravel提供的全局函數(shù),甚至引用一個類,調(diào)用它的靜態(tài)方法或者實例化它。
            • 在 tinker 模式下使用全局函數(shù) factory() 生成模擬的數(shù)據(jù) factory(AppBlog::class)->make() 此時屏幕上會顯示,它給你模擬出來的一個虛擬數(shù)據(jù)數(shù)組。
            • 使用 create() 一次性向數(shù)據(jù)表中插入100條模擬的數(shù)據(jù) factory(AppBlog::class, 100)->create() 打開數(shù)據(jù)庫,您會發(fā)現(xiàn)100條標(biāo)題和內(nèi)容都無關(guān)緊要,但是對我們快速開發(fā)特別有用的測試數(shù)據(jù)已經(jīng)存放在數(shù)據(jù)庫中了。

          • 使用 Seeder 一次性完成多個數(shù)據(jù)庫的批量虛擬數(shù)據(jù)插入
          • 創(chuàng)建 Seeder (如果你處于 tinker, 【ctrl】+【c】 先退出) php artisan make:seeder UserTableSeeder ,針對博客表和評論表的Seeder創(chuàng)建命令自己寫。
          • 打開 /database/seeds/ 我們創(chuàng)建的Seeder都在這里了,不過多了一個 DatabaseSeeder.php,我們等下再來了解它,先編輯其他Seeder,以 UserTableSeeder.php 為例
          ... use AppUser;  // 在 class 關(guān)鍵字前面,引用一下 User 模型 class ... public function run()  {     factory(AppUser::class, 50)->create(); //向users表中插入50條模擬數(shù)據(jù)     $user = User::find(1); //插入完后,找到 id 為 1 的用戶     $user->name = "najiuyuanzou"; //設(shè)置 用戶名     $user->email = "najiuyuanzou@test.com"; //設(shè)置 郵箱     $user->password = bcrypt('liuhaoyu'); //設(shè)置 密碼     $user->save(); //保存  }

          在這里我們明確1號用戶為真實的可用的管理員用戶!所以我們設(shè)置一下它的 用戶名 郵箱 以及密碼

          • 其余的Seeder我們可以只插入模擬的數(shù)據(jù)即可。

          • 現(xiàn)在回過頭來,編輯 DatabaseSeeder

          public function run() {     // $this->call(UsersTableSeeder::class);      // 這里給我們舉例了如何引用其他Seeder         $this->call(UserTableSeeder::class);         $this->call(BlogTableSeeder::class);         $this->call(CommentTableSeeder::class);// 這里有先后關(guān)系需要注意一下: 評論n : 1文章/用戶,所以應(yīng)該把它寫在最后 }

          • 使用命令,刷新整個數(shù)據(jù)庫并且執(zhí)行模擬數(shù)據(jù)插入 php artisan migrate:refresh --seed => 查看數(shù)據(jù)庫,發(fā)現(xiàn)數(shù)據(jù)庫重置了,并且 users blogs comments 每張表都有很多虛擬的數(shù)據(jù)。

          第一階段總結(jié)

          • 學(xué)習(xí)使用 migrations 的創(chuàng)建、編輯、執(zhí)行以及回滾: 實現(xiàn)對數(shù)據(jù)表的結(jié)構(gòu)更改以及數(shù)據(jù)庫版本管理(說白了就是個帶日志的數(shù)據(jù)表結(jié)構(gòu)管理工具)
          • 學(xué)習(xí)使用 factories 的創(chuàng)建、使用 tinker 調(diào)試、使用 factory() 全局函數(shù)制造和插入數(shù)據(jù)。
          • 學(xué)習(xí)使用 seeds 的創(chuàng)建(Seeder)、編輯其他Seeder(在 run() 中調(diào)用 factory() )、編輯DatabaseSeed(在 run() 中調(diào)用 其他 Seeder)。
          • 最后通過它們3個的配合,使用命令刷新了整個數(shù)據(jù)庫并且分別向3張表插入了很多模擬的數(shù)據(jù),便于我們開發(fā)。

          也許你到這里會覺得這還不如你寫sql語句。但是請相信我,等你熟練掌握使用這些東西之后,你的開發(fā)速度會非??欤。ó吘鼓悴恍枰?"INSERT INTO table values ()" 復(fù)制粘貼修改100遍了)

          第二階段: Auth的使用

          • 輸入神奇的命令,看看發(fā)生了什么 php artisan make:auth
          • 打開瀏覽器輸入你配置的虛擬主機地址,你會看到一個Laravel框架的歡迎頁面,這不是重點,點擊右上角的 register ,你可以注冊賬號,點擊 login 你可以登陸…
          • 本階段結(jié)束。

          第二階段繼續(xù): Auth

          • 好吧你可能很懵逼,但這就是Laravel的厲害之處,那個2014年就建好的migration遷移文件可不是個擺設(shè)。它就是通過操作users表來實現(xiàn)注冊登陸等等的。

          • php artisan make:auth 到底干了哪些事情呢?

            • 它給你創(chuàng)造了一組控制器,位于 /app/Http/Controllers/Auth
            • 它在 /routes/web.php 中給你定義了2條路由
            Auth::routes(); //這是用戶操作相關(guān)的路由 Route::get('/home', 'HomeController@index')->name('home'); //這是主頁的路由
            • 它給你創(chuàng)造了一組視圖 /resources/views/auth/ 下是用戶操作相關(guān)的路由, home.blade.php是主頁, layouts/下是布局模板。
          • 我們改良一下它自動為我們生成的東西

            • 路由方面 (routes/web.php) 我們將根路由也指向視圖 home.blade.php ,這是最后的有效代碼:
            // Route::action('uri', 'Controller@function'); Route::get('/', 'HomeController@index');  Auth::routes();  Route::get('/home', 'HomeController@index')->name('home');
            • 控制器方面 app/Http/Controllers/ 我們修改一下 HomeController.php
            /**  * 這里這個構(gòu)造函數(shù)調(diào)用了 中間件auth 對我們進行權(quán)限認(rèn)證  * 即要求我們必須登陸才可以訪問該控制器的其他方法  * 有兩種解決方法,一直是在 $this->middleware('auth')->except('你要排除權(quán)限認(rèn)證的方法'),比如 ...->except('index')  * 另一種是直接干掉這個函數(shù)(我們確定這個控制器就只是來展示首頁的,那么就干掉它吧)  */ // public function __construct() // { //     $this->middleware('auth'); // }
            • 視圖方面:HomeController@index (這里我指的是 Home控制器的 index() 方法)調(diào)用了 return view('視圖名稱') 來抓取視圖顯示在頁面上,現(xiàn)在打開瀏覽器訪問主頁,你就可以看得到 home.blade.php 中的內(nèi)容了,我們看看 /resources/views/home.blade.php 的內(nèi)容: 重點: @extens @section
            {{--  內(nèi)容不重要我們等下要改,先來看下 @符號 的作用  --}}  {{--  @extends繼承其他模板  --}} @extends('layouts.app') {{--  這里的layouts.app => /resources/views/layouts/app.blade.php  --}}  {{--  @section 填充在布局模板上用 @yield 標(biāo)注的占位符  --}} @section('content') {{--  你可以在 /resources/views/layouts/app.blade.php 看到 @ yield('content')標(biāo)注的占位符 --}}     ... 這里面是html內(nèi)容 @endsection

            Auth為我們生成的整個視圖模板的邏輯: layouts/app.blade.php 為布局模板,其他模板都繼承該模板。

            • 最后我們“漢化”這些視圖
              • home.blade.php,你可以自由發(fā)揮,展示一個好看的主頁,這是我的
              @extends('layouts.app')  @section('content')<div class="container">     <div class="row justify-content-center">             <div class="col-md-8">                     <div class="card">                          <div class="card-header">歡迎!這里是 “那就遠(yuǎn)走” 的個人博客</div>             <div class="card-body">                     如無牽掛,那就遠(yuǎn)走。                     {{--  這里等下要添加一個跳轉(zhuǎn)到展示文章列表頁面的按鈕  --}}             </div>                   </div>            </div>        </div>  </div>  @endsection
              • ../layouts/app.blade.php & ../auth/login.blade.php & register.blade.php
              # 首先布局模板我們需要把 brand 登陸、注冊這些東西改一改 {{ config('app.name', 'Laravel') }} => 我的博客 //注意這里有一個 config('app.name') 該函數(shù)其實是讀取的 /.env 里的 APP_NAME 值,且默認(rèn)值為 'Laravel' ,也就是說,你改 APP_NAME 也可以改這里顯示的值,不過我嫌麻煩,直接查找替換了。 {{ __('Login') }} => 登陸 {{ __('Register') }} => 注冊 {{ __('Logout') }} => 退出 # 然后登陸模板: {{ __('Login') }} => 登陸 {{ __('E-Mail Address') }} => 郵箱 {{ __('Password') }} => 密碼 {{ __('Remember Me') }} => 記住我 然后我們把 ForgetPassword 那個按鈕給干掉吧(這個找回密碼的功能需要一個SMTP服務(wù)的郵箱才能實現(xiàn),現(xiàn)在暫時不弄) # 然后注冊模板 {{ __('Register') }} => 注冊 {{ __('Name') }} => 昵稱(用戶名) {{ __('Confirm Password') }} => 密碼確認(rèn) # 有可能有說漏的,反正自己看著頁面上的英文查找替換成中文就可以了。

          第二階段總結(jié)

          • 我們使用一條命令就實現(xiàn)了用戶操作的相關(guān)功能。
          • 但是這條命令生成的視圖是英文的,所以需要我們改成中文。
          • 這條命令主要是 生成了一組用戶操作的控制器+主頁控制器(其實還有中間件),生成了2條路由,生成了一組視圖。

          第三階段_1: 路由、模型、視圖、控制器詳解。

          • 如果你完全熟悉MVC架構(gòu),可以跳過這一步。
          • 這里用大白話解釋:
            • 路由: /routes/web.php 瀏覽器中輸入的地址,比如定義 Route::get('home', 'HomeController@home') => 即表示,你輸入 "http://localhost/blog/public/home" 是以GET的請求方式去請求 HomeController 的 home() 方法。
            • 模型: /app/ 一個模型對應(yīng)數(shù)據(jù)庫中的一張數(shù)據(jù)表。(注意大小寫和單復(fù)數(shù),模型:Model => 數(shù)據(jù)表:models)
            • 視圖: /resources/views/ 視圖就是普通的html模板,它等待控制器通過 return view() 調(diào)用和渲染它,最終展示給網(wǎng)站訪客。
            • 控制器: /app/Http/Controllers/ 處理數(shù)據(jù)、調(diào)用模型、簡單地操作數(shù)據(jù)庫、渲染視圖…,都由它完成。
            • 總結(jié) => 路由定義在瀏覽器中訪問某控制器中某方法的地址,控制器完成一系列操作:如果需要操作數(shù)據(jù)庫,需要調(diào)用模型,每一個模型對應(yīng)一張表。如果需要顯示數(shù)據(jù),則需要找到框架內(nèi)指定位置的視圖,對它完成渲染。

          第三階段_2:資源路由、在資源控制器中完成對博客的增刪改查。

          我們寫的程序,除了前臺好看的界面,就是后臺的程序,而后臺的程序無非就是“增刪改查”以及“花式增刪改查”罷了。
          因此,仔細(xì)想想,對于一張數(shù)據(jù)表的操作,我們通常就需要這些行為:1、一個分頁展示所有數(shù)據(jù)的列表 2、一個添加數(shù)據(jù)的功能 3、一個編輯數(shù)據(jù)的功能 4、一個顯示單條數(shù)據(jù)詳細(xì)信息的功能 5、一個刪除功能。

          • 創(chuàng)建一個資源控制器,一次性幫我們生成能實現(xiàn)上面5個功能的方法 php artisan make:controller BlogController --resource --model=Blog ( –resouce生成的控制器為資源控制器即自帶 CURD增刪改查 所有方法的控制器 ) ( –model 是讓生成的控制器在參數(shù)列表中自動幫我們完成依賴注入生成實際變量 )

          • 根據(jù) 三_1 階段的說法,我們其實需要設(shè)置很多路由,來對應(yīng)生成的 BlogController 下的各種方法,Laravel已經(jīng)幫我們想到了所以它給我們提供了這樣一種方法配置路由,編輯 /routes/web.php ,在最后面添加這么一句 Route::resource('blog', 'BlogController');

          • 有一個命令可以看到當(dāng)前所有生效的路由 php artisan route:list ,控制臺自動彈出的表格中,Method 表示 請求方法,即
            Route::這里的方法() ,URI 表示 請求地址,即 Route::action('這里就是uri'), name 表示 路由別名,可以通過 Route::action('uri', 'Controller@function')->name('這里可以定義路由別名')

          • 你會發(fā)現(xiàn),有7條關(guān)于 blog 的路由,這就是 Route::resource('blog', 'BlogController') 幫我們生成的。(5個功能7條是因為 添加和編輯多了2條載入視圖的路由)

          • 完成增刪改查吧: 首先完成 BlogController@index : 展示列表

            • 先來個入口鏈接,打開 home.blade.php
            {{--  上面說過這里會添加一個按鈕  --}} <a href="{{ route('blog.index') }}" class="btn btn-lg btn-block btn-primary">點擊這里查看我的博客</a>
            • 編輯 BlogController@index => 這里還是再提醒一下吧,這是說 BlogController 的 index() 方法??刂破魑募荚?appHttpControllers 中
            <?php      namespace AppHttpControllers;      use AppBlog; //這里是使用命令創(chuàng)建控制器時,通過 --model=Blog 自動幫我們生成的      use IlluminateHttpRequest;      class BlogController extends Controller{          public function index()              {                    // 查詢數(shù)據(jù),并且讓查詢結(jié)果是一個可分頁對象         $blogs = Blog::orderBy('created_at', 'desc') // 調(diào)用 Blog模型 的靜態(tài)方法 orderBy('根據(jù)created_at字段', '倒敘排序')             ->paginate(6); // -> 鏈?zhǔn)讲僮鳎簆aginate(6) 即數(shù)據(jù)沒頁6條                 // 跳轉(zhuǎn)到視圖并傳值               return view('blog.index', [ //第一個參數(shù)是說,視圖模板是 /resources/views/blog/index.blade.php            'blogs' => $blogs, //這里是說,我們給視圖傳遞一個叫 $'blogs'的變量,值是前面我們查詢的數(shù)據(jù),也叫$blogs。         ]); // view() 的第二參數(shù)也可以使用 view(..., compact('blogs'))     }
            • 此時刷新頁面當(dāng)然會報錯了,因為我們的視圖還不存在,新建文件夾 /resources/views/blog/index.blade.php
            @extends('layouts.app')  @section('content') <div class="container">     <div class="row justify-content-center">           <div class="card">                  <div class="card-header">這是頁面小標(biāo)題</div>                    <div class="card-body">                 這里是內(nèi)容                   </div>             </div>       </div>  </div> @endsection

            這就是我們所有頁面的布局,可以復(fù)制一份,作為模板。

            • 完成視圖里面的內(nèi)容
            <div class="container">     <div class="row justify-content-center">             <div class="card">                   <div class="card-header">文章列表</div>                      <div class="card-body">                          <table class="table table-hover table-bordered">                  <thead class="bg-info">                                       <tr>                                             <th>文章標(biāo)題</th>                                           <th>發(fā)布時間</th>                                            <th>相關(guān)操作</th>                                        </tr>                                     </thead>                              <tbody>          {{-- 這里通過 @foreach 遍歷數(shù)據(jù) --}} @foreach ($blogs as $blog)                      <tr>                                             <td>{{ $blog->title }}</td>                                  <td>{{ $blog->created_at }}</td>                               <td></td>                                          </tr>                   @endforeach                                      </tbody>                                    <tfoot>         {{-- 這里通過 $blogs->links() 來顯示分頁按鈕 --}} {{ $blogs->links() }}                   </tfoot>                            </table>                    </div>            </div>        </div>  </div>
            • 完成文章添加 添加入口鏈接, ../layouts/app.blade.php
            {{-- route('路由別名') 在視圖上就是一個指向 BlogController@create 的鏈接 --}} <a href="{{ route('blog.create') }}" class="dropdown-item"> 添加文章 </a>
            • 完成文章的添加 BlogController@create
            public function create(){     return view('blog.create'); //載入視圖     }
            • 編輯視圖 重點:表單中添加@csrf告訴框架,這是我們自己的表單,不用擔(dān)心csrf跨站請求偽造的攻擊
            @extends('layouts.app')  @section('content') <div class="container">     <div class="row justify-content-center">             <div class="card">                    <div class="card-header">添加文章</div>                       <div class="card-body">       {{--  from.method="POST" action="通過 route()函數(shù)讀取路由別名 " --}}              <form method="POST" action="{{ route('blog.store') }}">           {{--  聲明 csrf 令牌  --}}            @csrf                                <div class="form-group">                                      <label for="title">文章標(biāo)題</label>                                 <input type="text" class="form-control" id="title" placeholder="請輸入文章標(biāo)題" name="title">                </div>                                  <div class="form-group">                                      <label for="content">文章內(nèi)容</label>                                <textarea id="content" cols="30" rows="10" class="form-control" name="content"></textarea>               </div>                               <button class="btn btn-primary" type="submit">發(fā)布新文章</button>                </form>                     </div>              </div>         </div>    </div>   @endsection

            所謂跨站請求偽造,可以理解為來自于其他ip的表單,惡意請求我們的服務(wù)器。Laravel提供了一種防范這種攻擊的手段,即將自己的路由隱藏起來,只有帶有 @csrf 聲明的表單可以找得到接收表單信息的路由

            • 編輯 BlogController@store
            public function store(Request $request) //這里的 $request 是通過依賴注入的方法實例化的 Request 類的對象,包含的有所有請求的信息 {     // 我們只需要調(diào)用 Blog模型 的靜態(tài)方法 create() 插入 $request->post() 數(shù)據(jù)即可         $blog = Blog::create($request->post()); //改方法的返回值是新插入的數(shù)據(jù)生成的對象     // redirect() 頁面重定向         return redirect()->route('blog.show', $blog); // 這里我們將 $blog 作為參數(shù)請求 BlogController@show  }
            • 回到頁面,點擊提交,會發(fā)現(xiàn)報錯了,Laravel是一個極其注重安全的框架,用戶能修改哪些字段,必須要在模型文件中聲明,因此打開 appBlog.php 模型文件
            // 可填字段白名單 protected $fillable = [     'title', 'content'     ];
            • 再次提交,頁面一片空白,是因為我們的 BlogController@show 方法還沒有寫,不過你可以注意到地址欄已經(jīng)發(fā)生了改變。

            • 完成 show 方法

            public function show(Blog $blog) //這里已經(jīng)通過依賴注入的形式幫我們實例化了 $blog {     return view('blog.show', [             'blog' => $blog, //直接將$blog傳給視圖進行渲染     ]); }
            • 新建 ../blog/show.blade.php
            @extends('layouts.app')  @section('content') <div class="container">     <div class="row justify-content-center">            <div class="card">                  <div class="card-header">文章詳情</div>                    <div class="card-body">                          <h1 class="text-center">{{ $blog->title }}</h1>                            <p>發(fā)布時間<small>{{ $blog->created_at }}</small></p>                        <hr>                                 <p> {{ $blog->content }} </p>                         </div>                  </div>            </div>      </div>   @endsection
            • 刷新頁面,文章就顯示出來了。

            • 完成我們的編輯入口鏈接: 在 ../blog/index.blade.php & show.blade.php 中合理的位置添加一個編輯按鈕

            <a href="{{ route('blog.edit', $blog->id) }}" class="btn btn-info">編輯文章</a>
            • 完成 BlogController@edit
            public function edit(Blog $blog){     return view('blog.edit', [            'blog' => $blog,     ]); }
            • 完成視圖 重點:action聲明文章編號,根據(jù)路由要求action在表單中使用@method偽造請求動作類型
            @extends('layouts.app')  @section('content') <div class="container">     <div class="row justify-content-center">              <div class="card">                  <div class="card-header">編輯文章</div>                   <div class="card-body">    {{-- action需要聲明當(dāng)前編輯的文章編號$blog->id --}}                        <form method="POST" action="{{ route('blog.update', $blog->id) }}">        {{--  聲明 csrf 令牌  --}}           @csrf        {{--  偽造 PATCH 方法  --}}           @method("PATCH")                            <div class="form-group">                                <label for="title">文章標(biāo)題</label>                                  <input type="text" class="form-control" id="title" placeholder="請輸入文章標(biāo)題" name="title" value="{{ $blog->title }}">          </div>                           <div class="form-group">                                <label for="content">文章內(nèi)容</label>                                  <textarea id="content" cols="30" rows="10" class="form-control" name="content">{{ $blog->content }}</textarea>           </div>                               <p>發(fā)表于<small>{{ $blog->created_at }}</small></p>                 <p>修改于<small>{{ $blog->updated_at }}</small></p>                         <button class="btn btn-primary" type="submit">確認(rèn)編輯</button>            </form>                   </div>             </div>       </div> </div> @endsection
            • 完成 BlogController@update
            public function update(Request $request, Blog $blog){     $blog->update($request->post()); //調(diào)用 $blog對象->update(更新數(shù)據(jù)組成的數(shù)組) 更新      return redirect()->route('blog.show', $blog); }
            • 完成刪除功能 在 index.blade.php 和 show.blade.php 合理的位置插入刪除按鈕
            <a href="javascript:deleteConfirm({{ $blog->id }});" class="btn btn-danger btn-sm">刪除文章</a>                              {{--  因為刪除也需要 csrf 令牌認(rèn)證,所以弄個表單  --}} <form method="POST" action="{{ route('blog.destroy', $blog->id) }}" id="delete-blog-{{ $blog->id }}">     @csrf     {{--  這里偽造DELETE請求  --}}     @method("DELETE") </form>
            • “刪除文章” 按鈕其實是調(diào)用了一個 js 函數(shù),我們在 ../layousts/app.blade.php 中完成
            <script>     function deleteConfirm(id) {            var confirm = window.confirm('確認(rèn)要刪除這篇文章嗎?');               if(confirm === true) {             $("#delete-blog-" + id).submit(); //提交表單         }else {                 window.alert('你選擇不刪除!');         }     }  </script>
            • 完成 BlogController@delete 方法
            public function destroy(Blog $blog){     $blog->delete();     return redirect()->route('blog.index'); //跳轉(zhuǎn)到首頁   }
            • 增刪改查完成。
          • 完善和優(yōu)化

            • 首先無論增刪改查操作,成功后我們沒有任何提示,我們使用 session 閃存方法消息吧:

              • 新建組件視圖文件夾 /resources/views/components/
              • 然后新建一個組件視圖 _message.blade.php => 組件視圖我們都用_下劃線開頭
              <div class="container">     {{--  遍歷 success danger 這兩個我們等會會在 session->flash() 方法中設(shè)置的"key"  --}}     @foreach (['success', 'danger'] as $msg)         {{--  當(dāng)key存在的時候,證明我們給 session flash 閃存里面裝載了一次提示信息,那么就顯示提示信息  --}}         @if (session()->has($msg))              <div class="alert alert-{{ $msg }}">                 <ul>                     <li>{{ session()->get($msg) }}</li>                 </ul>             </div>         @endif     @endforeach </div>
              • 在 ../layousts/app.blade.php 中導(dǎo)入該組件 重點:@include 導(dǎo)入html片段
              {{--  在導(dǎo)航下面,內(nèi)容上面導(dǎo)入  --}}@include('components._message')
              • 編輯 BlogController 里的各種方法,在執(zhí)行成功某些方法時,頁面重定向前,裝載閃存。以刪除舉例
              $blog->delete(); session()->flash('success', '刪除文章成功!'); //裝載session閃存 return redirect()->route('blog.index');
            • 然后有個問題,就是在于,我們這是一個個人博客,所以只有我們自己可以對博客文章進行增刪改,而用戶只可以進行查看。因此我們需要:

              • 使用構(gòu)造函數(shù)調(diào)用 auth中間件 來排除沒有登陸的用戶查看文章詳情: 編輯 BlogController
              public function __construct(){   $this->middleware('auth')->except('index'); }
              • 在 新增create、編輯edit、和刪除方法中加入一次用戶認(rèn)證,以 create 方法舉例
              // 因為比較簡單,所以我們不用Policy進行認(rèn)證,我會在以后的教程里面教大家如何使用Policy策略進行權(quán)限認(rèn)證 // 這里我們就使用判斷當(dāng)前用戶在數(shù)據(jù)表中信息的主鍵id是不是1即可(因為我們在Seeder里面把編號為1的用戶設(shè)置為了可用的管理員賬號) // 1、在代碼開頭引用 Auth // 2、在方法內(nèi)先判斷一下是不是 1號用戶 if(Auth::user()->id != 1) {  // Auth::user() 獲取當(dāng)前用戶信息 -> id獲取屬性id(主鍵)     session()->flash('danger', '抱歉,只有博主才可以新增文章!');        return redirect()->back(); }
          • 針對博客的增刪改查在這里就結(jié)束了。

          第三階段總結(jié)

          • 我們使用命令創(chuàng)建了一個 “資源控制器”
          • 我們在 /routes/web.php 定義了一條資源路由
          • 我們使用 BlogController 中的7個方法完成了對 博客文章 的 CURD(增刪改查)操作。
          • 我們優(yōu)化了一下體驗,使用 session()->flash() 裝載閃存信息,用一個組件html片段加載信息,最后用@include()在模板上加載這個html組件。
          • 我們最后增加了一個簡單的權(quán)限認(rèn)證,判斷進行增刪改的用戶是不是管理員,不是管理員則不允許操作,直接裝載一條錯誤提示閃存,然后返回。

          第四階段 評論功能

          • 新建一個評論資源控制器 php artisan make:controller CommentController --model=Commment
          • 新增一條資源路由,但只支持發(fā)表 /routes/web.php Route::resource('comment', 'CommentController', ['only' => 'store']);

          其實我們可以定義一條 Route::post('comment', 'CommentController@store') 路由,但是為什么要寫資源路由呢?因為我要告訴你資源路由可以用 ['onlu'=>'操作'] 讓其只支持一種操作:)

          • 在文章詳情頁面下方增加一個表單 show.blade.php
          <form method="POST" action="{{ route('comment.store') }}">     @csrf         <input type="hidden" name="user_id" value="{{ Auth::user()->id }}">           <input type="hidden" name="blog_id" value="{{ $blog->id }}">           <div class="form-group">                <label for="content"></label>                <textarea id="content" class="form-control" cols="30" rows="10" name="content">您對這篇文章有什么看法呢?</textarea>           </div>          <button class="btn btn-primary" type="submit">發(fā)表評論</button>  </form>
          • 編輯 CommentController@store
          public function store(Request $request){     Comment::create($request->post());     session()->flash('success', '評論成功!');     return redirect()->back(); }
          • 提交評論出錯了,又忘了寫可填字段白名單,編輯模型 appComment
          protected $fillable = [    'content', 'user_id',     'blog_id'  ];
          • 展示評論
            • 首先我們需要確定 Blog 和 Comment 的關(guān)系 => Blog 1:n Comment “一篇博客有多個評論”
            • 我們來綁定他們的關(guān)系
              • appBlog.php
              // 綁定1:n關(guān)系 public function comments() {    return $this->hasMany('AppComment'); // 1 hasMany n  }
              • appComment.php
              public function blog() {     return $this->belongsTo('AppBlog'); // n belongsTo 1  }
            • 然后通過他們的關(guān)系,我們可以在 BlogController@show 方法中調(diào)用 $blog->comments 來獲取屬于這篇文章的評論
            // 查詢評論 $comments = $blog->comments; // 視圖渲染 return view('blog.show', [     'blog' => $blog,         'comments' => $comments, //把評論也傳過去   ]);
            • 在視圖層遍歷評論 show.blade.php
            <h3>評論</h3> <ul>     @foreach ($comments as $comment)         <li><small>{{ $comment->userName() }} 評論說:</small>“ {{ $comment->content }} ”</li>     @endforeach</ul>
            • 注意我們調(diào)用了 $comment->userName() 方法,現(xiàn)在沒有,所以我們再 appComment.php 模型中完成
            use AppUser; //引用模型 // 根據(jù) user_id 獲取用戶名 public function userName() {     return User::find($this->user_id)->name; //這里通過當(dāng)前對象的 user_id 獲取 user對象, 然后指向->name屬性  }
          • 評論驗證

          在博客中,我們就沒有使用驗證,那是因為項目定位是一個個人博客,能夠操縱博客增刪改的只有我們自己。而評論則是只要有人注冊賬號,就可以評論了,所以我們應(yīng)該對評論進行一些校驗以防惡意攻擊。

          • 新建一個請求Request php artisan make:request CommentRequest

          • 新建的請求位于 appHttpRequests 下,編輯 CommentRequest

            // 1、 開啟授權(quán) public function authorize(){     return true; //如果返回false則所有請求都無法生效,會告訴你沒有授權(quán)(其實在這里面我們是需要去進行判斷的,但是這里的邏輯很簡單:只有登陸才能查看文章詳情,才能看到文章詳情下面發(fā)表評論的表單,才能發(fā)表評論。)所以我們這里直接 return true;}// 2、 編輯規(guī)則public function rules(){    return [        'content' => 'required|min:15|max:100', //這里你可以定義規(guī)則我的是:必填、最少15字、最多100字     ]; }
            • 在 CommentController@store 方法的參數(shù)列表中通過 CommentRequest 構(gòu)造 $request, 自動完成校驗
            public function store(CommentRequest $request) // 這將 Request 改成 CommentRequest 就會自動調(diào)用 CommentRequest@rules 來校驗請求的數(shù)據(jù)了 {     Comment::create($request->post());     session()->flash('success', '評論成功!');         return redirect()->back(); }
            • 優(yōu)化視圖 show.blade.php
            {{-- 樣式里面加一個判斷,判斷是否有關(guān)于content的錯誤有的話給樣式給文本域加一個紅邊邊 --}} <textarea id="content" class="form-control {{ $errors->has('content') ? ' is-invalid' : '' }}" cols="30" rows="10" name="content">你對文章有什么看法呢?</textarea>  {{-- 如果有錯誤,再顯示一個小的錯誤提示信息 --}} @if ($errors->has('content'))     <span class="invalid-feedback">         <strong>{{ $errors->first('content') }}</strong>     </span> @endif
            • 此時提交表單,左下角會提醒你 “內(nèi)容不能為空”,如果你想改“內(nèi)容兩個字”,可以打開 /resources/lang/zh-CN/validation.php
            'content' => '內(nèi)容', //這里就是配置字段的中文名,你把它改成評論即可。
            • 有時候文章過長,導(dǎo)致提交了,往下拉才看得到文本域變紅,所以我們需要新建一個錯誤組件../components/_error.blade.php
            {{--  判斷是否有錯誤  --}} @if (count($errors) > 0)     <div class="alert alert-danger">         {{--  遍歷所有錯誤  --}}         @foreach ($errors->all() as $error)                     <ul>                 {{--  打印錯誤  --}}                                 <li> {{ $error }}</li>                       </ul>         @endforeach          </div>
          •  @endif
            • 然后在 show.blade.php 中引用 @include('components._error')

          第四階段總結(jié)

          • 我們依然創(chuàng)建資源控制器,但是在路由中使用['only'=>'store'] 讓資源路由只暴露指向 CommentController@store 的路由
          • 我們學(xué)會了通過hasMany() & belongsTo()綁定模型之間的1:n關(guān)系。然后通過文章->評論+s;的方法直接獲取了屬于某篇文章的所有評論。
          • 我們學(xué)會了創(chuàng)建請求Request,并且在它的內(nèi)部配置驗證規(guī)則,在控制器層中通過依賴注入的形式驗證數(shù)據(jù)。
          • 一旦表單提交的數(shù)據(jù)不符合 Request@rules Laravel會自動幫我們生成一個叫 $errors 的數(shù)組,它存放著所有的錯誤信息, 我們在視圖上通過判斷它是否有 content 字段來判斷是否是表單提交的評論有問題,然后修改文本域的樣式并且在下方用一個小的提示span顯示錯誤提示信息
          • 錯誤提示信息顯示的是“內(nèi)容 怎么怎么樣…”,我們想把“內(nèi)容”改成評論只需要修改中文語言包下的validation.php中的'content'字段的別名即可。

          第五階段 最后總結(jié)

          • 想讓項目上線,也許你需要
            • 更好看的html排版
            • 重新執(zhí)行一次 php artisan migrate:rollback
            • 權(quán)限認(rèn)證太水了。你需要學(xué)習(xí)使用 Policy 來進行更安全和全面的權(quán)限認(rèn)證。

          也許文字很多,但是真正的代碼可能只有不到100行,你如果熟練掌握,可能不需要30分鐘,甚至10分鐘,你就可以開發(fā)出這樣一個博客了。

          • 視圖方面
            • 我們有通過 auth 生成的模板
            • Laravel 自帶的 bootstrap4 + jquery
            • 所以我們解決了css和js的問題 => 我們只是寫了一個 “確認(rèn)刪除” 的前端代碼
          • 數(shù)據(jù)庫方面
            • 我們有 /database/ 下提供的 3套解決方案 Migration / Factory / Seeder 來幫我們解決數(shù)據(jù)庫管理的問題
            • 因為上面的解決方案,我們甚至只寫了 建用戶、建表、授權(quán)3條 數(shù)據(jù)庫操作語句。
          • 路由方面
            • Auth 自動幫我們生成了用戶操作相關(guān)路由
            • 我們使用資源路由來映射一個 CURD 控制器
          • 控制器和模型方面,通過命令生成的所有類文件,都幾乎幫我們寫好了,我們只需要完成里面的邏輯。
          • 當(dāng)然,我們還有 Request 請求認(rèn)證 Policy 策略控制等等一些列的特性沒有學(xué)習(xí),我們也只使用了一次composer,其實在開發(fā)Laravel時,我們還可以使用非常多的,支持Laravel的,完善的輪子可以利用。

          現(xiàn)在請告訴我,它是否配得上 “優(yōu)雅” 的兩字?:)

          希望大家可以喜歡、學(xué)習(xí)和推廣Laravel。如果您愿意付出比學(xué)習(xí)thinkphp5多0.01分的努力,我想這個框架是非常簡單的。

          如果您依然討厭它的龐大,我向您推薦 Lumen 框架。

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號