主题
Laravel Valet
简介
NOTE
想在 macOS 或 Windows 上用一种更简单的方式开发 Laravel 应用吗?可以看看 Laravel Herd。Herd 内置了开始进行 Laravel 开发所需的一切,包括 Valet、PHP 和 Composer。
Laravel Valet 是为追求极简的 macOS 用户准备的开发环境。Laravel Valet 会将你的 Mac 配置为在开机时始终在后台运行 Nginx。然后借助 DnsMasq,Valet 会将 *.test 域名下的所有请求代理到你本机安装的网站。
换句话说,Valet 是一个极快的 Laravel 开发环境,内存占用大约只有 7 MB。Valet 并不能完全替代 Sail 或 Homestead,但如果你想要更灵活的基础环境、偏爱极致速度,或者正在使用内存较小的机器,它会是一个很好的选择。
Valet 开箱即支持的框架 / 系统包括但不限于:
不过,你也可以通过自己的自定义驱动扩展 Valet。
安装
WARNING
Valet 依赖 macOS 和 Homebrew。安装前,你应确保本机没有其他程序(例如 Apache 或 Nginx)占用 80 端口。
首先,使用 update 命令确保 Homebrew 已更新到最新版本:
shell
brew update接着,使用 Homebrew 安装 PHP:
shell
brew install php安装 PHP 后,你就可以安装 Composer 包管理器 了。另外,你还应确保 $HOME/.composer/vendor/bin 目录已经加入系统的 PATH。安装好 Composer 后,就可以将 Laravel Valet 作为全局 Composer 包安装:
shell
composer global require laravel/valet最后,执行 Valet 的 install 命令。它会配置并安装 Valet 与 DnsMasq。此外,Valet 依赖的守护进程也会被配置为在系统启动时自动启动:
shell
valet install安装完成后,你可以在终端中尝试 ping 任意 *.test 域名,例如 ping foobar.test。如果 Valet 安装正确,你应能看到这个域名响应自 127.0.0.1。
每次机器启动时,Valet 都会自动启动其所需服务。
PHP 版本
NOTE
你不必修改全局 PHP 版本,也可以通过 isolate 命令 让 Valet 为每个站点使用不同的 PHP 版本。
Valet 允许你使用 valet use php@version 命令切换 PHP 版本。如果指定版本尚未安装,Valet 会通过 Homebrew 自动安装:
shell
valet use php@8.2
valet use php你也可以在项目根目录创建一个 .valetrc 文件。这个 .valetrc 文件应写明该站点需要使用的 PHP 版本:
shell
php=php@8.2创建该文件后,你只需执行 valet use 命令,Valet 就会通过读取该文件来确定站点偏好的 PHP 版本。
WARNING
即使你安装了多个 PHP 版本,Valet 在同一时间也只会使用一个 PHP 版本来提供服务。
数据库
如果你的应用需要数据库,可以看看 DBngin。它是一个免费的数据库管理工具,集成了 MySQL、PostgreSQL 和 Redis。安装 DBngin 后,你可以通过 127.0.0.1,使用用户名 root 和空密码连接数据库。
重置安装
如果你的 Valet 安装运行不正常,重新执行 composer global require laravel/valet,再执行 valet install,通常可以重置安装并解决多种问题。在极少数情况下,你可能需要通过执行 valet uninstall --force 再执行 valet install 来对 Valet 进行“硬重置”。
升级 Valet
你可以在终端中执行 composer global require laravel/valet 来更新 Valet 安装。升级完成后,最佳实践是再运行一次 valet install,以便 Valet 在必要时对配置文件做额外升级。
升级到 Valet 4
如果你要从 Valet 3 升级到 Valet 4,请按照以下步骤正确完成升级:
- 如果你曾添加
.valetphprc文件来自定义站点的 PHP 版本,请将每个.valetphprc文件重命名为.valetrc。然后,在.valetrc文件现有内容前加上php=。 - 更新所有自定义驱动,使其命名空间、扩展方式、类型提示和返回类型提示与新的驱动系统一致。你可以参考 Valet 的 SampleValetDriver。
- 如果你使用 PHP 7.1 - 7.4 为站点提供服务,请确保仍然使用 Homebrew 安装一个 8.0 或更高版本的 PHP,因为 Valet 会使用这个版本来运行其部分脚本,即使它不是你当前主要链接的版本。
提供站点服务
Valet 安装完成后,你就可以开始为 Laravel 应用提供本地服务了。Valet 提供两个命令帮助你提供站点服务:park 和 link。
park 命令
park 命令会注册你机器上的某个目录,该目录中包含你的应用。某个目录被 Valet “park” 之后,该目录下的所有子目录都可以通过 http://<directory-name>.test 在浏览器中访问:
shell
cd ~/Sites
valet park就这么简单。现在,你在这个“已 park”的目录中创建的任何应用,都会自动按照 http://<directory-name>.test 这一约定提供服务。因此,如果你的已 park 目录中有一个名为 laravel 的目录,那么其中的应用就可以通过 http://laravel.test 访问。此外,Valet 还会自动允许你使用通配符子域访问站点,例如 http://foo.laravel.test。
link 命令
link 命令也可以用于为 Laravel 应用提供服务。当你只想为某个目录下的单个站点提供服务,而不是为整个目录提供服务时,这个命令非常有用:
shell
cd ~/Sites/laravel
valet link应用通过 link 命令链接到 Valet 后,你就可以使用它所在目录的名称访问该应用。因此,上面示例中的站点可以通过 http://laravel.test 访问。此外,Valet 也会自动允许你通过通配符子域访问站点,例如 http://foo.laravel.test。
如果你希望应用通过其他主机名提供服务,也可以将主机名传给 link 命令。例如,执行以下命令可让应用通过 http://application.test 访问:
shell
cd ~/Sites/laravel
valet link application当然,你也可以使用 link 命令在子域名上提供服务:
shell
valet link api.application你可以执行 links 命令查看所有已链接目录的列表:
shell
valet linksunlink 命令可用于删除站点的符号链接:
shell
cd ~/Sites/laravel
valet unlink使用 TLS 保护站点
默认情况下,Valet 通过 HTTP 提供站点服务。不过,如果你希望通过加密的 TLS 使用 HTTP/2 为站点提供服务,可以使用 secure 命令。例如,如果你的站点正通过 laravel.test 域名由 Valet 提供服务,则应执行以下命令:
shell
valet secure laravel如果你想取消站点的安全配置并恢复为纯 HTTP,可以使用 unsecure 命令。与 secure 命令一样,该命令也接受你希望取消安全配置的主机名:
shell
valet unsecure laravel提供默认站点
有时,你可能希望在访问未知 test 域名时,由 Valet 提供一个“默认”站点,而不是返回 404。为此,你可以在 ~/.config/valet/config.json 配置文件中添加一个 default 选项,并将其值设置为默认站点的路径:
"default": "/Users/Sally/Sites/example-site",
每站点 PHP 版本
默认情况下,Valet 使用你的全局 PHP 安装来为站点提供服务。不过,如果你需要让不同站点运行不同 PHP 版本,可以使用 isolate 命令为某个具体站点指定 PHP 版本。isolate 命令会为当前工作目录中的站点配置指定的 PHP 版本:
shell
cd ~/Sites/example-site
valet isolate php@8.0如果你的站点名与所在目录名不一致,也可以通过 --site 选项显式指定站点名:
shell
valet isolate php@8.0 --site="site-name"为方便起见,你还可以使用 valet php、composer 和 which-php 命令,根据站点配置的 PHP 版本,将调用代理到对应的 PHP CLI 或工具:
shell
valet php
valet composer
valet which-php你可以执行 isolated 命令来显示所有已隔离站点及其对应的 PHP 版本列表:
shell
valet isolated若要让某个站点恢复为使用 Valet 全局安装的 PHP 版本,可以在该站点根目录中执行 unisolate 命令:
shell
valet unisolate共享站点
Valet 提供了一个命令,可以将你的本地站点共享到外部网络,从而方便你在移动设备上测试,或与团队成员和客户共享站点。
Valet 默认支持通过 ngrok 或 Expose 共享站点。在共享站点之前,你应使用 share-tool 命令更新 Valet 配置,并指定 ngrok、expose 或 cloudflared:
shell
valet share-tool ngrok如果你选择了某个工具,但尚未通过 Homebrew(针对 ngrok 和 cloudflared)或 Composer(针对 Expose)安装它,Valet 会自动提示你安装。当然,这两种工具都要求你先完成 ngrok 或 Expose 账号认证,之后才能开始共享站点。
要共享站点,请在终端中切换到站点目录,然后执行 Valet 的 share 命令。一个可公开访问的 URL 会被复制到剪贴板中,你可以直接粘贴到浏览器或分享给团队成员:
shell
cd ~/Sites/laravel
valet share要停止共享站点,可以按 Control + C。
WARNING
如果你使用自定义 DNS 服务器(例如 1.1.1.1),ngrok 共享可能无法正常工作。如果你的机器上存在这种情况,请打开 Mac 的系统设置,进入网络设置,再打开高级设置,切换到 DNS 标签页,并将 127.0.0.1 添加为第一个 DNS 服务器。
通过 Ngrok 共享站点
使用 ngrok 共享站点要求你先创建一个 ngrok 账号,并设置认证 token。获取 token 后,你可以使用它更新 Valet 配置:
shell
valet set-ngrok-token YOUR_TOKEN_HERENOTE
你可以向 share 命令传递额外的 ngrok 参数,例如 valet share --region=eu。更多信息请参阅 ngrok 文档。
通过 Expose 共享站点
使用 Expose 共享站点要求你先创建一个 Expose 账号,并使用认证 token 完成 Expose 认证。
关于它支持的更多命令行参数,可以参考 Expose 文档。
在本地网络中共享站点
默认情况下,Valet 会将传入流量限制在内部 127.0.0.1 接口上,以避免开发机器暴露给互联网带来的安全风险。
如果你希望本地网络中的其他设备通过你机器的 IP 地址访问本机上的 Valet 站点(例如 192.168.1.10/application.test),就需要手动编辑该站点对应的 Nginx 配置文件,移除 listen 指令中的限制。你需要删除 80 和 443 端口对应 listen 指令前面的 127.0.0.1: 前缀。
如果你没有对该项目执行过 valet secure,那么可以通过编辑 /usr/local/etc/nginx/valet/valet.conf 文件,为所有非 HTTPS 站点打开网络访问。相反,如果该项目站点是通过 HTTPS 提供服务的(即你已为该站点运行过 valet secure),那么你应编辑 ~/.config/valet/Nginx/app-name.test 文件。
更新 Nginx 配置后,运行 valet restart 命令以应用配置变更。
站点专属环境变量
某些使用其他框架的应用可能依赖服务器环境变量,但又没有提供在项目内部配置这些变量的方式。Valet 允许你在项目根目录中添加 .valet-env.php 文件来配置站点专属环境变量。这个文件应返回一个数组,包含站点与环境变量的映射关系,Valet 会将这些变量添加到数组中指定站点的全局 $_SERVER 数组:
php
<?php
return [
// 为 laravel.test 站点设置 $_SERVER['key'] 为 "value"...
'laravel' => [
'key' => 'value',
],
// 为所有站点设置 $_SERVER['key'] 为 "value"...
'*' => [
'key' => 'value',
],
];代理服务
有时你可能希望把某个 Valet 域名代理到本机上的另一个服务。例如,你可能偶尔需要在运行 Valet 的同时,再运行一个 Docker 中的独立站点;但 Valet 和 Docker 不能同时绑定到 80 端口。
为了解决这个问题,你可以使用 proxy 命令创建代理。例如,你可以将 http://elasticsearch.test 的所有流量代理到 http://127.0.0.1:9200:
shell
# 通过 HTTP 代理...
valet proxy elasticsearch http://127.0.0.1:9200
# 通过 TLS + HTTP/2 代理...
valet proxy elasticsearch http://127.0.0.1:9200 --secure你可以使用 unproxy 命令删除代理:
shell
valet unproxy elasticsearch你也可以使用 proxies 命令列出所有被代理的站点配置:
shell
valet proxies自定义 Valet 驱动
你可以编写自己的 Valet“驱动”,为那些 Valet 原生不支持的框架或 CMS 所运行的 PHP 应用提供服务。安装 Valet 后,会创建一个 ~/.config/valet/Drivers 目录,其中包含一个 SampleValetDriver.php 文件。这个文件包含一个示例驱动实现,用于说明如何编写自定义驱动。编写驱动只需要实现三个方法:serves、isStaticFile 和 frontControllerPath。
这三个方法都会接收 $sitePath、$siteName 和 $uri 作为参数。$sitePath 是当前在你机器上提供服务的站点完整路径,例如 /Users/Lisa/Sites/my-project。$siteName 是域名中的“host” / “site name”部分(例如 my-project)。$uri 是传入请求的 URI(例如 /foo/bar)。
完成自定义 Valet 驱动后,请将其放入 ~/.config/valet/Drivers 目录,并遵循 FrameworkValetDriver.php 的命名约定。例如,如果你为 WordPress 编写一个自定义 valet 驱动,文件名应为 WordPressValetDriver.php。
下面来看看你的自定义 Valet 驱动应实现的各个方法示例。
serves 方法
如果你的驱动应该处理当前传入请求,serves 方法应返回 true;否则返回 false。因此,在该方法中,你应尝试判断给定的 $sitePath 是否包含你要服务的那种项目。
例如,假设我们正在编写一个 WordPressValetDriver,那么 serves 方法大致可能如下所示:
php
/**
* Determine if the driver serves the request.
*/
public function serves(string $sitePath, string $siteName, string $uri): bool
{
return is_dir($sitePath.'/wp-admin');
}isStaticFile 方法
isStaticFile 方法应判断当前传入请求是否针对某个“静态”文件,例如图片或样式表。如果该文件是静态文件,则该方法应返回磁盘上该静态文件的完整路径;如果当前请求并非静态文件,则应返回 false:
php
/**
* Determine if the incoming request is for a static file.
*
* @return string|false
*/
public function isStaticFile(string $sitePath, string $siteName, string $uri)
{
if (file_exists($staticFilePath = $sitePath.'/public/'.$uri)) {
return $staticFilePath;
}
return false;
}WARNING
只有当 serves 方法对当前请求返回 true,并且请求 URI 不是 / 时,isStaticFile 方法才会被调用。
frontControllerPath 方法
frontControllerPath 方法应返回应用“前端控制器”的完整路径,通常是 index.php 或其等价文件:
php
/**
* Get the fully resolved path to the application's front controller.
*/
public function frontControllerPath(string $sitePath, string $siteName, string $uri): string
{
return $sitePath.'/public/index.php';
}本地驱动
如果你只想为单个应用定义一个自定义 Valet 驱动,可以在该应用根目录中创建一个 LocalValetDriver.php 文件。你的自定义驱动可以继承基础 ValetDriver 类,也可以继承某个现有的应用专属驱动,例如 LaravelValetDriver:
php
use Valet\Drivers\LaravelValetDriver;
class LocalValetDriver extends LaravelValetDriver
{
/**
* Determine if the driver serves the request.
*/
public function serves(string $sitePath, string $siteName, string $uri): bool
{
return true;
}
/**
* Get the fully resolved path to the application's front controller.
*/
public function frontControllerPath(string $sitePath, string $siteName, string $uri): string
{
return $sitePath.'/public_html/index.php';
}
}其他 Valet 命令
| Command | Description |
|---|---|
valet list | 显示所有 Valet 命令的列表。 |
valet diagnose | 输出诊断信息,帮助调试 Valet。 |
valet directory-listing | 控制目录列表行为。默认值为 off,即对目录渲染 404 页面。 |
valet forget | 在已 park 的目录中运行此命令,将其从已 park 目录列表中移除。 |
valet log | 查看 Valet 服务写入的日志列表。 |
valet paths | 查看所有已 park 的路径。 |
valet restart | 重启 Valet 守护进程。 |
valet start | 启动 Valet 守护进程。 |
valet stop | 停止 Valet 守护进程。 |
valet trust | 为 Brew 和 Valet 添加 sudoers 文件,使运行 Valet 命令时无需输入密码。 |
valet uninstall | 卸载 Valet:显示手动卸载说明。传入 --force 选项则会更激进地删除 Valet 的全部资源。 |
Valet 目录与文件
在排查 Valet 环境问题时,以下目录和文件信息可能会对你有所帮助:
~/.config/valet
包含 Valet 的全部配置。你可能会想为这个目录保留一份备份。
~/.config/valet/dnsmasq.d/
该目录包含 DNSMasq 的配置。
~/.config/valet/Drivers/
该目录包含 Valet 的驱动。驱动决定特定框架 / CMS 如何被提供服务。
~/.config/valet/Nginx/
该目录包含 Valet 的全部 Nginx 站点配置。运行 install 和 secure 命令时,这些文件会被重新构建。
~/.config/valet/Sites/
该目录包含所有已链接项目的符号链接。
~/.config/valet/config.json
这是 Valet 的主配置文件。
~/.config/valet/valet.sock
这是 Valet 的 Nginx 安装所使用的 PHP-FPM socket。只有在 PHP 正常运行时,这个文件才会存在。
~/.config/valet/Log/fpm-php.www.log
这是 PHP 错误的用户日志文件。
~/.config/valet/Log/nginx-error.log
这是 Nginx 错误的用户日志文件。
/usr/local/var/log/php-fpm.log
这是 PHP-FPM 错误的系统日志文件。
/usr/local/var/log/nginx
该目录包含 Nginx 的访问日志和错误日志。
/usr/local/etc/php/X.X/conf.d
该目录包含各种 PHP 配置项的 *.ini 文件。
/usr/local/etc/php/X.X/php-fpm.d/valet-fpm.conf
这是 PHP-FPM 进程池配置文件。
~/.composer/vendor/laravel/valet/cli/stubs/secure.valet.conf
这是用于为你的站点生成 SSL 证书的默认 Nginx 配置文件。
磁盘访问
自 macOS 10.14 起,对某些文件和目录的访问默认会受到限制。这些限制包括 Desktop、Documents 和 Downloads 目录。此外,网络卷和可移动卷的访问也会受到限制。因此,Valet 建议你将站点文件夹放在这些受保护位置之外。
不过,如果你确实希望从这些位置中的某个目录提供站点服务,那么就需要为 Nginx 授予“完全磁盘访问”权限。否则,你可能会遇到服务器错误,或者 Nginx 出现其他不可预测的行为,特别是在提供静态资源时。通常,macOS 会自动提示你授予 Nginx 对这些位置的完整访问权限。或者,你也可以手动在 System Preferences > Security & Privacy > Privacy > Full Disk Access 中完成设置,然后在主窗口中启用所有 nginx 项。