Skip to content

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 并不能完全替代 SailHomestead,但如果你想要更灵活的基础环境、偏爱极致速度,或者正在使用内存较小的机器,它会是一个很好的选择。

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 提供两个命令帮助你提供站点服务:parklink

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 命令也可以用于为 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 links

unlink 命令可用于删除站点的符号链接:

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 phpcomposerwhich-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 配置,并指定 ngrokexposecloudflared

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_HERE

NOTE

你可以向 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 文件。这个文件包含一个示例驱动实现,用于说明如何编写自定义驱动。编写驱动只需要实现三个方法:servesisStaticFilefrontControllerPath

这三个方法都会接收 $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 命令

CommandDescription
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 站点配置。运行 installsecure 命令时,这些文件会被重新构建。

~/.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 项。