顯示具有 Laravel 標籤的文章。 顯示所有文章
顯示具有 Laravel 標籤的文章。 顯示所有文章

2025/12/27

Setting Up Trusted SSL for Laravel Sail and Docker Environments

平常在本機開發時對應的通常是 http,但如果某些特殊原因,想要使用 https 的話,沒有憑證會看到令人礙眼的警告內容,今天紀錄一下怎麼可以在本地使用自簽憑證讓討厭的 ssl 警告消失,有兩種我目前開發的常用情境:

  1. 用 docker 自架 php + nginx
  2. 使用 laravel sail

安裝使用 mkcert

1. 安裝 mkcert

我們使用 Scoop 作為 Windows 的套件管理工具,打開 PowerShell,執行以下指令:

scoop install mkcert

2. 建立本地 CA (憑證授權單位)

這一步最為關鍵,它會讓你的 Windows 系統信任由 mkcert 簽發的憑證:

mkcert -install

注意:若彈出安全性警告,請點擊「是」。

套用自簽憑證

自架範例

1. 專案結構

├── docker/
│   ├── conf.d/
│   │   └── default.conf  # Nginx 設定
│   └── ssl/              # 存放 mkcert 憑證
├── public/
│   └── index.php             # 測試檔案
└── compose.yml           # Docker 配置

2. 產生憑證

# 建立目錄
mkdir -p docker/nginx/ssl

# 使用 mkcert 生成針對 demo.test 的憑證
# 檔案會直接產生在 docker/nginx/ssl 內
cd docker/nginx/ssl
mkcert demo.test

3. default.conf 配置

server {
    listen 80;
    server_name demo.test;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name demo.test;

    ssl_certificate /etc/nginx/ssl/demo.test.pem;
    ssl_certificate_key /etc/nginx/ssl/demo.test-key.pem;

    root /var/www/html/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

4. compose.yml

services:
  php:
    image: php:8.4-fpm
    volumes:
      - .:/var/www/html

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - .:/var/www/html
      - ./docker/conf.d:/etc/nginx/conf.d
      - ./docker/nginx/ssl:/etc/nginx/ssl
    depends_on:
      - php

sail 範例

1. 生成專屬憑證

切換到你的 Laravel 專案根目錄,建立存放憑證的資料夾並產生檔案:

mkdir -p docker/ssl
cd docker/ssl
mkcert demo.test

2. 配置 Docker 環境

我們將使用 Caddy 作為反向代理伺服器。
修改 docker-compose.yml
找到 services 區塊,加入 caddy 服務,並調整 laravel.test 的埠號對應:

services:
    laravel.test:
        # ... (其餘配置保持不變)
        ports:
            - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' # 移除 80 埠映射,改由 Caddy 處理
        networks:
            - sail

    caddy:
        image: caddy:latest
        restart: unless-stopped
        ports:
            - "80:80"
            - "443:443"
        volumes:
            - ./Caddyfile:/etc/caddy/Caddyfile
            - ./docker/ssl:/etc/caddy/certs
            - sail-caddy-data:/data
            - sail-caddy-config:/config
        networks:
            - sail
        depends_on:
            - laravel.test

# 記得在最下方的 volumes 區塊新增
volumes:
    sail-caddy-data:
        driver: local
    sail-caddy-config:
        driver: local

3. 建立 Caddyfile

在專案根目錄建立 Caddyfile

demo.test {
    reverse_proxy laravel.test:80
    tls /etc/caddy/certs/demo.test.pem /etc/caddy/certs/demo.test-key.pem
}

4. 調整應用程式設定

1. 更新 .env

確保 Laravel 知道目前的通訊協定:

APP_URL=https://demo.test
2. 讓 Laravel 信任 Proxy

修改 bootstrap/app.php,讓 route() 函式能正確生成 https 連結:

->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(at: '*');
})
3. 配置 Vite (若有使用)

修改 vite.config.js 以支援 HMR (熱重載) 透過 HTTPS 運作:

import fs from 'fs';

