# Laravel Valet
- [简介](#introduction)
- [Valet 还是 Homestead](#valet-or-homestead)
- [安装](#installation)
- [升级](#upgrading)
- [服务站点](#serving-sites)
- [Park 命令](#the-park-command)
- [Link 命令](#the-link-command)
- [使用 TLS 构建安全站点](#securing-sites)
- [分享站点](#sharing-sites)
- [自定义 Valet 驱动](#custom-valet-drivers)
- [本地驱动](#local-drivers)
- [其他 Valet 命令](#other-valet-commands)
## 简介
Valet 是 Mac 极简主义者的 Laravel 开发环境。没有 Vagrant,不需要配置 `/etc/hosts` 文件。 甚至可以使用本地隧道公开分享你的站点。 Yeah, we like it too.
Laravel Valet 为您的 Mac 设置了开机后始终在后台运行 [Nginx](https://www.nginx.com/) 服务。 然后,Valet 使用 [DnsMasq](https://en.wikipedia.org/wiki/Dnsmasq) 将所有指向安装在本地的计算机站点请求代理到 `*.test` 结尾的域名上。
换句话说,一个速度极快的 Laravel 开发环境只占用 7MB 内存。Valet 并不是想要完全替换 Vagrant 或 Homestead,只是提供另外一种使用起来更加灵活、方便、以及内存占用更小的选择。
Valet 支持但不局限于以下内容:
- [Laravel](https://laravel.com)
- [Lumen](https://lumen.laravel.com)
- [Bedrock](https://roots.io/bedrock/)
- [CakePHP 3](https://cakephp.org)
- [Concrete5](https://www.concrete5.org/)
- [Contao](https://contao.org/en/)
- [Craft](https://craftcms.com)
- [Drupal](https://www.drupal.org/)
- [Jigsaw](https://jigsaw.tighten.co)
- [Joomla](https://www.joomla.org/)
- [Katana](https://github.com/themsaid/katana)
- [Kirby](https://getkirby.com/)
- [Magento](https://magento.com/)
- [OctoberCMS](https://octobercms.com/)
- [Sculpin](https://sculpin.io/)
- [Slim](https://www.slimframework.com)
- [Statamic](https://statamic.com)
- Static HTML
- [Symfony](https://symfony.com)
- [WordPress](https://wordpress.org)
- [Zend](https://framework.zend.com)
当然, 您也可以使用 [自定义驱动](#custom-valet-drivers) 来扩展您的 Valet。
### Valet 还是 Homestead
您应该知道,Laravel 还提供了另外一种本地开发环境 [Homestead](/docs/{{version}}/homestead)。Homestead 和 Valet 的不同之处在于目标受众和本地开发的方式。Homestead 提供了一个完整的、具有自动化的 Nginx 配置的 Ubuntu 虚拟机。如果你想在 Windows/Linux 上实现完全虚拟化的 Linux 开发环境,Homestead 是一个不错的选择。
Valet 仅支持 Mac,并要求你将 PHP 和数据库服务器直接安装到本地机器上。这可以很容易地通过使用 `Homebrew` 命令来实现,比如 `brew install php` 和 `brew install mysql`。Valet 提供了一个极快的、资源消耗最少本地开发环境,非常适合只需要 PHP/MySQL 并且不需要虚拟开发环境的开发人员。
Valet 和 Homestead 都是配置 Laravel 开发环境的绝佳选择。选择哪一个仅仅取决于个人喜好和团队的需求。
## 安装
**Valet 需要 macOS 系统和 Homebrew。在安装之前,要确保没有其它程序(如 Apache 或 Nginx)占用了本地机器的 80 端口。**
- 使用 `brew update` 将 [Homebrew](https://brew.sh/) 安装或更新到最新版本。
- 使用 Homebrew 的 `brew install php` 命令安装 PHP 7.3。
- 安装 [Composer](https://getcomposer.org).
- 使用 Composer 的 `composer global require laravel/valet` 命令安装 Valet。并确保 `~/.composer/vendor/bin` 目录在系统的 "PATH" 中。
- 运行 `valet install` 命令来配置和安装 Valet 和 DnsMasq,并注册 Valet 后台服务,随系统运行自行启动。
安装完 Valet 后,可以尝试使用类似 `ping foobar.test` 的命令在终端上 ping 任何一个 `*.test` 的域名。如果 Valet 安装正确,可以在终端上看到来自 `127.0.0.1` 的响应。
每次机器启动时,Valet 会自动启动其进程。所以只要完成了 Valet 的初始化,就无需再次运行 `valet start` 或 `valet install`。
#### 使用其它域名
默认情况下,Valet 使用 `.test` 顶级域名为你的项目提供服务。如果你想使用其它域名,可以使用 `valet domain tld-name` 命令。
例如,如果你想使用 `.app` 来代替 `.test`,运行 `valet domain app`,Valet 会自动将站点顶级域名改为 `*.app` 。
#### 数据库
如果你要使用数据库,请在终端运行 `brew install mysql@5.7` 安装 MySQL。一旦安装完成,你可以使用 `brew services start mysql` 命令启动MySQL。然后,你可以使用 `root` 用户名和空字符串密码连接到 `127.0.0.1` 的数据库。
#### PHP 版本
Valet 允许你使用 `valet use php@version` 命令来切换 PHP 版本。如果指定版本尚未安装,Valet 将通过 Brew 来安装指定的 PHP 版本:
valet use php@7.2
valet use php
### 升级
你可以在终端使用 `composer global update` 命令来更新 Valet。升级后,如有需要,最好再次运行 valet install ,以便 Valet 对配置文件进行升级。
#### 升级到 Valet 2.0
Valet 2.0 将 Valet 底层的 Web 服务器从 Caddy 转移到 Nginx。升级到此版本之前,你应该运行以下命令停止并卸载现有的 Caddy 进程:
valet stop
valet uninstall
接下来,就根据你采用的安装方式来升级 Valet (通常是通过 Git 或 Composer )。如果是通过 Composer 安装了 Valet ,则应使用以下命令更新到最新的主要版本:
composer global require laravel/valet
如果更新了 Valet 的源码,你应该执行 install 命令:
valet install
valet restart
升级过后,可能需要重新设置或重新链接你的站点。
## 服务站点
安装了 Valet 之后,你就可以开始设置站点。Valet 提供两个命令来为 Laravel 的站点提供服务: `park` 和 `link`。
**`park` 命令**
- 运行 `mkdir ~/Sites` 命令在 Mac 上创建一个新的目录。接下来,运行 `cd ~/Sites` 和 `valet park` 将当前的工作目录作为 Valet 搜索站点的路径。
- 接下来,在这个目录中创建一个新的 Laravel 站点:`laravel new blog`。
- 在浏览器中打开 `http://blog.test`。
**就这么多。** 现在,你在 『parked』的目录中创建的任何 Laravel 项目都将自动使用 `http://folder-name.test` 这种方式访问。
**`link` 命令**
如果要在目录中提供单个站点而不是整个目录,就使用 link 命令。
- 要使用该命令,先在终端里切换到你的某个项目并运行 `valet link app-name`。Valet 会在 `~/.valet/Sites` 中创建一个符号链接指向当前的目录。
- 运行 `link` 命令后,你可以在浏览器通过 `http://app-name.test` 访问站点。
运行 `valet links` 命令可以查看所有目录链接的列表。你还可以使用 `valet unlink app-name` 来删除符号链接。
> {tip} 你可以使用 `valet link` 将多个(子)域名指向同一个应用。要添加子域名或其它域名到应用,可以在应用目录下运行 `valet link subdomain.app-name`。
**使用 TLS 保护站点**
默认情况下,Valet 服务站点通过纯 HTTP 的方式。但是,如果你想一个站点使用 HTTP/2 通过加密 TLS 提供服务,使用 `secure` 命令。例如,如果你的站点通过 Valet 在 `laravel.test` 域上提供服务,你应当运行如下的命令去保护它:
```bash
valet secure laravel
```
要一个站点『解除保护』并恢复为通过纯 HTTP 提供服务它的流量,使用 `unsecure` 命令。与 `secure` 命令一样,该命令接受你希望去解除保护的主机名称:
```bash
valet unsecure laravel
```
## 共享站点
Valet 甚至包括与世界共享你的本地站点的命令。一旦安装 Valet 后无需安装其它软件。
要共享站点,在终端中导航你的站点目录并运行 `valet share` 命令。一个公开可访问的 URL 将被插入到剪贴板中,并可以直接粘贴到你的浏览器中。仅此而已。
要停止共享你的站点,请按 `Control + C` 去取消该过程。
## 自定义 Valet 驱动
你可以编写你自己的 Valet『驱动』来为 Valet 原本不支持的其它框架或 CMS 上运行的 PHP 应用程序提供服务。当你安装 Valet 时,会创建一个包含 `SampleValetDriver.php` 文件的 `~/.config/valet/Drivers` 目录。该文件包含一个示例驱动程序实现,演示了如何编写一个自定义的驱动程序。编写驱动程序仅需要你去实现三个方法:`serves`,`isStaticFile` 和 `frontControllerPath`。
这三个方法都接受 `$sitePath`,`$siteName` 和 `$uri` 值作为参数。`$sitePath` 是你的机器上提供站点的完全限定路径。比如 `/Users/Lisa/Sites/my-project`。`$siteName` 是域(`my-project`)的『主机』/『站点名称』部分。`$uri` 是即将到来的请求 URL(/foo/bar)。
一旦你完成你的自定义 Valet 驱动,使用 `FrameworkValetDriver.php` 命名约定将它放置在 `~/.config/valet/Drivers` 目录中。例如,如果你为 WordPress 编写了一个自定义的 valet 驱动,你的文件名称应该是 `WordPressValetDriver.php`。
我们来看看自定义的 Valet 驱动程序应该实现的每种方法的示例实现。
#### `serves` 方法
如果你的驱动程序应当处理即将到来的请求时, `serves` 方法应该返回 `true`。否则,此方法应当返回 `false`。因此,在此方法中,你应该你企图确定给定的 `$sitePath` 是否包含你尝试提供的类型的项目。
例如,让我们假装正在编写一个 `WordPressValetDriver`。我们的 `serves` 方法可能看起来如下所示:
```php
/**
* 确定驱动程序是否满足请求。
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return bool
*/
public function serves($sitePath, $siteName, $uri)
{
return is_dir($sitePath.'/wp-admin');
}
```
#### `isStaticFile` 方法
`isStaticFile` 应当确定即将到来的请求是否针对一个『静态』文件,比如:图片和样式表。如果文件是静态的,此方法应当返回静态文件在磁盘上的完全限定路径。如果即将到来的请求不是针对一个静态文件,这个方法应当返回 `false`:
```php
/**
* 确定即将到来的请求是否针对静态文件。
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return string|false
*/
public function isStaticFile($sitePath, $siteName, $uri)
{
if (file_exists($staticFilePath = $sitePath.'/public/'.$uri)) {
return $staticFilePath;
}
return false;
}
```
> {note} 如果 `serves` 方法对即将到来的请求且请求 URI 不是 `/` 返回 `true` 时,才会调用 `isStaticFile` 方法。
#### `frontControllerPath` 方法
`frontControllerPath` 方法应当返回你的应用程序的『前端控制器』完全限定的路径,它通常是你的 『index.php』文件或者等效的文件:
```php
/**
* 获取对应用程序的前端控制器的完全解析路径。
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return string
*/
public function frontControllerPath($sitePath, $siteName, $uri)
{
return $sitePath.'/public/index.php';
}
```
### 本地驱动
如果你想为单个应用程序自定义 Valet 驱动程序,在应用程序的根目录下创建一个 `LocalValetDriver.php` 文件。你的自定义驱动程序可以扩展 `ValetDriver` 基类或者继承一个现有的应用程序的特定驱动程序,比如:`LaravelValetDriver`:
```php
class LocalValetDriver extends LaravelValetDriver
{
/**
* 确定驱动程序是否满足请求。
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return bool
*/
public function serves($sitePath, $siteName, $uri)
{
return true;
}
/**
* 获取对应用程序的前端控制器的完全解析路径。
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return string
*/
public function frontControllerPath($sitePath, $siteName, $uri)
{
return $sitePath.'/public_html/index.php';
}
}
```
## 其它 Valet 命令
| 命令 | 描述 |
| :---------------- | :----------------------------------------------------- |
| `valet forget` | 从一个『驻留』目录运行此命令,从驻留目录列表将其它移除 |
| `valet paths` | 查看所有『驻留』路径 |
| `valet restart` | 重启 Valet 守护进程 |
| `valet start` | 开启 Valet 守护进程 |
| `valet stop` | 停止 Valet 守护进程 |
| `valet uninstall` | 完成卸载 Valet 守护进程 |