到 YouTube 搜尋 Laravel 教學,找到哥布林老師的教學影片
我的 Laravel 學習是從書籍開始,到知名書店網站用「Laravel」為關鍵字搜尋,找到一兩本發行時間較近的書籍後下單購買,然後一邊看書一邊累積相關知識。學習一段時間後,我想透過「專案實做」的方式驗證自己所累積的知識是否足夠專案所需,如果不夠該怎麼補足或加強。
因為娛樂與學習,我經常在 YouTube 網站搜尋感興趣的影片。在搜尋「用 Laravel 製作部落格」的影片中發現哥布林老師的【Laravel實戰】部落格從零開始實作攻略 #by Voyager ,從中看到 BootstrapMade 網站提供眾多專業設計的佈景主題下載,付費版本具備更多功能及售後支援。
哥布林老師的影片中使用的是 Moderna 這個主題的部落格頁面作為教學示範,比較過 BootstrapMade 網站上其他主題後,覺得 Moderna 的設計調性跟自己比較契合,所以使用這個主題資源給 larablog 使用。
Moderna 主題提供 Bootstrap 4 及 5 版本免費下載,larablog 使用的是後者。
複製前端資源檔案至 /public
Laravel 專案預設的前台頁面路徑是 public
,與前端有關的圖片、CSS 樣式表、JavaScript 腳本檔等檔案應放置在此。將下載的主題壓縮檔解壓縮後將 assets
資料夾內所有檔案/資料夾複製到專案 public
資料夾內。
Blade template 位置:resources/views
Moderna 主題部落格樣式頁面是 blog.html
(部落格首頁)與 blog-single.html
(文章全文),將這兩個檔案複製到專案resources/views
資料夾內,更名為 home.blade.php
(部落格首頁)與 blog_page.blade.php
。
命名方式建議以容易識別為原則,與首頁有關的檔案通常會命名為 home 或 index,副檔名需為 .blade.php。
routes/web.php
routes
資料夾中的 web.php
是網站路由檔案,在這裡看到存取網頁根目錄時會回傳 welcome
這個 View 檔案,指向的是 resources/views
資料夾內的 welcome.blade.php
。
將這段程式碼複製後在下方貼上,然後將原有程式碼註記使其不執行,更改為自訂的首頁檔案名後存檔,之後在瀏覽器輸入網址就會改由自訂的首頁檔案顯示。
//Route::get('/', function () {
// return view('welcome');
//});
Route::get('/', function () {
return view('home');
});
頁面跑版?很正常,修改資源引用路徑
上圖是 Moderna 的部落格頁面(blog.html)示範,下面的圖片是我將頁面更名為 Blame template 後(home.blade.php)在瀏覽器顯示的畫面。
範例圖不見了,樣式檔也沒套用到,難道我複製錯了嗎?
複製的路徑是正確的,只是引用資源的位置要修改。
修正資源引用路徑,改以 asset() 包含
打開 /resources/views/home.blade.php
,在第 21 至第 31 行是 CSS 樣式表的引用敘述,內容是這樣的:
<!-- Vendor CSS Files -->
<link href="assets/vendor/animate.css/animate.min.css" rel="stylesheet">
<link href="assets/vendor/aos/aos.css" rel="stylesheet">
<link href="assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/vendor/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
<link href="assets/vendor/boxicons/css/boxicons.min.css" rel="stylesheet">
<link href="assets/vendor/glightbox/css/glightbox.min.css" rel="stylesheet">
<link href="assets/vendor/swiper/swiper-bundle.min.css" rel="stylesheet">
<!-- Template Main CSS File -->
<link href="assets/css/style.css" rel="stylesheet">
在此看到引用的 CSS 樣式表檔案位於 asset 資料夾下,複製到 Laravel 專案後因為資料夾路徑不同了無法引用,才變成上面圖片的樣子。
那麼就動手修正吧:在 Blade template 中呼叫變數需使用兩組大括弧({{ }}
)包含,接著使用 asset()
取用 public
資料夾內檔案。
所以上述的樣式檔引用路徑會更改為以下內容:
<!-- Vendor CSS Files -->
<link href="{{ asset('vendor/animate.css/animate.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/aos/aos.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/bootstrap-icons/bootstrap-icons.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/boxicons/css/boxicons.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/glightbox/css/glightbox.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/swiper/swiper-bundle.min.css') }}" rel="stylesheet">
<!-- Template Main CSS File -->
<link href="{{ asset('css/style.css') }}" rel="stylesheet">
圖片(副檔名為 .jpg)與 JavaScript 檔案(副檔名為 .js)也以同樣的方式變更引用路徑,存檔後瀏覽器重新讀取頁面後就會看到正常顯示的畫面。
檢視頁面原始碼,確認頁面區塊與 HTML 原始碼對應關係
解決了資源檔案引用的問題後,我回到 home.blade.php 的編輯畫面,查看 HTML 碼段落與網頁畫面的對應關係:
1 - 39 行定義 HTML 頁面至 (head 標籤結束),包含:
- 5、6、9、10 行:meta 資訊。
- 8 行:頁面標題。
- 12 - 14 行:網站圖標(favicon)。
- 21 - 31 行:CSS 樣式檔引用。
41 行開始是頁面本體(body)敘述,包含:
- 47 - 51 行:網站圖標(文字或圖形)。
- 53 - 82 行:網站選單。
(
- 89 - 103 行:頁面標題及網頁路徑(麵包屑)。
(
- 105 - 263 行:部落格文章。
- 265 - 271 行:頁面分頁條。
- 275 - 357 行:畫面右邊的側邊欄:搜尋、分類項目、近期文章、文章標籤。
362 行開始是頁尾部分,包含:
- 365 - 379 行:電子報訂閱表單。
- 381 - 433 行:常用連結(選單項目)、聯絡資訊、關於本網站說明。
- 435 - 446 行:版權宣告。
- 449 - 450 行:回到頁首圖標
- 452 - 463 行:JavaScript 檔案引用
定義切版依據:依照共用程度或功能區塊
接下來依照「共用程度」或是「功能運作」,將 HTML 碼切割成不同的 Blade template 檔案儲存,主要有兩個目的:
- 如果某個區塊是每個頁面會用到的(樣式檔引用、網站選單,頁尾的常用連結、版權宣告等),獨立成單一檔案後只要呼叫該檔案顯示即可,可以減少重複內容,修改後可以整體套用。
- 功能運作區塊獨立成單一檔案後可以透過引入與否做到功能開關。
子資料夾內檔案
Blade template 檔案存放路徑在專案 resoureces/views
,可以透過建立資料夾的方式管理不同用途的 Blade template 檔案。當需要引用子資料夾中的檔案時使用 資料夾.檔案
的方式呼叫。
//存取網站根目錄時顯示「frontend」資料夾中的「index.blade.php」檔案。
Route::get('/', function () {
return view('frontend.index');
});
共用區塊獨立成 Blade template 檔案
「CSS 樣式表及 JavaScript 檔案」、「網站選單」及「頁尾常用連結及版權宣告」是每個頁面都會用到的,所以將這三個部分的 HTML 碼獨立出來成為 Blade template 檔案,之後在 home.blade.php
引入,驗證是否正常顯示。
我在/resources/views
資料夾底下建立 layouts
存放上述區塊獨立出來的 Blade template 檔案,分別為:
- master.blade.php:網站頁面主版,存放 至 內容(包含CSS 樣式)及 JavaScript 檔案引入。
- header.blade.php:網頁路徑、網站圖標(文字或圖片)及網站選單。
- footer.blade.php:頁尾常用連結及版權宣告。
獨立後的 Blade template 檔案再依需要對內容進行增減,以下是檔案說明:
layouts/master.blade.php
- 第 2 行:語言改成漢語(臺灣)。
<html lang="zh-Hant-TW">
- 第 8 - 16 行:移除 meta 關鍵字敘述(Google 已不再索引),新增 Open Graph(開放社交關係圖)資訊讓網站頁面在社群網站分享時以自己所希望的方式呈現。
參考資料:Open Graph 介紹:讓網站在社群上被漂亮分享,就靠 OG 標籤!
內容中使用「@yield」表示該項目資訊交由之後頁面(其他 Blade template,或資料庫內容)呈現,
meta name="og:description"
內容與meta name="description"
共用。
<!-- meta and open graph information -->
<meta name="description" content="@yield('meta_description')">
<meta name="og:title" content="@yield('title')" />
<meta name="og:type" content="article" />
<meta name="og:image" content="@yield('cover_image')" />
<meta name="og:url" content="@yield('url')" />
<meta name="og:site_name" content="從零開始的 Laravel 部落格建置日誌" />
<meta name="og:description" content="@yield('meta_description')" />
<meta name="robots" content="index, nofollow" />
- 第 18 行:頁面標題。標題內容一樣由之後頁面決定(每個頁面的標題都不同),再加上網站名稱。
<title>@yield('title') - 從零開始的 Laravel 部落格建置日誌</title>
- 第 20 - 22 行:指定網站的瀏覽器圖示(favicon),「apple-touch-icon」部分是給 apple 設備設定「加入主畫面」時顯示的圖示。
<!-- Favicons -->
<link href="{{ asset('img/favicon.png') }}" rel="icon">
<link href="{{ asset('img/apple-touch-icon.png') }}" rel="apple-touch-icon">
- 第 24 - 39 行:導入 Google 字型、CSS 動畫和圖示、以及主樣式。
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i|Roboto:300,300i,400,400i,500,500i,700,700i&display=swap" rel="stylesheet">
<!-- Vendor CSS Files -->
<link href="{{ asset('vendor/animate.css/animate.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/aos/aos.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/bootstrap-icons/bootstrap-icons.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/boxicons/css/boxicons.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/glightbox/css/glightbox.min.css') }}" rel="stylesheet">
<link href="{{ asset('vendor/swiper/swiper-bundle.min.css') }}" rel="stylesheet">
<!-- Template Main CSS File -->
<link href="{{ asset('css/style.css') }}" rel="stylesheet">
- 第 51 行:引入
layouts/header.blade.php
:網站圖標(文字或圖片)及網站選單、網頁路徑 。
<!-- ======= Header ======= -->
@include('layouts.header')
<!-- End Header -->
- 第 58 行:頁面左方主要內容顯示區,由之後的頁面承接。
<!-- 頁面主內容 -->
@yield('content')
<!-- 頁面主內容 -->
- 第 65 行:引入
layouts/footer.blade.php
:顯示頁尾區塊。
<!-- ======= Footer ======= -->
@include('layouts.footer')
<!-- End Footer -->
- 第 68 行:頁面右下方的箭頭圖示,點選後回到頁面最上方。
<a href="#" class="back-to-top d-flex align-items-center justify-content-center">
<i class="bi bi-arrow-up-short"></i>
</a>
- 第 71-82 行:引入 JavaScript 檔案。
<!-- Vendor JS Files -->
<script src="{{ asset('vendor/aos/aos.js') }}"></script>
<script src="{{ asset('vendor/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<script src="{{ asset('vendor/glightbox/js/glightbox.min.js') }}"></script>
<script src="{{ asset('vendor/isotope-layout/isotope.pkgd.min.js') }}"></script>
<script src="{{ asset('vendor/php-email-form/validate.js') }}"></script>
<script src="{{ asset('vendor/purecounter/purecounter.js') }}"></script>
<script src="{{ asset('vendor/swiper/swiper-bundle.min.js') }}"></script>
<script src="{{ asset('vendor/waypoints/noframework.waypoints.js') }}"></script>
<!-- Template Main JS File -->
<script src="{{ asset('js/main.js') }}"></script>
layouts/header.blade.php
- 第 5 - 9 行:網站圖標,使用文字(第 6 行)或是圖片(第 7 - 8 行)擇一。
<div class="logo">
<h1 class="text-light"><a href="index.html"><span>Moderna</span></a></h1>
<!-- Uncomment below if you prefer to use an image logo -->
<!-- <a href="index.html"><img src="assets/img/logo.png" alt="" class="img-fluid"></a>-->
</div>
- 第 11 - 40 行:網站選單範例,提供第一至第三層選單的呈現語法,第 39 行是行動版頁面會出現的漢堡選單。選單項目可透過 Voyager 製作、產生。
<nav id="navbar" class="navbar">
<ul>
<li><a class="" href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="services.html">Services</a></li>
<li><a href="portfolio.html">Portfolio</a></li>
<li><a href="team.html">Team</a></li>
<li><a class="active" href="blog.html">Blog</a></li>
<li class="dropdown"><a href="#"><span>Drop Down</span> <i class="bi bi-chevron-down"></i></a>
<ul>
<li><a href="#">Drop Down 1</a></li>
<li class="dropdown"><a href="#"><span>Deep Drop Down</span>
<i class="bi bi-chevron-right"></i></a>
<ul>
<li><a href="#">Deep Drop Down 1</a></li>
<li><a href="#">Deep Drop Down 2</a></li>
<li><a href="#">Deep Drop Down 3</a></li>
<li><a href="#">Deep Drop Down 4</a></li>
<li><a href="#">Deep Drop Down 5</a></li>
</ul>
</li>
<li><a href="#">Drop Down 2</a></li>
<li><a href="#">Drop Down 3</a></li>
<li><a href="#">Drop Down 4</a></li>
</ul>
</li>
<li><a href="contact.html">Contact Us</a></li>
</ul>
<i class="bi bi-list mobile-nav-toggle"></i>
</nav><!-- .navbar -->
layouts/footer.blade.php
規劃上沒有「電子報訂閱」功能,所以將相關區塊刪除。
- 第 7 - 16 行:頁尾左方區塊一,預定顯示網站選單(可透過 Voyager 產生後指定)。
<div class="col-lg-3 col-md-6 footer-links">
<h4>Useful Links</h4>
<ul>
<li><i class="bx bx-chevron-right"></i> <a href="#">Home</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">About us</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">Services</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">Terms of service</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">Privacy policy</a></li>
</ul>
</div>
- 第 18 - 27 行:頁尾左方區塊二,預定顯示網站使用條款及隱私權規定。(選單項目可透過 Voyager 產生後指定)
<div class="col-lg-3 col-md-6 footer-links">
<h4>Our Services</h4>
<ul>
<li><i class="bx bx-chevron-right"></i> <a href="#">Web Design</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">Web Development</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">Product Management</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">Marketing</a></li>
<li><i class="bx bx-chevron-right"></i> <a href="#">Graphic Design</a></li>
</ul>
</div>
- 第 29 - 51 行:頁尾左方區塊三及區塊四,預計將區塊三的樣式從 col-lg-3 更改 col-lg-6,再將區塊四敘述刪除後合併為單一區塊,填入網站簡介。 46 - 49 行是社群網站圖示,可參考 Bootstrap Icons 網站更換成需要的樣式。
<div class="col-lg-3 col-md-6 footer-contact">
<h4>Contact Us</h4>
<p>
A108 Adam Street <br>
New York, NY 535022<br>
United States <br><br>
<strong>Phone:</strong> +1 5589 55488 55<br>
<strong>Email:</strong> info@example.com<br>
</p>
</div>
<div class="col-lg-3 col-md-6 footer-info">
<h3>About Moderna</h3>
<p>Cras fermentum odio eu feugiat lide par naso tierra. Justo eget nada terra videa magna derita
valies darta donna mare fermentum iaculis eu non diam phasellus.</p>
<div class="social-links mt-3">
<a href="#" class="twitter"><i class="bx bxl-twitter"></i></a>
<a href="#" class="facebook"><i class="bx bxl-facebook"></i></a>
<a href="#" class="instagram"><i class="bx bxl-instagram"></i></a>
<a href="#" class="linkedin"><i class="bx bxl-linkedin"></i></a>
</div>
</div>
- 第 57 - 68 行:網站版權宣告及設計來源。
<div class="container">
<div class="copyright">
© Copyright <strong><span>Moderna</span></strong>. All Rights Reserved
</div>
<div class="credits">
<!-- All the links in the footer should remain intact. -->
<!-- You can delete the links only if you purchased the pro version. -->
<!-- Licensing information: https://bootstrapmade.com/license/ -->
<!-- Purchase the pro version with working PHP/AJAX contact form: https://bootstrapmade.com/free-bootstrap-template-corporate-moderna/ -->
Designed by <a href="https://bootstrapmade.com/">BootstrapMade</a>
</div>
</div>
將分離後的 Blade template 檔案引用進來
將共用區塊分離後的 head.php
內容行數減少三分之一,在維護上輕鬆許多。以下是重點說明:
@extends('layouts.master')
@section('meta_description', '')
@section('title', '首頁')
@section('cover_image', '')
@section('url', url()->full())
- 第 1 行:繼承
layouts/master.blade.php
內容,引入頁面規劃主版。 - 第 2 行:補上
layouts/master.blade.php
中@yield('meta_description')
資訊。 - 第 3 行:補上
layouts/master.blade.php
中@yield('title')
資訊。 - 第 4 行:補上
layouts/master.blade.php
中@yield('cover_image')
資訊。 - 第 5 行:補上
layouts/master.blade.php
中@yield('url')
資訊。 - 第 6 - 261 行:補上
layouts/master.blade.php
中@yield('content')
資訊,以@section('content')
開頭@endsection
結尾,中間是頁面主內容。 第 167 - 173 行是頁面分頁條,這裡會透過套件運作自動分頁。
<div class="blog-pagination">
<ul class="justify-content-center">
<li><a href="#">1</a></li>
<li class="active"><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</div>
將側邊欄各功能區塊獨立成 Blade template 檔案
部落格畫面右方的側邊欄有「搜尋」、「文章分類」、「最近貼文」以及「標籤」四個功能區塊,以先前將重複內容獨立成 Blade template 檔案的相同流程,將功能區塊再分離成獨立 Blade template 檔案引入,一方面再減少 home.php 的內容長度,再來可以做成功能開關,在顯示使用條款這類不需要側邊欄的情況就不需引入。
以下是獨立出來的各區塊 Blade template 檔案:
- 搜尋:widgets/search.blade.php
- 文章分類:widgets/categories.blade.php
- 最近貼文:widgets/recent_posts.blade.php
- 標籤:widgets/tags.blade.php
內容分離後的側邊欄程式碼會是以下內容:
<div class="col-lg-4">
<div class="sidebar">
<!-- 搜尋表單 -->
@include('widgets.search')
<!-- 文章分類 -->
@include('widgets.categories')
<!-- 近期文章 -->
@include('widgets.recent_posts')
<!-- 標籤雲 -->
@include('widgets.tags')
</div><!-- End sidebar -->
</div><!-- End blog sidebar -->
結語
網站的基本頁面透過切版分離成單獨的 Blade template 檔案,接下來透過 Controller 與 Model 的協同合作,將 Blade template 中的範例資料改換成程式運作的動態產出。