export default defineConfig({
    server: {
        host: '0.0.0.0',
        hmr: { host: 'demo.test' },
        https: {
            key: fs.readFileSync('./docker/ssl/demo.test-key.pem'),
            cert: fs.readFileSync('./docker/ssl/demo.test.pem'),
        },
    },
    // ...
});

2025/10/08

Laravel Sail On WSL

緣由

我開發 PHP,不管是純 PHP 或 Laravel 都很喜歡用 Homestead,他優點是可以起一台 VM 就可以同時使用多個專案,而且透過修改一個簡單的 Homestead.yml 就可以做完全部環境的設定,但官方已經宣布不維護了,身為資訊人,你要嘛 fork 一份自己維護,不然就要跟著時代走。

不維護的原因也很簡單,VM 真的很肥很吃資源,現在 docker 實在是太香了,而且 Windows 引入 WSL 以後,Docker Desktop 也是秒級啟動,Laravel Sail 也是 base on Docker Compose,是時候跟 Homestead 分手了 。°(°¯᷄◠¯᷅°)°。。

SMB

WSL 有一個痛點,你用他預設掛載進去的目錄執行任何程式碼都慢到哭,目前我實作比較好的方式是透過 SMB 把你的工作目錄掛進去,跑起來跟在本機執行相差無幾,首先是在你要分享的目錄上按右鍵選內容,共用 -> 進階共用 -> 共用此資料夾,共用名稱建議字尾加個 $,這樣在網路芳鄰上會看不到這個目錄,像是 code$,這樣我打 \\HOST\\code$ 可以連到,在公網上是看不到的,另外是我在本機多設定了一組 smb/smb 帳號,這樣我在 demo 的時候也不會因為被看到密碼尷尬,SMB 沒設定的話預設是你這台 Windows 的登入帳號密碼。

WSL

我並沒有使用 Docker Desktop,因為他開機即啟動,而且無法手動 terminate,WSL 資源雖然吃不多,但我沒有要開發的時候並不需要你來吃我這份資源,我知道網路上有許多改機碼之類的方式可以達成這個目的,但官方沒給的我認為都是邪門歪道,我很不喜歡用非官方的方式解決問題,所以我自己起一台 Ubuntu wsl --install -d Ubuntu --name develop,之後再進去自己安裝 Docker,自由自在~

進去 WSL 以後我建議一律 sudo su,用 root 可以少遇到很多奇奇怪怪的權限問題,再來就是手動掛載 smb 了,我將指令放到 ~/.bashrc,因為 WSL 沒有固定 IP,所以你沒辦法把掛載寫死,要的話也是要寫一堆 script 去判斷東西,我是覺得沒必要。

在 Powershell 內可以執行 Get-SmbShare 得到你 smb 的目錄名稱。

Get-SmbShare

Name   ScopeName Path               Description
----   --------- ----               -----------
ADMIN$ *         C:\WINDOWS         遠端管理
C$     *         C:\                預設共用
code$  *         C:\Users\chan\code
IPC$   *                            遠端 IPC
Users  *         C:\Users

/scripts/mount_smb.sh

_get_windows_ip() {
    # 方法 1:透過 /proc/net/route (最穩定)
    # 取得預設閘道,就是 Windows host IP
    local gateway_ip
    gateway_ip=$(awk '$1 == "00000000" {print strtonum("0x"substr($3,7,2))"."strtonum("0x"substr($3,5,2))"."strtonum("0x"substr($3,3,2))"."strtonum("0x"substr($3,1,2))}' /proc/net/route | head -1)
    
    if [[ -n "$gateway_ip" ]]; then
        echo "$gateway_ip"
        return 0
    fi
    
    # 方法 2:透過 ip route (備選)
    gateway_ip=$(ip route show | awk '/^default via/ {print $3}' | head -1)
    
    if [[ -n "$gateway_ip" ]]; then
        echo "$gateway_ip"
        return 0
    fi
    
    # 方法 3:透過 resolv.conf (Windows 10 相容)
    gateway_ip=$(awk '/^nameserver/ {print $2; exit}' /etc/resolv.conf)
    
    if [[ -n "$gateway_ip" ]]; then
        echo "$gateway_ip"
        return 0
    fi
    
    echo "" >&2
    return 1
}

