在寫 SEO/SMO 相關程式碼的時候,我發現很多使用 laravel/php 的開發者會在 layout 相關檔案這樣寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @if (isset($product)) <title>{{ $product->name }}產品資訊</title> <meta name="description" content="{{ $product->description }}">
<meta property='og:title' content="{{ $product->name }}產品資訊"> <meta property='og:description' content="{{ $product->description }}"> @elseif (isset($category)) <title>{{ $category->name }}類別資訊</title> <meta name="description" content="{{ $category->description }}">
<meta property='og:title' content="{{ $category->name }}類別資訊"> <meta property='og:description' content="{{ $category->description }}"> @elseif (isset($user)) <title>{{ $user->name }}用戶資訊</title> <meta name="description" content="{{ $user->description }}">
<meta property='og:title' content="{{ $user->name }}用戶資訊"> <meta property='og:description' content="{{ $user->description }}"> @else <title>歡迎來到 blah 購物網站!</title> <meta name="description" content="亞洲最優質購物網站!">
<meta property='og:title' content="歡迎來到 blah 購物網站!"> <meta property='og:description' content="亞洲最優質購物網站!"> @endif
|
這種寫法對於小網站還行,網站稍大就會發現幾個明顯的問題
- layout 檔案打開,想要看個排版,卻要先看上百行的這種 seo/smo 程式碼
- 有時會希望某個 controller 底下的不同 function 回傳不同的 seo/smo meta tag,希望可以在 controller 內設定
- 有時會希望某個 controller 底下如果什麼都沒設定,預設也不要傳跟首頁一樣的 meta tag,讓 seo/smo 至少可分出大方向
古典的 singleton pattern 被許多開發者忽視許久。其實在這邊可以派上用場。
以 laravel 為例,以下是我在所有專案都會使用的程式碼
layout.blade.php
1 2 3 4 5 6 7 8 9 10 11
| <title>{{ AppCore::getOpenGraphTitle() }}</title> <meta name="description" content="{{ AppCore::getOpenGraphDescription() }}">
<meta property='og:title' content="{{ AppCore::getOpenGraphTitle() }}"> <meta property='og:description' content="{{ AppCore::getOpenGraphDescription() }}"> <meta property='og:image' content="{{ AppCore::getOpenGraphImage() }}">
<meta name="twitter:card" content="photo" /> <meta name="twitter:title" content="{{ AppCore::getOpenGraphTitle() }}" /> <meta name="twitter:description" content="{{ AppCore::getOpenGraphDescription() }}" /> <meta name="twitter:image" content="{{ AppCore::getOpenGraphImage() }}" />
|
config/app.php
1 2 3 4
| 'aliases' => [ ... 'AppCore' => App\AppCoreFacade::class, ],
|
app/AppCoreFacade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php
namespace App;
use Illuminate\Support\Facades\Facade; use App\AppCore as RealAppCore;
class AppCoreFacade extends Facade { protected static function getFacadeAccessor() { return RealAppCore::class; } }
|
app/AppCore.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| <?php
namespace App;
class AppCore { protected $openGraphTitle = null;
protected $openGraphDescription = null;
protected $openGraphImage = null;
function setOpenGraphTitle($title) { $this->openGraphTitle = $title; }
function setOpenGraphDescription($description) { $this->openGraphDescription = $description; }
function setOpenGraphImage($image) { $this->openGraphImage = $image; }
function getOpenGraphTitle() { if ($this->openGraphTitle) return $this->openGraphTitle;
return '歡迎來到 blah 購物網站!'; }
function getOpenGraphDescription() { if ($this->openGraphDescription) return $this->openGraphDescription;
return '亞洲最優質購物網站!'; }
function getOpenGraphImage() { if ($this->openGraphImage) return $this->openGraphImage;
return url('/ms-icon-310x310.png'); } }
|
如此一來,seo/smo 的設定就變成在各個 controller 內決定了!
ProductController.php
1 2 3 4 5 6 7
| function viewProduct(Request $request) { AppCore::setOpenGraphTitle($product->name . '產品資訊');
AppCore::setOpenGraphDescription($product->description); ... }
|
可以在不同的 controller 內,寫各種複雜的判斷邏輯都沒關係!
也可以在 constructor 內設定適合的內容,對相關頁面做出初步的 seo/smo,接著一層一層覆蓋、做出更精準的 seo/smo 即可!
CategoryController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class CategoryController extends Controller { function __construct() { AppCore::setOpenGraphTitle('分類瀏覽 - blah 購物網');
AppCore::setOpenGraphDescription('更方便的搜尋商品'); }
function viewCategory(Request $request) { AppCore::setOpenGraphTitle($category->name);
AppCore::setOpenGraphDescription($category->description);
... }
function viewCategoryTag(Request $request) { // even I didn't setup the seo/smo, I still have better tags // rather than just return homepage tags!
... } }
|
結語
Singleton Pattern 如果濫用,會出現一些像是 global state 的糟糕情況,讓程式碼難以維護。
但是 Singleton Pattern 在建構網站的時候有很多很棒的使用場景,本文的例子只是一個起點,你一定會找到其他也很適合的使用場景。