_mount_smb() {
    local smb_share="$1"
    local mount_point="$2"
    local smb_username="smb"
    local smb_password="smb"
    local smb_host
    
    # 檢查必要參數
    if [[ -z "$smb_share" ]] || [[ -z "$mount_point" ]]; then
        echo "Usage: _mount_smb <share> <mount_point>" >&2
        return 1
    fi
    
    # 檢查是否已掛載
    if mountpoint -q "$mount_point"; then
        echo "Already mounted at $mount_point"
        return 0
    fi
    
    # 確保掛載點存在
    [[ -d "$mount_point" ]] || mkdir -p "$mount_point"
    
    # 動態取得 Windows host IP
    smb_host=$(_get_windows_ip)
    
    if [[ -z "$smb_host" ]]; then
        echo "Error: Cannot determine Windows host IP" >&2
        return 1
    fi
    
    echo "Detected Windows host IP: $smb_host"
    echo "Attempting to mount //$smb_host/$smb_share to $mount_point"
    
    # 測試連線
    if ! timeout 3 bash -c "</dev/tcp/$smb_host/445" 2>/dev/null; then
        echo "Error: Cannot connect to $smb_host:445 (SMB port)" >&2
        return 1
    fi
    
    echo "SMB port is reachable, mounting..."
    
    # 執行掛載 (優先使用 SMB 3.0,失敗則試 2.1)
    if sudo mount -t cifs "//${smb_host}/${smb_share}" "$mount_point" \
        -o username="$smb_username",password="$smb_password",vers=3.0,uid=$(id -u),gid=$(id -g),file_mode=0777,dir_mode=0777 2>/dev/null; then
        echo "✓ SMB share mounted at $mount_point"
        return 0
    else
        echo "SMB 3.0 failed, trying SMB 2.1..."
        
        if sudo mount -t cifs "//${smb_host}/${smb_share}" "$mount_point" \
            -o username="$smb_username",password="$smb_password",vers=2.1,uid=$(id -u),gid=$(id -g),file_mode=0777,dir_mode=0777 2>/dev/null; then
            echo "✓ SMB share mounted at $mount_point (SMB 2.1)"
            return 0
        fi
        
        echo "✗ Failed to mount SMB share" >&2
        return 1
    fi
}

~/.bashrc

# ~/.bashrc - SMB Mount Configuration with Dynamic Windows IP

source /scripts/mount_smb.sh

# 只在互動式 shell 中執行
if [[ $- == *i* ]] && [[ $SHLVL -eq 1 ]]; then
    _mount_smb "code$" /mnt/code
fi

這段程式碼簡單講就是把我在本機 share 的 \\HOST\\code$ 掛到 ~/mnt/code,需要多掛幾個多執行幾次 _mount_smb 即可,每次進入 WSL 便抓取 Host Gateway IP 來連結,目錄跟檔案權限都設定成 777 避免一堆怪事發生,反正開發機不怕。

實際測試

這邊獻上幾個環境跑 phpunit 測試結果,測試數量 1364:

Host

real 1m 37.34s
real 1m 37.83s
real 1m 36.08s


平均:1m 37.08s

Vagrant + SMB

real 3m58.906s
real 3m32.119s
real 3m17.965s


平均:3m 36.33s

WSL + SMB

real 1m48.497s
real 1m57.464s
real 1m50.013s


平均:1m51.991s

其實在 Vagrant 裡面即便使用 SMB 執行速度還是悲劇,我已經這樣操作很久了,但因為 Homestead 的便利性一直選擇忽視這個問題,反正也不是整天跑 full test,另外有趣的一件事情,在 WSL 裡面使用 docker build 一個 php 環境跑測試,我預計應該要掉個 3% 的速度,因為它是 Host -> WSL -> Docker Volume,多一層轉換理應要消耗吧,但沒想到跑了幾次的結果它居然跟在 Windows Host 跑的時間差不多,php.ini 除了調整 memory_limit = -1 以外都沒動,不確定是 Docker 預設拉取的 OS 是 Alpine Linux 效能很好,還是 PHP 官方的 container php.ini 的配置有優化,總之蠻意外的。

之後預計會使用 WSL + Docker + Laravel/Sail 開發測試專案啦,謝謝你 Homestead。

2025/05/26

Homestad PHP PPA Issue

最近執行 Homesteadvagrant reload --provision 會遇到錯誤。

E: Repository 'https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy InRelease' changed its 'Label' value from '***** The main PPA for supported PHP versions with many PECL extensions *****' to 'PPA for PHP'

這是因為該 PPA 的 Label 產生了變化,解決方法也挺簡單。

vagrant ssh 進去 vm 後,執行下面指令:

sudo rm -rf /var/lib/apt/lists/*
sudo apt-get clean
sudo apt-get update --allow-releaseinfo-change

記得遇到這個問題處理過後要退出 vm 執行 vagrant reload --provision,才會有變動。

2021/12/02

Laravel Connet To MSSQL Server On CentOS

PHP 安裝

# Install PHP 7.4
sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum -y install yum-utils
sudo yum-config-manager --enable remi-php74
sudo yum install -y php php-pdo php-odbc php-mbstring php-zip php-xml

MSSQL Driver 安裝,擇一安裝

1. MSSQL Driver(首選,支援版本 SQL Server 2000 以上)

sudo yum install php-sqlsrv
curl https://packages.microsoft.com/config/rhel/7/prod.repo > /etc/yum.repos.d/mssql-release.repo

sudo yum remove unixODBC-utf16 unixODBC-utf16-devel #to avoid conflicts
sudo ACCEPT_EULA=Y yum install -y msodbcsql17

2. FreeTDS(Sql Server 2000)

sudo yum -y install php-mssql
sudo yum -y install unixODBC-*
sudo yum -y install freetds

cd /usr/lib64
sudo mv libtdsodbc.so.0.0.0 libtdsodbc.so
sudo vi /etc/odbcinst.ini

在最後增加:

[FreeTDS]
Description = ODBC for FreeTDS
Driver64    = /usr/lib64/libtdsodbc.so
Setup64     = /usr/lib64/libtdsodbc.so
FileUsage   = 1
sudo vi /etc/freetds.conf

在最後增加:

[SqlServer2000]
    host = {IP}
    port = 1433
    tds version = 8.0
    client charset = UTF-8

在 Laravel 的配置一切照舊,除了 MSSQL 的 host 要指到 SqlServer2000,若遇到時間格式的問題可以參考此篇,使用 FreeTDS 可以通吃,但怕會有無法預期的問題,不建議同一台 Server 同時使用兩種方式。

參考網站

2020/11/04

Laravel Homestead Windows Folder Sync Issue

目前工作是基於 Laravel 開發公司產品,系統環境是 Windows,開發環境安裝了 Homestead,Homestead 是 Laravel 官方釋出,使用 Vagrant 安裝 Ubuntu,透過 config 可配置出 Laravel 開發需要的所有內容,包含 PHP(多種版本)、Apache 或 Nginx 提供選擇、Database、Redis 等等,Windows 以及 Mac 都可用,對 Windows user 來說最大的好處是開發環境可以較接近 production 環境(unix base)。

虛擬機器的工作模式多半會跟實體環境 mount 共同目錄,這樣可以直接在本機編輯檔案,虛擬環境連結的的內容會即時更新,但使用 Homestead 開發時一直遇到問題,例如在 vm 環境無法刪除某些檔案,或者是專案從 gitlab 下載以後 compose install 時會有錯誤訊息,像是:

[ErrorException]
  include(/home/vagrant/code/laravel/vendor/phpstan/extension-installer/src/Plugin.php): failed to open stream: No such file 
  or directory

只要把檔案放置在非 sync 的目錄下執行就不會有問題,因此我選擇了從別的地方 composer install or update 之後再複製到 sync 目錄,一直到日前我要開發新專案直接 new 一個新的目錄出後發生了更多大大小小的錯誤,包括測試會中斷,問題多到我無法像維護先前專案那樣換目錄執行套件安裝就好了,因此必須徹底解決這個問題。

其實問題很明顯,Windows sync 到 VM 後一定被外部的 Windows 影響到了目錄或檔案的權限,所以解法就朝變更 sync 方式發想,Vagrant 官方有提到幾種 sync 方式。

NFS

其中有一段文。

Windows users: NFS folders do not work on Windows hosts. Vagrant will ignore your request for NFS synced folders on Windows.

所以我就連試都沒試了。

RSync

Rsync 只能單方推送,我在 Windows 改變的檔案可以進去 VM,但在 VM 裡面執行產生的檔案不會同步回來,所以也不行。

SMB

Samba 有成功,之前發生的問題沒有了,但他非常慢,非常慢或許可以忍,但使用 SAMBA 後跑 unittest 會跑到 server 掛掉,這可就不能接受了。

上述方法使用無效以後,我還試了 WSL 以及 Multipass,WSL 我裝了 Ubuntu 20,但他 mount 的結果跟 Homestead 狀況一樣,multipass 也一樣,multipass 另外一個 issue 是如果使用 virtualbox 的話在 Windows 環境無法發派 IP,那你根本不能用 domain name 或 IP 進行測試,除非改用 hyper-v。

正當我試了一切想要放棄,打算使用 remote ssh 工作的時候,突然翻到 Homestead 有這麼一段說明:

To enable NFS, you only need to add a simple flag to your synced folder configuration:

When using NFS on Windows, you should consider installing the vagrant-winnfsd plug-in. This plug-in will maintain the correct user / group permissions for files and directories within the Homestead box.

What?

於是我安裝了 vagrant-winnfsd,然後 homestead 裡面配置了:

folders:
    - map: ~/code/project1
      to: /home/vagrant/project1
      type: "nfs"

所有問題都解決了,一切正常,而且速度很快,Vagrant 官方那段是在莊孝維嗎,為了解決這個問題我花了快一週,之後其他 Vagrant 配置也都會指定 sync 類型。

Vagrant.configure("2") do |config|
  config.vm.synced_folder ".", "/vagrant", type: "nfs"
end

很多東西解法其實很簡單,但有可能是前人嘗試了很久的結果,因為我順利解決了,所以留下這篇文章希望可以幫助到跟我遇到一樣問題的朋友。

2016/05/25

ssh keygen and management

常使用 ssh 連去遠端工作,連遠端時在 windows 我使用 xshell,他有工具可以幫我記帳密,只要點選便可以連結,但在我 ubuntu 的工作環境使用 terminal 的時候,必須打完整的指令 ssh root@chan15.info,然後再輸入密碼,是不會很麻煩啦,但目前專案越來越多跟需另開視窗同一 server 啟用 node.js 服務越來越頻繁的情況,希望可以減少輸入的頻率,最簡單的方式就是用金鑰,可以免輸入密碼,接下來是建構介紹

建立配置金鑰

金鑰的概念是,你在本基上 generate 一組 public key 跟 private key,然後將 public key 置入 remote server 中,你就可以用你的 private key 登入該 remote server,在 Linux 環境有 ssh-keygen 指令可以建立,在 windows 的話,很多 Linux 模擬器例如 cmder,xshell 本身也有 gen 的功能,或者是使用 puttygen,都是在做一樣的事情,這邊我使用 key-gen 來做。

# 先切換到自己帳號的目錄,並建立一個 .ssh 的資料夾
# Windows 的話會是 C:\Users\root\.ssh
# Linux 的話就是 /home/root/.ssh

$ ssh-keygen -t rsa - C "chan15tw@gmail.com"

# 這邊會問你名稱,我要連到自己的 chan15 server,所以我取名為 chan15 然後按下 enter
$ Enter file in which to save the key (/c/Users/kr141101/.ssh/id_rsa):chan15

# 接著問你要不要密碼,可以跳過
$ Enter passphrase (empty for no passphrase):

# 看到這個畫面就表示成功了
$ Your identification has been saved in chan15.
$ Your public key has been saved in chan15.pub.
$ The key fingerprint is:
$ SHA256:IrXB6LfAtW7rFMJlIRjrx+JWaty2nLKNc0jrFM0+9nc chan15tw@gmail.com
$ The key's randomart image is:
$ +---[RSA 2048]----+
$ |  .o. ..         |
$ |   o+.  . E      |
$ |   +.o . .       |
$ |  . + =o         |
$ |   . Bo.S        |
$ |  o.B o.         |
$ |  .BoB.o . .     |
$ |  o+O.*o+.o .    |
$ |   +BO.++o..     |
$ +----[SHA256]-----+

# 資料夾會有 chan15 以及 chan15.pub,兩個檔案,看一下 chan15.pub 有什麼
$ cat chan15.pub
$ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC91YXEW08rAIzVc3xS5owRsIBizSlZJvkaJcddZEGP3XrQk+3fC0lDpMdXR2UfoIMdFQbMHETcsfeuEgivjUzqppA7QRcxV/uCbrfRtrz38nR9Nu/celqUPTEF2k1RjyK19acsTOOaX/hS8KFBw91HnENAUUpFtmjMXEsgPern9YV3DcgFBxKrgtg13lnzDoSVVYdmqqqxZG6OggJE6r27lF9BIfz8fdcuGBMbNx5DvivEu/h6Hejj0ax9N5DAqJhSCASSkd+dRYUur7OMptvM05UDgl/zAuRWlT9jO38yMvMBFztcyAPUGeVANV6nG0Kbr2GQe9T5Hi1wtf1y/yCX chan15tw@gmail.com

網路上很多將 pub key 加到 remote server 的方法,像是用 cat,用 scp 等等的,但最妥當沒風險的,就是你直接打開 remote server,然後找到 /home/root/.ssh/authorized_keys,將 pub key 加到裡面去,如果你沒有這個檔案,還可以自行創立,然後將權限設定為 600。

連線管理與配置

接下來我們就可以用指令連線到 remote server

$ ssh -i chan15 root@chan15.info

這個指令意思就是使用 chan15 這個 private key 去連線到 remote,而 remote 那邊會去找 root 根目錄 authorized_keys 有沒有對應的 key,有的話就會 pass,但樣指令還是太長,我們可以透過設定 config 將指令縮短,打開 local /hoem/root/.ssh/,建立一個叫 config 的檔案,內容如下:

Host chan15
    HostName chan15.info
    User root
    IdentityFile /home/root/.ssh/chan15

這樣設定好以後只要執行 ssh chan15 就可以連線了,是不是很方便。

參考文章

https://blog.longwin.com.tw/2005/12/ssh_keygen_no_passwd/
http://www.cyberciti.biz/faq/create-ssh-config-file-on-linux-unix/

2014/12/01

Homestead 2.1

Laravel 真的很坑爹,不久前才寫了 Homestead 的安裝方式,Homestead 就出了 2.0,不過其實也沒有差異到非常大啦,讓我們來 step by step 吧。

一樣,先加入 laravel 的 box,現在的版本是 0.2.1。

vagrant box add laravel/homestead

下載完之後,要進行這次最大的改變,使用 composer 安裝啟動 homestead 的相關套件指令,因此我們輸入 composer global require "laravel/homestead=~2.0",安裝完畢以後,我們就可以在任意處使用 homestead 相關指令了。

基本指令
destroy   Destroy the Homestead machine
edit      Edit the Homestead.yaml file
halt      Halt the Homestead machine
help      Displays help for a command
init      Create a stub Homestead.yaml file
list      Lists commands
resume    Resume the suspended Homestead mach
run       Run commands through the Homestead
ssh       Login to the Homestead machine via
status    Get the status of the Homestead mac
suspend   Suspend the Homestead machine
up        Start the Homestead machine
update    Update the Homestead machine image

基本上指令就是沿用 Vagrant 的常用指令,只不過讓你省去切換到 homestead 資料夾後執行指令這個動作,改用類似 homestead up 替代,接下來我們先執行 homestead init,執行之後在 ~/.homestead 目錄下會產生 Homestead.yaml 檔案,該檔案就是 homestead 的設定檔,也就是 1.0 的 Vagrantfile,Windows 的部分存在於 c:/Users/Your_Account/.homestead,打開檔案後其實跟之前的內容是一模一樣的,就不再贅述了

---
ip: "192.168.1.12"
memory: 1024
cpus: 1

authorize: C:/Users/ACCOUNT/.ssh/id_rsa.pub

keys:
    - C:/Users/ACCOUNT/.ssh/id_rsa

folders:
    - map: D:/www/laravel
      to: /home/vagrant/www/laravel

sites:
    - map: homestead.app
      to: /home/vagrant/www/laravel/public

databases:
    - homestead

variables:
    - key: APP_ENV
      value: local

這是我這次的 config,儲存後執行 homestead up,如果遇到權限問題,請執行 ssh-keygen -t rsa -C "you@homestead",啟動完畢後,你可以使用 homestead ssh 進入 server,或者用第三方軟體 ssh ip,預設帳密都是 vagrant,要使用 root 的話密碼也是 vagrant,登入以後,可以切換到 /home/vagrant/www 下,可以看到 Laravel 已經裝好了,1.0 的話要自己在執行 create project 的動作,2.0 之後會幫你自己裝好,切到自己本機 D:/www/laravel 目錄,發現檔案是同步的,安裝部分成功了。

nginx 的部分 homestead 也自動會對應完成,所以我們現在要修改 Windows 下的 C:\Windows\System32\drivers\etc\hosts,Linux 則是在 /etc/hosts/,將對應的 domain 加入 192.168.1.12 homestead.app,開啟我們的 browser,輸入 http://homestead.app,當你看到美麗的 Laravel logo 之後,美好的事情正要開始 :)

2014/11/11

Laravel With Vagrant

一般 programmer 開發程式都是自己安裝自己的開發環境,不管在 Windows 或者是 Linux 都有所謂的懶人包,譬如說早期的 AppServXAMPP 以及 WampServer,Linux 的部分也有,但我通常都是用套件管理裝的所以就不舉例了,如果大家都是 Windows 並且強迫安裝同一套就還好,但如果 A 同事是 Windows 愛用者,B 同事用 Ubuntu,C 同事用 Mac,這樣就有點麻煩了,虛擬機器這個 solution 就可以確保所有的人開發環境都一樣,目前最佳解大概就是 Vagrant + VirtualBox 了。

Vagrant 可以說是 VirtualBox 的管理套件,以往我們要使用 VirtualBox,就是開一個環境,然後 download 某個 OS 的 ISO 檔案,掛載虛擬光碟,然後再進 VirtualBox 慢慢安裝,Vagrant 可以讓你把已經設定好的環境打包成一個 box,有點類似 ghost,所以你可以找人家包好的環境,例如說今天需要一個「真正」的 IE 6 的測試環境,你可以去 http://www.vagrantbox.es/ 或者是 https://vagrantcloud.com/ 搜尋 Windows XP,看到有人打包了 indows XP with IE6,我們就可以輕輕鬆鬆部屬這個環境,只要以下的指令即可。

vagrant add ie6_test http://aka.ms/vagrant-xp-ie6
vagrant ie6_test
vagrant up

甚至你可以自己把自己建置好的環境打包給別人使用,今天來示範一下怎麼快速建置一個 Laravel 環境,Laravel 有製作自己的 Vagrant Box 叫 Homestead,我來一步步操作怎麼在 Windows 建立官方的範例。

下載 laravel/homestead

vagrant box add laravel/homestead

當然你要在你的電腦先裝好 Vagrant 以及 VirtualBox,當他跑完安裝以後,可以執行 vagrant box list,如果有看到 laravel/homestead (virtualbox, 0.2.0) 代表你的 box 已經進來了,接下來我在 D:/ 建立一個叫 vm 的資料夾,進入 D:/vm,執行 git clone https://github.com/laravel/homestead.git Homestead,成功後看到 D:/vm/Homestead 資料夾,進去之後打開 Homestead.yaml 來修改,一般來說我們要 init 一個新的 box 都是修改 Vagrantfile 這個 config,而 Laravel 這個 yaml 就是他們獨立出來的客製化 config,預設如下:

---
ip: "192.168.10.10"
memory: 2048
cpus: 1

authorize: ~/.ssh/id_rsa.pub

keys:
    - ~/.ssh/id_rsa

folders:
    - map: ~/Code
      to: /home/vagrant/Code

sites:
    - map: homestead.app
      to: /home/vagrant/Code/Laravel/public

variables:
    - key: APP_ENV
      value: loca

ip 就是該虛擬機器的 ip,memory 就是你要給這台機器占用多少記憶體,authorize 以及 keys 是 Laravel 驗證 ssh 使用,folders 是指 folder sync,也就是說,假設我們在 D:/ 建立了一個資料夾,將他跟 vm 裡面的開發資料夾做 sync 的話,我們就不用整天都要 ssh 進去該 vm 來改程式,只要改我們 D:/ 的資料夾以後 vm 裡面的開發資料夾就會同步 sync 了,sites 就是將 domain name 指定到開發資料夾,如果你沒有要修改 hosts 的話,這個東西就沒有作用了,variables 就不用管,所以修改過後的內容如下:

---
ip: "192.168.10.14"
memory: 1024
cpus: 1

authorize: C:/Users/YOUR_USER_NAME/.ssh/id_rsa.pub

keys:
    - C:/Users/YOUR_USER_NAME/.ssh/id_rsa

folders:
    - map: 'D:/vm/laravel'
      to: /home/vagrant/www

sites:
    - map: laravel.app
      to: /home/vagrant/www/laravel/public

variables:
    - key: APP_ENV
      value: local

如果你的驗證有問題的話,請執行 ssh-keygen -t rsa -C "you@homestead",如果順利起來的話,執行 vagrant ssh 就可以直接進入 server,如果你想用其他的 ssh 軟體,只要指定 ssh 127.0.0.1 2222 即可,帳號密碼都是 vagrant,我們進入剛指定的資料夾 /home/vagrant/www,開始建立我們的 Laravel 專案,執行 composer create-project laravel/laravel --prefer-dist,composer 會開始幫我們載入檔案,我們可以切換到 D:/vm/laravel 資料夾,應該多了一個 laravel 資料夾並且正在同步下載檔案,安裝完畢後在 browser 跑 192.168.10.14,如果看到 Laravel 歡迎畫面,表示打完收工。

Homestead 幫你打造了下列的環境:

  • Ubuntu 14.04
  • PHP 5.6
  • HHVM
  • Nginx
  • MySQL
  • Postgres
  • Node (With Bower, Grunt, and Gulp)
  • Redis
  • Memcached
  • Beanstalkd
  • Laravel Envoy
  • Fabric + HipChat Extension

實用的 vagrant 指令

vagrant box list # 列出現在所有的 box
vagrant box remove xxx # 移除某個 box
vagrant destroy # 將某個目錄下的 vm 銷毀
vagrant status # 查看目前 vm 的狀況
vagrant halt # 關閉目前的 vm
vagrant reload # 重啟 vm

2014/11/07

Transaction With Eloquent

今天研究 Database Transaction 的時候發現了一招可以 Eloquent 跟 Transaction 混用。

<?

$user = new User;
$user->name = 'Chan';

$member = new Member;
$member->age = 33;

DB::transaction(function() use ($user, $member) {
    try {
        $user->save();
        $member->save();
    } catch (Exception $e) {
        dd($e->getMessage());
    }
});