├── .editorconfig
├── .gitignore
├── about.md
├── apis.md
├── artisan.md
├── authentication.md
├── authorization.md
├── billing.md
├── blade.md
├── broadcasting.md
├── cache.md
├── collections.md
├── configuration.md
├── container.md
├── contracts.md
├── contributing.md
├── contributions.md
├── controllers.md
├── csrf.md
├── database-testing.md
├── database.md
├── deployment.md
├── documentation.md
├── dusk.md
├── eloquent-collections.md
├── eloquent-mutators.md
├── eloquent-relationships.md
├── eloquent-resources.md
├── eloquent-serialization.md
├── eloquent.md
├── encryption.md
├── envoy.md
├── errors.md
├── events.md
├── facades.md
├── filesystem.md
├── frontend.md
├── hashing.md
├── helpers.md
├── homestead.md
├── horizon.md
├── http-tests.md
├── installation.md
├── license.md
├── lifecycle.md
├── links.php
├── localization.md
├── mail.md
├── middleware.md
├── migrations.md
├── mix.md
├── mocking.md
├── notifications.md
├── packages.md
├── pagination.md
├── passport.md
├── passwords.md
├── providers.md
├── queries.md
├── queues.md
├── readme.md
├── redirects.md
├── redis.md
├── releases.md
├── requests.md
├── responses.md
├── routing.md
├── scheduling.md
├── scout.md
├── seeding.md
├── session.md
├── socialite.md
├── structure.md
├── testing.md
├── upgrade.md
├── urls.md
├── valet.md
├── validation.md
└── views.md
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 4
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = false
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/about.md:
--------------------------------------------------------------------------------
1 | # Laravel 5.5 中文文档
2 | ## 说明
3 |
4 | 为了更好的阅读文档,请查看 [Laravel China 文档导读](https://laravel-china.org/topics/2095)。
5 |
6 | 此文档由 [Laravel China 社区](https://laravel-china.org) 用户协同翻译产生,本次 5.5 版本翻译的完整参与人员列表请见 :[Laravel 5.5 译者](https://laravel-china.org/roles/12) 。
7 |
8 | > 感谢这些可爱的译者,感谢他们的热情。
9 |
10 | ### 相关讨论
11 |
12 | * [Laravel 5.5 文档翻译召集](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)
13 | * [Laravel 5.5 中文文档翻译完成](#)
14 |
15 | ## 排版规范
16 |
17 | 此文档遵循 [中文排版指南](https://github.com/sparanoid/chinese-copywriting-guidelines) 规范,并在此之上遵守以下约定:
18 |
19 | * 英文的左右保持一个空白,避免中英文字黏在一起;
20 | * 使用全角标点符号;
21 | * 严格遵循 Markdown 语法;
22 | * 原文中的双引号(" ")请代换成中文的引号(「」符号怎么打出来见 [这里](http://zhihu.com/question/19755746/answer/27233392));
23 | * 「`加亮`」和「**加粗**」和「[链接]()」都需要在左右保持一个空格。
24 |
25 | ## 翻译对照列表
26 |
27 | 按照英文字母排序。
28 |
29 | ### A
30 |
31 | - Aggregate 聚合
32 | - Array 数组
33 | - Artisan (命令,不翻)
34 | - Argument 参数
35 | - Assets 资源文件
36 | - Authorization 用户认证
37 | - Adapter 接口
38 |
39 | ### B
40 |
41 | - Blade (专为 Laravel 发明的 PHP 模板引擎,不翻)
42 | - Bundle (上一代的 package 名称,不翻)
43 | - Binding 绑定
44 |
45 | ### C
46 |
47 | - Cache 缓存
48 | - Call 调用
49 | - Callback 回调
50 | - Classes 类
51 | - CLI 命令行界面
52 | - Command 命令
53 | - Command Line 命令行
54 | - Component 组件
55 | - Console 终端
56 | - Context 情境
57 | - Controller 控制器
58 | - Controller Action 控制器行为
59 | - constructor 构造函数
60 | - Cookie (不翻)
61 | - Composer (开源项目名称,不翻)
62 | - Credentials 凭证
63 | - Closure 闭包
64 | - Configuration 配置信息
65 | - Chain 链式
66 | - Chain Methods 链式调用
67 | - Contracts 契约
68 |
69 | ### D
70 |
71 | - Database-Transactions 数据库事务
72 | - Deferred Providers 延迟提供器
73 | - Driver 驱动
74 | - Dependency Injection 依赖注入
75 |
76 | ### E
77 |
78 | - Event 事件
79 | - Extend 拓展/继承
80 | - Extension 扩展
81 | - Eloquent (不翻)
82 | - Exception 异常
83 | - Echo (不翻)
84 | - Elixir (不翻)
85 |
86 | ### F
87 |
88 | - Facades (不翻)
89 | - Framework 框架
90 | - Filter 过滤器
91 | - Form 表单
92 | - Function 函数
93 |
94 | ### G
95 |
96 | - Guide 指南
97 | - Guard 看守器
98 |
99 | ### H
100 |
101 | - Helper 辅助函数
102 | - Hash 哈希 (可不翻)
103 | - Homestead (不翻)
104 | - Header 标头
105 | - Hook 钩子
106 |
107 | ### I
108 |
109 | - Instance 实例
110 | - IoC (不翻)
111 | - inheritance 继承
112 | - implements 实现
113 |
114 | ### J
115 |
116 | - Job 任务
117 |
118 | ### K
119 |
120 | - Key 键
121 |
122 | ### L
123 |
124 | - Laravel (不翻)
125 | - Listener 监听器
126 | - Library 类库
127 |
128 | ### M
129 |
130 | - Method 方法
131 | - Migration 迁移
132 | - Model 模型
133 | - Middleware 中间件
134 |
135 | ### N
136 |
137 | - Namespace 命名空间
138 |
139 | ### O
140 |
141 | - Object 对象
142 |
143 | ### P
144 |
145 | - Package 扩展包
146 | - Packagist (开源项目名称,不翻)
147 | - Provider 提供器
148 | - Prefix 前缀
149 | - Presenter (不翻)
150 | - Pipeline 管道
151 | - Policies 策略
152 | - Passport(不翻)
153 |
154 | ### Q
155 |
156 | - Queue 队列
157 | - Query Builder 查询构造器
158 |
159 | ### R
160 |
161 | - Route / Routing 路由
162 | - Router 路由器
163 | - Request 请求
164 | - Response 响应
165 | - Resolved 解析
166 | - Repository (不翻)
167 | - Redirect 重定向
168 | - (Database's) Rollback 还原
169 |
170 | ### S
171 |
172 | - Schema 数据库结构
173 | - Service 服务
174 | - Service Container 服务容器
175 | - Service Providers 服务提供器
176 | - Session 会话 (可不翻)
177 | - Seed 数据填充
178 | - Scheduler 调度器
179 | - Scout (不翻)
180 |
181 | ### T
182 |
183 | - Tag 标签
184 | - Table 数据表
185 | - Templates 模板
186 | - Terminal 终端
187 | - Token 令牌
188 | - Timestamps 时间戳
189 | - Type-hint 类型提示
190 | - Trait (不翻)
191 | - Ternary statement 三元运算符
192 | - Throw (Exception) 拋出(异常)
193 |
194 | ### V
195 |
196 | - Vagrant (开源项目名称,不翻)
197 | - Vagrant Box (开源项目名称,不翻)
198 | - View 视图
199 | - Vendor 供应商
200 | - View Composer/Creator 视图合成器/构造器
201 |
202 | ### W
203 |
204 | - Workbench (开源项目名称,不翻)
205 | - Webhooks (不翻)
206 | - Word Factor 加密系数
207 | - Webpack (不翻)
208 |
209 |
210 | ---
211 |
212 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
213 | >
214 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
215 | >
216 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/apis.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/laravel-china/laravel-docs/2a2f96359461190c6a51c311ed8c918e10d0f4e5/apis.md
--------------------------------------------------------------------------------
/configuration.md:
--------------------------------------------------------------------------------
1 | # Laravel 的配置信息
2 |
3 | - [介绍](#introduction)
4 | - [环境配置](#environment-configuration)
5 | - [检索环境配置](#retrieving-environment-configuration)
6 | - [确定当前环境](#determining-the-current-environment)
7 | - [访问配置值](#accessing-configuration-values)
8 | - [配置缓存](#configuration-caching)
9 | - [维护模式](#maintenance-mode)
10 |
11 |
12 | ## 介绍
13 |
14 | Laravel 框架的所有配置文件都保存在 `config` 目录中。 每个选项都有说明,你可随时查看这些文件并熟悉都有哪些配置选项可供你使用。
15 |
16 |
17 | ## 环境配置
18 |
19 | 对于应用程序运行的环境来说,不同的环境有不同的配置通常是很有用的。 例如,你可能希望在本地使用的缓存驱动不同于生产服务器所使用的缓存驱动。
20 |
21 | Laravel 利用 Vance Lucas 的 PHP 库 [DotEnv](https://github.com/vlucas/phpdotenv) 使得此项功能的实现变得非常简单。在新安装好的 Laravel 应用程序中,其根目录会包含一个 `.env.example` 文件。如果是通过 Composer 安装的 Laravel,该文件会自动更名为 `.env`。否则,需要你手动更改一下文件名。
22 |
23 | 你的 `.env` 文件不应该提交到应用程序的源代码控制系统中,因为每个使用你的应用程序的开发人员 / 服务器可能需要有一个不同的环境配置。此外,在入侵者获得你的源代码控制仓库的访问权的情况下,这会成为一个安全隐患,因为任何敏感的凭据都被暴露了。
24 |
25 | 如果是团队开发,则可能希望应用程序中仍包含 ` .env.example` 文件。因为通过在示例配置文件中放置占位值,团队中的其他开发人员可以清楚地看到哪些环境变量是运行应用程序所必需的。你也可以创建一个 `.env.testing` 文件,当运行 PHPUnit 测试或以 `--env=testing` 为选项执行 Artisan 命令时,该文件将覆盖 `.env` 文件中的值。
26 |
27 | > {tip} `.env` 文件中的所有变量都可被外部环境变量(比如服务器级或系统级环境变量)所覆盖。
28 |
29 |
30 | ### 检索环境配置
31 |
32 | 当应用程序收到请求时,`.env` 文件中列出的所有变量将被加载到 PHP 的超级全局变量 `$ _ENV` 中。你可以使用 `env` 函数检索这些变量的值。事实上,如果你查看 Laravel 的配置文件,你就能注意到有数个选项已经使用了这个函数:
33 |
34 | 'debug' => env('APP_DEBUG', false),
35 |
36 | 传递给 `env` 函数的第二个值是「默认值」。如果给定的键不存在环境变量,则会使用该值。
37 |
38 |
39 | ### 确定当前环境
40 |
41 | 应用程序当前所处环境是通过 `.env` 文件中的 `APP_ENV` 变量确定的。你可以通过 `App` [facade](/docs/{{version}}/facades) 中的 `environment` 方法来访问此值:
42 |
43 | $environment = App::environment();
44 |
45 | 你还可以传递参数给 `environment` 方法,以检查当前的环境配置是否与给定值匹配。 如果与给定值匹配,该方法将返回 `true`:
46 |
47 | if (App::environment('local')) {
48 | // 环境为 local
49 | }
50 |
51 | if (App::environment(['local', 'staging'])) {
52 | // 环境为 local 或 staging
53 | }
54 |
55 | > {tip} 应用程序当前所处环境检测可以被服务器级的 `APP_ENV` 环境变量覆盖。这为相同的应用程序配置不同的环境时是非常有用的,这样你可以在你的服务器配置中为给定的主机设置与其匹配的给定的环境。
56 |
57 |
58 | ## 访问配置值
59 |
60 | 你可以轻松地在应用程序的任何位置使用全局 `config` 函数来访问配置值。配置值的访问可以使用「点」语法,这其中包含了要访问的文件和选项的名称。还可以指定默认值,如果配置选项不存在,则返回默认值:
61 |
62 | $value = config('app.timezone');
63 |
64 | 要在运行时设置配置值,传递一个数组给 `config` 函数:
65 |
66 | config(['app.timezone' => 'America/Chicago']);
67 |
68 |
69 | ## 配置缓存
70 |
71 | 为了给你的应用程序提升速度,你应该使用 Artisan 命令 `config:cache` 将所有的配置文件缓存到单个文件中。这会把你的应用程序中所有的配置选项合并成一个单一的文件,然后框架会快速加载这个文件。
72 |
73 | 通常来说,你应该把运行 `php artisan config:cache` 命令作为生产环境部署常规的一部分。这个命令不应在本地开发环境下运行,因为配置选项在应用程序开发过程中是经常需要被更改的。
74 |
75 | > {note} 如果在部署过程中执行 `config:cache` 命令,那你应该确保只从配置文件内部调用 `env` 函数。
76 |
77 |
78 | ## 维护模式
79 |
80 | 当应用程序处于维护模式时,所有对应用程序的请求都显示为一个自定义视图。这样可以在更新或执行维护时轻松地「关闭」你的应用程序。 维护模式检查包含在应用程序的默认中间件栈中。如果应用程序处于维护模式,则将抛出一个状态码为 503 的 `MaintenanceModeException` 异常。
81 |
82 | 要启用维护模式,只需执行下面的 Artisan 命令 `down`:
83 |
84 | php artisan down
85 |
86 | 你还可以向 down 命令提供 `message` 和 `retry` 选项。其中 message 选项的值可用于显示或记录自定义消息,而 retry 值可用于设置 HTTP 请求头中 `Retry-After` 的值:
87 |
88 | php artisan down --message="Upgrading Database" --retry=60
89 |
90 | 要关闭维护模式,请使用 `up` 命令:
91 |
92 | php artisan up
93 |
94 | > {tip} 你可以通过修改 `resources/views/errors/503.blade.php` 模板文件来自定义默认维护模式模板。
95 |
96 | #### 维护模式和队列
97 |
98 | 当应用程序处于维护模式时,不会处理 [队列任务](/docs/{{version}}/queues)。而这些任务会在应用程序退出维护模式后再继续处理。
99 |
100 | #### 维护模式的替代方案
101 |
102 | 维护模式会导致应用程序有数秒的停机(不响应)时间,因此你可以考虑使用像 [Envoyer](https://envoyer.io) 这样的替代方案,以便与 Laravel 完成零停机时间部署。
103 |
104 | ## 译者署名
105 | | 用户名 | 头像 | 职能 | 签名 |
106 | | --- | --- | --- | --- |
107 | | [@痛饮狂歌](https://laravel-china.org/users/7636) |
| 翻译 | 独立开发者,全栈工程师 |
108 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
109 |
110 |
111 |
112 | ---
113 |
114 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
115 | >
116 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
117 | >
118 | > 文档永久地址: https://d.laravel-china.org
119 |
--------------------------------------------------------------------------------
/container.md:
--------------------------------------------------------------------------------
1 | # Laravel 服务容器解析
2 |
3 | - [简介](#introduction)
4 | - [绑定](#binding)
5 | - [绑定基础](#binding-basics)
6 | - [绑定接口实现](#binding-interfaces-to-implementations)
7 | - [上下文绑定](#contextual-binding)
8 | - [标记](#tagging)
9 | - [解析](#resolving)
10 | - [Make 方法](#the-make-method)
11 | - [自动注入](#automatic-injection)
12 | - [容器事件](#container-events)
13 | - [PSR-11](#psr-11)
14 |
15 |
16 | ## 简介
17 |
18 | Laravel 服务容器是用于管理类的依赖和执行依赖注入的工具。依赖注入这个花俏名词实质上是指:类的依赖项通过构造函数,或者某些情况下通过「setter」方法「注入」到类中。
19 |
20 | 来看一个简单的例子:
21 |
22 | users = $users;
48 | }
49 |
50 | /**
51 | * 显示指定用户的 profile。
52 | *
53 | * @param int $id
54 | * @return Response
55 | */
56 | public function show($id)
57 | {
58 | $user = $this->users->find($id);
59 |
60 | return view('user.profile', ['user' => $user]);
61 | }
62 | }
63 |
64 | 在这个例子中,控制器 `UserController` 需要从数据源中获取 users 。因此,我们要**注入**可以获取 users 的服务。在这种情况下,`UserRepository` 可能是使用 [Eloquent](/docs/{{version}}/eloquent) 从数据库中获取 user 信息。因为 Repository 是通过 `UserRepository` 注入的,所以我们可以轻易地将其切换为另一个实现。这种注入方式的便利之处还体现在当我们为应用编写测试时,我们还可以轻松地「模拟」或创建 `UserRepository` 的虚拟实现。
65 |
66 | 想要构建强大的大型应用,至关重要的一件事是:要深刻的理解 Laravel 服务容器。当然,为 Laravel 的核心代码做出贡献也一样。
67 |
68 |
69 |
70 | ## 绑定
71 |
72 |
73 | ### 绑定基础
74 |
75 | 因为几乎所有服务容器都是在 [服务提供器](/docs/{{version}}/providers) 中注册绑定的,所以文档中大多数例子都是使用了在服务提供器中绑定的容器。
76 |
77 | > {tip} 如果类没有依赖任何接口,就没有必要将类绑定到容器中。容器不需要指定如何构建这些对象,因为它可以使用反射自动解析这些对象。
78 |
79 | #### 简单绑定
80 |
81 | 在服务提供器中,你可以通过 `$this->app` 属性访问容器。我们可以通过 `bind` 方法注册绑定,传递我们想要注册的类或接口名称再返回类的实例的 `Closure` :
82 |
83 | $this->app->bind('HelpSpot\API', function ($app) {
84 | return new HelpSpot\API($app->make('HttpClient'));
85 | });
86 |
87 | 注意,我们接受容器本身作为解析器的参数。然后,我们可以使用容器来解析正在构建的对象的子依赖。
88 |
89 | #### 绑定一个单例
90 |
91 | `singleton` 方法将类或接口绑定到只能解析一次的容器中。绑定的单例被解析后,相同的对象实例会在随后的调用中返回到容器中:
92 |
93 | $this->app->singleton('HelpSpot\API', function ($app) {
94 | return new HelpSpot\API($app->make('HttpClient'));
95 | });
96 |
97 | #### 绑定实例
98 |
99 | 你也可以使用 `instance` 方法将现有对象实例绑定到容器中。给定的实例会始终在随后的调用中返回到容器中:
100 |
101 | $api = new HelpSpot\API(new HttpClient);
102 |
103 | $this->app->instance('HelpSpot\API', $api);
104 |
105 | #### 绑定初始数据
106 |
107 | 当你有一个类不仅需要接受一个注入类,还需要注入一个基本值(比如整数)。你可以使用上下文绑定来轻松注入你的类需要的任何值:
108 |
109 | $this->app->when('App\Http\Controllers\UserController')
110 | ->needs('$variableName')
111 | ->give($value);
112 |
113 |
114 |
115 | ### 绑定接口到实现
116 |
117 | 服务容器有一个强大的功能,就是将接口绑定到给定实现。例如,如果我们有一个 `EventPusher` 接口和一个 `RedisEventPusher` 实现。编写完接口的 `RedisEventPusher` 实现后,我们就可以在服务容器中注册它,像这样:
118 |
119 | $this->app->bind(
120 | 'App\Contracts\EventPusher',
121 | 'App\Services\RedisEventPusher'
122 | );
123 |
124 | 这么做相当于告诉容器:当一个类需要实现 `EventPusher` 时,应该注入 `RedisEventPusher`。现在我们就可以在构造函数或者任何其他通过服务容器注入依赖项的地方使用类型提示注入 `EventPusher` 接口:
125 |
126 | use App\Contracts\EventPusher;
127 |
128 | /**
129 | * 创建一个新的类实例
130 | *
131 | * @param EventPusher $pusher
132 | * @return void
133 | */
134 | public function __construct(EventPusher $pusher)
135 | {
136 | $this->pusher = $pusher;
137 | }
138 |
139 |
140 | ### 上下文绑定
141 |
142 | 有时候,你可能有两个类使用了相同的接口,但你希望每个类都能注入不同的实现。例如,两个控制器可能需要依赖不同的 `Illuminate\Contracts\Filesystem\Filesystem` [契约](/docs/{{version}}/contracts) 实现。 Laravel 提供了一个简单、优雅的接口来定义这个行为:
143 |
144 | use Illuminate\Support\Facades\Storage;
145 | use App\Http\Controllers\PhotoController;
146 | use App\Http\Controllers\VideoController;
147 | use Illuminate\Contracts\Filesystem\Filesystem;
148 |
149 | $this->app->when(PhotoController::class)
150 | ->needs(Filesystem::class)
151 | ->give(function () {
152 | return Storage::disk('local');
153 | });
154 |
155 | $this->app->when(VideoController::class)
156 | ->needs(Filesystem::class)
157 | ->give(function () {
158 | return Storage::disk('s3');
159 | });
160 |
161 |
162 | ### 标记
163 |
164 | 有时候,你可能需要解析某个「分类」下的所有绑定。例如,你正在构建一个报表的聚合器,它接收一个包含不同 `Report` 接口实现的数组。注册了 `Report` 实现后,你可以使用 `tag` 方法为其分配标签:
165 |
166 | $this->app->bind('SpeedReport', function () {
167 | //
168 | });
169 |
170 | $this->app->bind('MemoryReport', function () {
171 | //
172 | });
173 |
174 | $this->app->tag(['SpeedReport', 'MemoryReport'], 'reports');
175 |
176 | 服务被标记后,你可以通过 `tagged` 方法轻松地将它们全部解析:
177 |
178 | $this->app->bind('ReportAggregator', function ($app) {
179 | return new ReportAggregator($app->tagged('reports'));
180 | });
181 |
182 |
183 | ## 解析
184 |
185 |
186 | #### `make` 方法
187 |
188 | 你可以使用 `make` 方法将容器中的类实例解析出来。`make` 方法接受要解析的类或接口的名称:
189 |
190 | $api = $this->app->make('HelpSpot\API');
191 |
192 | 如果你的代码处于不能访问 `$app` 变量的位置,你可以使用全局的辅助函数 `resolve`:
193 |
194 | $api = resolve('HelpSpot\API');
195 |
196 | 如果你的某些类的依赖项不能通过容器去解析,那你可以通过将它们作为关联数组传递到 `makeWith` 方法来注入它们。
197 |
198 | $api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);
199 |
200 |
201 | #### 自动注入
202 |
203 | 你可以简单地使用「类型提示」的方式在由容器解析的类的构造函数中添加依赖项,包括 [控制器](/docs/{{version}}/controllers)、[事件监听器](/docs/{{version}}/events)、[队列任务](/docs/{{version}}/queues)、[中间件](/docs/{{version}}/middleware) 等。 事实上,这是你的大多数对象也应该由容器解析。
204 |
205 | 例如,你可以在控制器的构造函数中对应用程序定义的 Repository 使用类型提示。Repository 会被自动解析并注入到类中:
206 |
207 | users = $users;
229 | }
230 |
231 | /**
232 | * 显示指定 ID 的用户信息。
233 | *
234 | * @param int $id
235 | * @return Response
236 | */
237 | public function show($id)
238 | {
239 | //
240 | }
241 | }
242 |
243 |
244 | ## 容器事件
245 |
246 | 每当服务容器解析一个对象时触发一个事件。你可以使用 `resolving` 方法监听这个事件:
247 |
248 | $this->app->resolving(function ($object, $app) {
249 | // 当容器解析任何类型的对象时调用...
250 | });
251 |
252 | $this->app->resolving(HelpSpot\API::class, function ($api, $app) {
253 | // 当容器解析类型为「HelpSpot\API」的对象时调用...
254 | });
255 |
256 | 如你所见,被解析的对象会被传递给回调中,让你在对象被传递出去之前可以在对象上设置任何属性。
257 |
258 |
259 |
260 | ## PSR-11
261 |
262 | Laravel 的服务容器实现了 [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md) 接口。因此,你可以对 PSR-11容器接口类型提示来获取 Laravel 容器的实例:
263 |
264 | use Psr\Container\ContainerInterface;
265 |
266 | Route::get('/', function (ContainerInterface $container) {
267 | $service = $container->get('Service');
268 |
269 | //
270 | });
271 |
272 | > {note} 如果标签没有明确绑定到容器中,那么调用 `get` 方法时会抛出异常。
273 |
274 | ## 译者署名
275 |
276 | | 用户名 | 头像 | 职能 | 签名 |
277 | |---|---|---|---|
278 | | [@kair](http://www.jianshu.com/u/7fdb641c0d01) |
| 翻译 | [@kair](https://github.com/JKair) |
279 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
280 |
281 |
282 | ---
283 |
284 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
285 | >
286 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
287 | >
288 | > 文档永久地址: https://d.laravel-china.org
289 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Laravel 的贡献索引
2 |
3 | If you are submitting documentation for the **current stable release**, submit it to the corresponding branch. For example, documentation for Laravel 5.1 would be submitted to the `5.1` branch. Documentation intended for the next release of Laravel should be submitted to the `master` branch.
--------------------------------------------------------------------------------
/contributions.md:
--------------------------------------------------------------------------------
1 | # Laravel 源代码贡献指南
2 |
3 | - [错误反馈](#bug-reports)
4 | - [核心开发讨论](#core-development-discussion)
5 | - [选择分支?](#which-branch)
6 | - [安全漏洞](#security-vulnerabilities)
7 | - [编码风格](#coding-style)
8 | - [PHPDoc](#phpdoc)
9 | - [StyleCI](#styleci)
10 |
11 |
12 | ## 错误反馈
13 |
14 | 为了鼓励积极协作,Laravel 强烈地鼓励使用 Pull Request 指出修改的内容,而不仅仅只是反馈错误。「错误反馈」也可以用 PR 来提交失败测试。
15 |
16 | 如果你要提交错误反馈,你的问题应该包含标题和明确的问题描述,并尽可能多的提供相关的信息和演示该问题的代码示例。错误反馈的目的是让你和其他人可以轻松地重现并修复错误。
17 |
18 | 请记住,错误反馈的初衷是让其它有相同问题的人能够和你协作解决问题。不要指望反馈错误后会很快有人修复它。创建错误反馈是能帮助你和其他人开始着手修复问题的途径。
19 |
20 | Laravel 源代码托管在 GitHub 上面,并且每个 Laravel 的项目都有自己的代码仓库:
21 |
22 |
23 | - [Laravel 应用](https://github.com/laravel/laravel)
24 | - [Laravel Art](https://github.com/laravel/art)
25 | - [Laravel 文档](https://github.com/laravel/docs)
26 | - [Laravel Cashier](https://github.com/laravel/cashier)
27 | - [Braintree 版 Laravel Cashier](https://github.com/laravel/cashier-braintree)
28 | - [Laravel Envoy](https://github.com/laravel/envoy)
29 | - [Laravel 框架](https://github.com/laravel/framework)
30 | - [Laravel Homestead](https://github.com/laravel/homestead)
31 | - [Laravel Homestead 构建脚本](https://github.com/laravel/settler)
32 | - [Laravel Passport](https://github.com/laravel/passport)
33 | - [Laravel 搜索系统](https://github.com/laravel/scout)
34 | - [Laravel Socialite](https://github.com/laravel/socialite)
35 | - [Laravel 网站](https://github.com/laravel/laravel.com)
36 |
37 |
38 |
39 | ## 核心开发讨论
40 |
41 | 如果你想提出现有的 Laravel 的功能建议或者改进,请到 Laravel Internals 的 [反馈栏](https://github.com/laravel/internals/issues) 讨论。如果你提出新功能,如果愿意,我们希望能请你至少实现一些完成该功能所需的代码。
42 |
43 | 有关错误、新功能和现有功能的实现的非正式讨论会在 [LaraChat](http://larachat.co) Slack 团队的 `#internals` 频道中进行。Laravel 的维护者 Taylor Otwell 通常都会在工作日的早上 8 点 到下午 5点( UTC-06:00 或 America/Chicago )出现在频道上,其它时间偶尔也会出现。
44 |
45 |
46 | ## 选择分支?
47 |
48 | **所有**错误修复都应该发送到最新的稳定分支或当前的 LTS 分支(5.5)上。错误修复**不**应该发送到 `master` 支,除非它们修复仅在即将发布的版本中存在的功能。
49 |
50 | 与当前 Laravel 版本**完全向后兼容**的**次要**功能可能会发送到最新的稳定分支。
51 |
52 | **主要的** 新功能都应该发送到 `master` 分支,它包含即将发布的 Laravel 版本。
53 |
54 | 如果不确定你的功能是主要的还是次要的,请咨询 [LaraChat](http://larachat.co) Slack 团队的 `#internals` 频道上的 Taylor Otwell。
55 |
56 |
57 | ## 安全漏洞
58 |
59 | 如果你发现 Laravel 存在安全漏洞,请发送电子邮件给Taylor Otwell: taylor@laravel.com。他会及时解决所有安全漏洞。
60 |
61 |
62 | ## 编码风格
63 |
64 | Laravel 遵循 [PSR-2](https://phphub.org/topics/2079) 编码规范和 [PSR-4](https://phphub.org/topics/2081) 自动加载规范。
65 |
66 |
67 | ### PHPDoc
68 |
69 | 以下是正确的 Laravel 注释的示例。请注意,`@param` 属性后跟两个空格、参数类型、两个空格,最后是变量名称:
70 |
71 | /**
72 | * 注册一个绑定到容器。
73 | *
74 | * @param string|array $abstract
75 | * @param \Closure|string|null $concrete
76 | * @param bool $shared
77 | * @return void
78 | */
79 | public function bind($abstract, $concrete = null, $shared = false)
80 | {
81 | //
82 | }
83 |
84 |
85 | ### StyleCI
86 |
87 | 别担心你的编码风格不够漂亮!在合并 PR 后 [StyleCI](https://styleci.io) 会自动修正样式后再合并到 Laravel 仓库中。这样使得我们可以专注于贡献内容本身而不是编码风格。
88 |
89 | ## 译者署名
90 |
91 | | 用户名 | 头像 | 职能 | 签名 |
92 | |---|---|---|---|
93 | | [Seven Du](https://github.com/medz) |
| 翻译 | 基于 Laravel 的社交开源系统 [ThinkSNS+](https://github.com/slimkit/thinksns-plus) 欢迎 Star。 |
94 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
95 |
96 |
97 | ---
98 |
99 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
100 | >
101 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
102 | >
103 | > 文档永久地址: https://d.laravel-china.org
104 |
--------------------------------------------------------------------------------
/csrf.md:
--------------------------------------------------------------------------------
1 | # Laravel 下的伪造跨站请求保护 CSRF
2 |
3 | - [简介](#csrf-introduction)
4 | - [CSRF 白名单](#csrf-excluding-uris)
5 | - [X-CSRF-Token](#csrf-x-csrf-token)
6 | - [X-XSRF-Token](#csrf-x-xsrf-token)
7 |
8 |
9 | ## 简介
10 |
11 | Laravel 可以轻松地保护应用程序免受 [跨站请求伪造](https://en.wikipedia.org/wiki/Cross-site_request_forgery) (CSRF) 的攻击。跨站请求伪造是一种恶意的攻击,它凭借已通过身份验证的用户身份来运行未经过授权的命令。
12 |
13 | Laravel 会自动为每个活跃用户的会话生成一个 CSRF「令牌」。该令牌用于验证经过身份验证的用户是否是向应用程序发出请求的用户。
14 |
15 | 任何情况下当你在应用程序中定义 HTML 表单时,都应该在表单中包含一个隐藏的 CSRF 令牌字段,以便 CSRF 保护中间件可以验证该请求。可以使用辅助函数 `csrf_field` 来生成令牌字段:
16 |
17 |
21 |
22 | 包含在 `web` 中间件组里的 `VerifyCsrfToken` [中间件](/docs/{{version}}/middleware)会自动验证请求里的令牌是否与存储在会话中令牌匹配。
23 |
24 | #### CSRF 令牌 & JavaScript
25 |
26 | 构建由 Javascript 驱动的应用时,可以很方便地让 Javascript HTTP 函数库在发起每一个请求时自动附上 CSRF 令牌。默认情况下, `resources/assets/js/bootstrap.js` 文件会用 Axios HTTP 函数库注册的 `csrf-token` meta 标签中的值。如果你不使用这个函数库,你需要手动为你的应用配置此行为。
27 |
28 |
29 | ## CSRF 白名单
30 |
31 | 有时候你可能希望设置一组并不需要 CSRF 保护的 URI。例如,如果你正在使用 [Stripe](https://stripe.com) 处理付款并使用了他们的 webhook 系统,你会需要从 CSRF 的保护中排除 Stripe Webhook 处理程序路由,因为 Stripe 并不会给你的路由发送 CSRF 令牌。
32 |
33 | 你可以把这类路由放到 `routes/web.php` 外,因为 `RouteServiceProvider` 的 `web` 中间件适用于该文件中的所有路由。不过,你也可以通过将这类 URI 添加到 `VerifyCsrfToken` 中间件中的 `$except` 属性来排除对这类路由的 CSRF 保护:
34 |
35 |
54 | ## X-CSRF-TOKEN
55 |
56 | 除了检查 POST 参数中的 CSRF 令牌外,`VerifyCsrfToken` 中间件还会检查 `X-CSRF-TOKEN` 请求头。你可以将令牌保存在 HTML `meta` 标签中:
57 |
58 |
59 |
60 | 然后你就可以使用类似 jQuery 的库自动将令牌添加到所有请求的头信息中。这可以为基于 AJAX 的应用提供简单、方便的 CSRF 保护:
61 |
62 | $.ajaxSetup({
63 | headers: {
64 | 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
65 | }
66 | });
67 |
68 | > {tip} 默认情况下, `resources/assets/js/bootstrap.js` 文件会用 Axios HTTP 函数库注册 `csrf-token` meta 标签中的值。如果你不使用这个函数库,则需要为你的应用手动配置此行为。
69 |
70 |
71 | ## X-XSRF-TOKEN
72 |
73 | Laravel 将当前的 CSRF 令牌存储在由框架生成的每个响应中包含的一个 `XSRF-TOKEN` cookie 中。为方便起见,你可以使用 cookie 值来设置 X-XSRF-TOKEN 请求头,而一些 JavaScript 框架和库(如 Angular 和 Axios)会自动将这个值添加到 `X-XSRF-TOKEN` 头中。
74 |
75 | ## 译者署名
76 | | 用户名 | 头像 | 职能 | 签名 |
77 | |---|---|---|---|
78 | | [@王凯波](http://weibo.com/wangkaibo) |
| 翻译 | 面向工资编程 [@wangkaibo](https://github.com/wangkaibo/) |
79 | | [@Lichmaker](https://laravel-china.org/users/16370) |
| 翻译 | Happy Coding! :) 我的微博:[神经考拉君](http://weibo.com/1779555595/) |
80 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
81 |
82 |
83 | ---
84 |
85 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
86 | >
87 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
88 | >
89 | > 文档永久地址: https://d.laravel-china.org
90 |
--------------------------------------------------------------------------------
/database-testing.md:
--------------------------------------------------------------------------------
1 | # Laravel 测试之 - 数据库测试
2 |
3 | - [简介](#introduction)
4 | - [每次测试后重置数据库](#resetting-the-database-after-each-test)
5 | - [创建模型工厂](#writing-factories)
6 | - [工厂状态](#factory-states)
7 | - [在测试中使用模型工厂](#using-factories)
8 | - [创建模型](#creating-models)
9 | - [持久化模型](#persisting-models)
10 | - [模型关联](#relationships)
11 | - [可用的断言方法](#available-assertions)
12 |
13 |
14 | ## 简介
15 |
16 | Laravel 提供了多种有用的工具来让你更容易的测试使用数据库的应用程序。首先,你可以使用 `assertDatabaseHas` 辅助函数,来断言数据库中是否存在与指定条件互相匹配的数据。举例来说,如果我们想验证 `users` 数据表中是否存在 `email` 值为 `sally@example.com` 的数据,我们可以按照以下的方式来做测试:
17 |
18 | public function testDatabase()
19 | {
20 | // 创建调用至应用程序...
21 |
22 | $this->assertDatabaseHas('users', [
23 | 'email' => 'sally@example.com'
24 | ]);
25 | }
26 |
27 | 你也可以使用 `assertDatabaseMissing` 辅助函数来断言数据不在数据库中。
28 |
29 | 当然,使用 `assertDatabaseHas` 方法及其它的辅助函数只是为了方便。你也可以随意使用 PHPUnit 内置的所有断言方法来扩充测试。
30 |
31 |
32 | ## 每次测试后重置数据库
33 |
34 | 在每次测试后重新设置数据库通常很有用,这样以前测试的数据不会干扰后续的测试。`RefreshDatabase` trait 会采用最优的方法来迁移你的测试数据库,这取决于你使用的是内存数据库还是传统数据库。在你的测试类中简单地引用这个 trait,一切都将为你处理:
35 |
36 | get('/');
56 |
57 | // ...
58 | }
59 | }
60 |
61 |
62 | ## 创建模型工厂
63 |
64 | 测试时,常常需要在运行测试之前写入一些数据到数据库中。创建测试数据时,除了手动的来设置每个字段的值,还可以使用 [Eloquent 模型](/docs/{{version}}/eloquent) 的「工厂」来设置每个属性的默认值。在开始之前,你可以先查看下应用程序的 `database/factories/UserFactory.php` 文件。此文件包含了一个现成的模型工厂定义:
65 |
66 | $factory->define(App\User::class, function (Faker\Generator $faker) {
67 | static $password;
68 |
69 | return [
70 | 'name' => $faker->name,
71 | 'email' => $faker->unique()->safeEmail,
72 | 'password' => $password ?: $password = bcrypt('secret'),
73 | 'remember_token' => str_random(10),
74 | ];
75 | });
76 |
77 | 在作为工厂定义的闭包中,你可以返回模型上所有属性的默认测试值。 闭包将接收 PHP 函数库 [Faker](https://github.com/fzaninotto/Faker) 的一个实例,它允许你方便地生成各种随机数据进行测试。
78 |
79 | 为了更好的组织代码,你也可以自己为每个数据模型创建对应的模型工厂类。例如,你可以在 `database/factories` 目录下创建 `UserFactory.php` 和 `CommentFactory.php` 文件。 Laravel 将会自动加载 `factories` 目录下的所有文件。
80 |
81 |
82 | ### 工厂状态
83 |
84 | 工厂状态可以让你任意组合你的模型工厂,仅需要做出适当差异化的修改,就可以达到让模型拥有多种不同的状态。例如,你的 `用户` 模型中可以修改某个默认属性值来达到标识一种 `欠款` 的状态。你可以使用 `state` 方法来进行这种状态转换。对于简单的工厂状态,你可以直接传入要修改的属性数组。
85 |
86 | $factory->state(App\User::class, 'delinquent', [
87 | 'account_status' => 'delinquent',
88 | ]);
89 |
90 | 如果你的工厂状态需要计算或者需要使用 `$faker` 实例,你可以使用闭包方法来实现状态属性的修改:
91 |
92 | $factory->state(App\User::class, 'address', function ($faker) {
93 | return [
94 | 'address' => $faker->address,
95 | ];
96 | });
97 |
98 |
99 | ## 在测试中使用模型工厂
100 |
101 |
102 | ### 创建模型
103 |
104 | 在模型工厂定义后,就可以在测试或是数据库的填充文件中,通过全局的 `factory` 函数来生成模型实例。接着让我们先来看看几个创建模型的例子。首先我们会使用 `make` 方法创建模型,但不将它们保存至数据库:
105 |
106 | public function testDatabase()
107 | {
108 | $user = factory(App\User::class)->make();
109 |
110 | // 在测试中使用模型...
111 | }
112 |
113 | 你也可以创建一个含有多个模型的集合,或创建一个指定类型的模型:
114 |
115 | // 创建一个 App\User 实例
116 | $users = factory(App\User::class, 3)->make();
117 |
118 | #### 应用模型工厂状态
119 |
120 | 你可能需要在你的模型中应用不同的 [模型工厂状态](#factory-states)。如果你想模型加上多种不同的状态,你只须指定每个你想添加的状态名称即可:
121 |
122 | $users = factory(App\User::class, 5)->states('delinquent')->make();
123 |
124 | $users = factory(App\User::class, 5)->states('premium', 'delinquent')->make();
125 |
126 | #### 重写模型属性
127 |
128 | 如果你想重写模型中的某些默认值,则可以传递一个包含数值的数组至 `make` 方法。只有指定的数值会被替换,其它剩余的数值则会按照模型工厂指定的默认值来设置:
129 |
130 | $user = factory(App\User::class)->make([
131 | 'name' => 'Abigail',
132 | ]);
133 |
134 |
135 | ### 持久化模型
136 |
137 | `create` 方法不仅会创建模型实例,同时会使用 Eloquent 的 `save` 方法来将它们保存至数据库:
138 |
139 | public function testDatabase()
140 | {
141 | // 创建一个 App\User 实例
142 | $user = factory(App\User::class)->create();
143 |
144 | // 创建 3 个 App\User 实例
145 | $users = factory(App\User::class, 3)->create();
146 |
147 | // 在测试中使用模型...
148 | }
149 |
150 | 同样的,你可以在数组传递至 `create` 方法时重写模型的属性
151 |
152 | $user = factory(App\User::class)->create([
153 | 'name' => 'Abigail',
154 | ]);
155 |
156 |
157 | ### 模型关联
158 |
159 | 在本例中,我们还会增加关联至我们所创建的模型。当使用 `create` 方法创建多个模型时,它会返回一个 Eloquent [集合实例](/docs/{{version}}/eloquent-collections),让你能够使用集合所提供的便利函数,像是 `each`:
160 |
161 | $users = factory(App\User::class, 3)
162 | ->create()
163 | ->each(function ($u) {
164 | $u->posts()->save(factory(App\Post::class)->make());
165 | });
166 |
167 | #### 关联和属性闭包
168 |
169 | 你可以使用闭包参数来创建模型关联。例如你想在创建一个 `Post` 时顺便创建一个 `User` 实例,可以这样定义:
170 |
171 | $factory->define(App\Post::class, function ($faker) {
172 | return [
173 | 'title' => $faker->title,
174 | 'content' => $faker->paragraph,
175 | 'user_id' => function () {
176 | return factory(App\User::class)->create()->id;
177 | }
178 | ];
179 | });
180 |
181 | 这些闭包也可以获取到生成的模型工厂包含的属性数组:
182 |
183 | $factory->define(App\Post::class, function ($faker) {
184 | return [
185 | 'title' => $faker->title,
186 | 'content' => $faker->paragraph,
187 | 'user_id' => function () {
188 | return factory(App\User::class)->create()->id;
189 | },
190 | 'user_type' => function (array $post) {
191 | return App\User::find($post['user_id'])->type;
192 | }
193 | ];
194 | });
195 |
196 |
197 | ## 可用的断言方法
198 |
199 | Laravel 为你的 [PHPUnit](https://phpunit.de/) 测试提供了一些数据库断言方法:
200 |
201 | 方法名 | 描述
202 | ------------- | -------------
203 | `$this->assertDatabaseHas($table, array $data);` | 断言数据库里含有指定数据。
204 | `$this->assertDatabaseMissing($table, array $data);` | 断言表里没有指定数据。
205 | `$this->assertSoftDeleted($table, array $data);` | 断言指定记录已经被软删除。
206 |
207 | ## 译者署名
208 |
209 | | 用户名 | 头像 | 职能 | 签名 |
210 | |---|---|---|---|
211 | | [@limxx](https://github.com/limxx) |
| 翻译 | Winter is coming. |
212 |
213 |
214 | ---
215 |
216 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
217 | >
218 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
219 | >
220 | > 文档永久地址: https://d.laravel-china.org
221 |
--------------------------------------------------------------------------------
/database.md:
--------------------------------------------------------------------------------
1 | # 数据库:入门
2 |
3 | - [简介](#introduction)
4 | - [配置](#configuration)
5 | - [读 & 写连接](#read-and-write-connections)
6 | - [使用多个数据库连接](#using-multiple-database-connections)
7 | - [运行原生 SQL 查询](#running-queries)
8 | - [查询事件监听](#listening-for-query-events)
9 | - [数据库事务](#database-transactions)
10 |
11 |
12 |
13 | ## 简介
14 |
15 | Laravel 能使用原生 SQL、[查询构造器](/docs/{{version}}/queries) 和 [Eloquent ORM](/docs/{{version}}/eloquent) 在各种数据库后台与数据库进行非常简单的交互。当前 Laravel 支持四种数据库:
16 |
17 |
18 |
19 | - MySQL
20 | - Postgres
21 | - SQLite
22 | - SQL Server
23 |
24 |
25 |
26 |
27 | ### 配置
28 |
29 | 数据库的配置文件放置在 `config/database.php` 文件中,你可以在此定义所有的数据库连接,并指定默认使用的连接。此文件内提供了大部分 Laravel 能支持的数据库配置示例。
30 |
31 | 默认情况下,Laravel 的示例 [环境配置](/docs/{{version}}/configuration#environment-configuration) 使用了 [Laravel Homestead](/docs/{{version}}/homestead)(这是一种小型虚拟机,能让你很方便地在本地进行 Laravel 的开发)。你可以根据本地数据库的需要修改这个配置。
32 |
33 | #### SQLite 配置
34 |
35 | 使用类似 `touch database/database.sqlite` 之类命令创建一个新的 SQLite 数据库之后,可以使用数据库的绝对路径配置环境变量来指向这个新创建的数据库:
36 |
37 | DB_CONNECTION=sqlite
38 | DB_DATABASE=/absolute/path/to/database.sqlite
39 |
40 |
41 |
42 | ### 读 & 写连接
43 |
44 | 如果你想使一个数据库连接只用于 SELECT ,另一个连接用于 INSERT、UPDATE、和 DELETE。那么在 Laravel 中无论你使用的是原生查询、查询构造器,还是 Eloquent ORM,你都能很轻松地实现这个需求。
45 |
46 | 看看下面这个例子如何配置读/写连接:
47 |
48 | 'mysql' => [
49 | 'read' => [
50 | 'host' => '192.168.1.1',
51 | ],
52 | 'write' => [
53 | 'host' => '196.168.1.2'
54 | ],
55 | 'sticky' => true,
56 | 'driver' => 'mysql',
57 | 'database' => 'database',
58 | 'username' => 'root',
59 | 'password' => '',
60 | 'charset' => 'utf8mb4',
61 | 'collation' => 'utf8mb4_unicode_ci',
62 | 'prefix' => '',
63 | ],
64 |
65 | 要注意的是,上面的示例中的配置数组中添加了三个键 : `read` 和 `write` 和 `sticky`。`read` 和 `write` 键都包含了一个键的值为 `host` 的数组。`read` 和 `write` 连接的其余数据库配置都在 `mysql` 这个主数组里面。
66 |
67 | 如果你想要覆盖主数组中的值,则只需将配置的内容移入 `read` 和 `write` 数组中即可。因此,在这种情况下,`192.168.1.1` 将被用作「读取」连接的主机,而 `192.168.1.2` 将被用于「写入」连接。这两个连接会共享数据库的凭证、前缀、字符集,以及在主 `mysql` 数组中的选项。
68 |
69 | **`sticky` 选项**
70 |
71 | `sticky` 是一个 *可选的* 选项,它可用于立即读取在当前请求周期内已写入数据库的记录。
72 |
73 | 如果 `sticky` 选项被启用,并且在当前的请求周期内在数据库执行过「写入」操作,那么任何「读取」的操作都将使用「写入」连接。这可以确保在请求周期内写入的任何数据可以在同一请求期间立即从数据库读回。这个选项的作用取决于应用程序的需求。
74 |
75 |
76 |
77 | ### 使用多个数据库连接
78 |
79 | 使用多个连接时,可以通过 `DB` facade 上的 `connection` 方法访问每个连接。传递给 `connection` 方法的 `name` 应该对应于 `config/database.php` 配置信息文件中列出的连接之一:
80 |
81 | $users = DB::connection('foo')->select(...);
82 |
83 | 你也可以在连接实例上使用 `getPdo` 方法访问底层的原生 PDO 实例 :
84 |
85 | $pdo = DB::connection()->getPdo();
86 |
87 |
88 |
89 | ## 运行原生 SQL 查询
90 |
91 | 配置好数据库连接后,可以使用 `DB` facade 运行查询。`DB` facade 为每种类型的查询提供了方法:`select`、`update`、`insert`、`delete` 和 `statement`。
92 | #### 运行 Select 查询
93 |
94 | 运行基础的查询语句,你可以使用 `DB` facade 上使用 `select` 方法:
95 |
96 | $users]);
115 | }
116 | }
117 |
118 | 传递到 `select` 方法的第一个参数是一个原生的 SQL 查询,而第二个参数则是传递需要绑定到查询中的参数值。通常,这些是 `where` 子句约束的值。参数绑定提供了对防止 SQL 注入的保护。
119 |
120 | `select` 方法将始终返回一个数组。数组中的每个结果都是一个PHP `StdClass` 对象,可以像下面这样访问结果的值:
121 |
122 | foreach ($users as $user) {
123 | echo $user->name;
124 | }
125 |
126 | #### 使用命名绑定
127 |
128 | 除了使用 `?` 来表示参数绑定外,你也可以使用命名绑定来执行一个查询:
129 |
130 | $results = DB::select('select * from users where id = :id', ['id' => 1]);
131 |
132 | #### 运行插入语句
133 |
134 | 可以在 `DB` facade 上使用 `insert` 方法来执行 `insert` 语句。与 `select` 一样,该方法将原生 SQL 查询作为其第一个参数,并将其绑定的数据作为第二个参数:
135 |
136 | DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
137 |
138 | #### 运行更新语句
139 |
140 | `update` 方法用于更新数据库中的现有记录。该方法会返回受该语句影响的行数:
141 |
142 | $affected = DB::update('update users set votes = 100 where name = ?', ['John']);
143 |
144 | #### 运行删除语句
145 |
146 | `delete` 方法用于删除数据库中记录。与 `update` 一样,会返回受该语句影响的行数:
147 |
148 | $deleted = DB::delete('delete from users');
149 |
150 | #### 运行普通语句
151 |
152 | 有些数据库语句不会返回任何值。对于这些语句,可以在 `DB` facade 上使用 `statement` 方法来操作:
153 |
154 | DB::statement('drop table users');
155 |
156 |
157 |
158 | ### 查询事件监听
159 |
160 | 如果你想监控程序执行的每个 SQL 查询,你可以使用 `listen` 方法。这个方法对于记录查询或调试非常有用。你可以在 [服务提供器](/docs/{{version}}/providers) 中为你的查询注册监听器:
161 |
162 | sql
180 | // $query->bindings
181 | // $query->time
182 | });
183 | }
184 |
185 | /**
186 | * 注册服务提供器
187 | *
188 | * @return void
189 | */
190 | public function register()
191 | {
192 | //
193 | }
194 | }
195 |
196 |
197 |
198 | ## 数据库事务
199 |
200 | 你可以在 `DB` facade 上使用 `transaction` 方法来运行数据库事务中的一组操作。如果在事务 `Closure` 中发生了异常,事务将自动回滚。而如果 `Closure` 成功执行,事务将自动被提交。也就是说,使用数据库事务,你就不需要在数据库语句执行发生异常时手动回滚或提交。
201 |
202 | DB::transaction(function () {
203 | DB::table('users')->update(['votes' => 1]);
204 |
205 | DB::table('posts')->delete();
206 | });
207 |
208 | #### 处理死锁
209 |
210 | 传递第二个可选参数给 `transaction` 方法,该参数定义在发生死锁时应该重新尝试事务的次数。一旦尝试次数都用尽了,就会抛出一个异常:
211 |
212 | DB::transaction(function () {
213 | DB::table('users')->update(['votes' => 1]);
214 |
215 | DB::table('posts')->delete();
216 | }, 5);
217 |
218 | #### 手动操作事务
219 |
220 | 如果你想要手动开始一个事务,并且能够完全控制回滚和提交,那么你可以在 `DB` facade 上使用 `beginTransaction` 方法:
221 |
222 | DB::beginTransaction();
223 |
224 | 可以通过 `rollBack` 方法回滚事务:
225 |
226 | DB::rollBack();
227 |
228 | 最后记得要通过 `commit` 方法提交事务:
229 |
230 | DB::commit();
231 |
232 | > {tip} `DB` facade 的事务方法也适用于 [查询语句构造器](/docs/{{version}}/queries) 和 [Eloquent ORM](/docs/{{version}}/eloquent) 的事务。
233 |
234 | ## 译者署名
235 | | 用户名 | 头像 | 职能 | 签名 |
236 | |---|---|---|---|
237 | | [@孤雪飘寒](https://laravel-china.org/users/15752) |
| 翻译 | 全桟工程师,[Github](https://github.com/piaohan),[CSDN](http://blog.csdn.net/msmile_my) |
238 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
239 |
240 | ---
241 |
242 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
243 | >
244 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
245 | >
246 | > 文档永久地址: https://d.laravel-china.org
247 |
--------------------------------------------------------------------------------
/deployment.md:
--------------------------------------------------------------------------------
1 | # Laravel 的部署
2 |
3 | - [简介](#introduction)
4 | - [服务器配置](#server-configuration)
5 | - [Nginx](#nginx)
6 | - [优化](#optimization)
7 | - [优化自动加载](#autoloader-optimization)
8 | - [优化配置加载](#optimizing-configuration-loading)
9 | - [优化路由加载](#optimizing-route-loading)
10 | - [Forge 部署](#deploying-with-forge)
11 |
12 |
13 | ## 简介
14 |
15 | 当你准备好将 Laravel 应用部署到生产环境时,你可以执行一些操作来确保应用程序尽可能高效地运行。在本文档中介绍一些能确保 Laravel 应用被正确部署。
16 |
17 |
18 | ## 服务器配置
19 |
20 |
21 | ### Nginx
22 |
23 | 如果你将应用程序部署到运行 Nginx 的服务器,可以使用下面的内容来配置 Web 服务器。这个文件可能需要根据你的服务器配置进行自定义。你可以考虑使用 [Laravel Forge](https://forge.laravel.com) 等服务协助管理你的服务器:
24 |
25 | server {
26 | listen 80;
27 | server_name example.com;
28 | root /example.com/public;
29 |
30 | add_header X-Frame-Options "SAMEORIGIN";
31 | add_header X-XSS-Protection "1; mode=block";
32 | add_header X-Content-Type-Options "nosniff";
33 |
34 | index index.html index.htm index.php;
35 |
36 | charset utf-8;
37 |
38 | location / {
39 | try_files $uri $uri/ /index.php?$query_string;
40 | }
41 |
42 | location = /favicon.ico { access_log off; log_not_found off; }
43 | location = /robots.txt { access_log off; log_not_found off; }
44 |
45 | error_page 404 /index.php;
46 |
47 | location ~ \.php$ {
48 | fastcgi_split_path_info ^(.+\.php)(/.+)$;
49 | fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
50 | fastcgi_index index.php;
51 | include fastcgi_params;
52 | }
53 |
54 | location ~ /\.(?!well-known).* {
55 | deny all;
56 | }
57 | }
58 |
59 |
60 | ## 优化
61 |
62 |
63 | ### 优化自动加载
64 |
65 | 部署项目到生产环境时,请确保你优化了 Composer 类的自动加载映射,以便 Composer 可以快速找到正确文件为给定类加载:
66 |
67 | composer install --optimize-autoloader
68 |
69 | > {tip} 除了优化自动加载之外,还应该确保项目的源代码管理库中包含了 `composer.lock` 文件。因为当 `composer.lock` 文件存在时,项目的依赖项可以被更快地安装。
70 |
71 |
72 | ### 优化配置加载
73 |
74 | 将应用部署到生产环境时,记得在部署过程中运行 Artisan 命令 `config:cache`:
75 |
76 | php artisan config:cache
77 | 这个命令可以将所有 Laravel 的配置文件合并到单个文件中缓存,此举能大大减少框架在加载配置值时必须执行的系统文件的数量。
78 |
79 |
80 | ### 优化路由加载
81 |
82 | 如果你构建的是具有许多路由的大型应用程序,那你应该在部署过程中运行 Artisan 命令 `route:cache`:
83 |
84 | php artisan route:cache
85 | 这个命令可以将所有路由注册减少为缓存文件中的单个方法调用,以达到当应用程序在注册数百条路由时,提高路由注册的性能。
86 |
87 | > {note} 由于此功能使用 PHP 序列化,而 PHP 无法序列化闭包,因此只能缓存应用程序中基于控制器的路由。
88 |
89 |
90 | ## Forge 部署
91 |
92 | 如果你还没有准备好管理自己的服务器配置,或者你的服务器没有配置 Laravel 应用程序所需的各种服务,[Laravel Forge](https://forge.laravel.com) 是一个不错的选择。
93 |
94 | Laravel Forge 可以在各种基础设施提供商(如 DigitalOcean、Linode、AWS 等)上创建服务器。此外,Forge 还能安装和管理构建 Laravel 应用程序所需的所有工具,如 Nginx、MySQL、Redis、Memcached、Beanstalk 等。
95 |
96 | ## 译者署名
97 | | 用户名 | 头像 | 职能 | 签名 |
98 | | --- | --- | --- | --- |
99 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| 翻译 | Stay Hungry. Stay Foolish. |
100 |
101 | ---
102 |
103 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
104 | >
105 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
106 | >
107 | > 文档永久地址: https://d.laravel-china.org
108 |
--------------------------------------------------------------------------------
/documentation.md:
--------------------------------------------------------------------------------
1 | - ## 前言
2 | - [翻译说明](/docs/{{version}}/about)
3 | - [发行说明](/docs/{{version}}/releases)
4 | - [升级说明](/docs/{{version}}/upgrade)
5 | - [贡献导引](/docs/{{version}}/contributions)
6 | - [API 文档](/api/{{version}})
7 | - ## 入门指南
8 | - [安装](/docs/{{version}}/installation)
9 | - [配置信息](/docs/{{version}}/configuration)
10 | - [文件夹结构](/docs/{{version}}/structure)
11 | - [Homestead](/docs/{{version}}/homestead)
12 | - [Valet](/docs/{{version}}/valet)
13 | - [部署](/docs/{{version}}/deployment)
14 | - ## 核心架构
15 | - [请求周期](/docs/{{version}}/lifecycle)
16 | - [服务容器](/docs/{{version}}/container)
17 | - [服务提供者](/docs/{{version}}/providers)
18 | - [Facades](/docs/{{version}}/facades)
19 | - [Contracts](/docs/{{version}}/contracts)
20 | - ## 基础功能
21 | - [路由](/docs/{{version}}/routing)
22 | - [中间件](/docs/{{version}}/middleware)
23 | - [CSRF 保护](/docs/{{version}}/csrf)
24 | - [控制器](/docs/{{version}}/controllers)
25 | - [请求](/docs/{{version}}/requests)
26 | - [响应](/docs/{{version}}/responses)
27 | - [视图](/docs/{{version}}/views)
28 | - [URL](/docs/{{version}}/urls)
29 | - [Session](/docs/{{version}}/session)
30 | - [表单验证](/docs/{{version}}/validation)
31 | - [错误与日志](/docs/{{version}}/errors)
32 | - ## 前端开发
33 | - [Blade 模板](/docs/{{version}}/blade)
34 | - [本地化](/docs/{{version}}/localization)
35 | - [前端指南](/docs/{{version}}/frontend)
36 | - [编辑资源 Mix](/docs/{{version}}/mix)
37 | - ## 安全相关
38 | - [用户认证](/docs/{{version}}/authentication)
39 | - [API 认证](/docs/{{version}}/passport)
40 | - [用户授权](/docs/{{version}}/authorization)
41 | - [加密解密](/docs/{{version}}/encryption)
42 | - [哈希](/docs/{{version}}/hashing)
43 | - [重置密码](/docs/{{version}}/passwords)
44 | - ## 综合话题
45 | - [Artisan 命令行](/docs/{{version}}/artisan)
46 | - [广播系统](/docs/{{version}}/broadcasting)
47 | - [缓存系统](/docs/{{version}}/cache)
48 | - [集合](/docs/{{version}}/collections)
49 | - [事件系统](/docs/{{version}}/events)
50 | - [文件存储](/docs/{{version}}/filesystem)
51 | - [辅助函数](/docs/{{version}}/helpers)
52 | - [邮件发送](/docs/{{version}}/mail)
53 | - [消息通知](/docs/{{version}}/notifications)
54 | - [扩展包开发](/docs/{{version}}/packages)
55 | - [队列](/docs/{{version}}/queues)
56 | - [任务调度](/docs/{{version}}/scheduling)
57 | - ## 数据库
58 | - [快速入门](/docs/{{version}}/database)
59 | - [查询构造器](/docs/{{version}}/queries)
60 | - [分页](/docs/{{version}}/pagination)
61 | - [数据库迁移](/docs/{{version}}/migrations)
62 | - [数据填充](/docs/{{version}}/seeding)
63 | - [Redis](/docs/{{version}}/redis)
64 | - ## Eloquent ORM
65 | - [快速入门](/docs/{{version}}/eloquent)
66 | - [模型关联](/docs/{{version}}/eloquent-relationships)
67 | - [Eloquent 集合](/docs/{{version}}/eloquent-collections)
68 | - [修改器](/docs/{{version}}/eloquent-mutators)
69 | - [API 资源](/docs/{{version}}/eloquent-resources)
70 | - [序列化](/docs/{{version}}/eloquent-serialization)
71 | - ## 测试相关
72 | - [快速入门](/docs/{{version}}/testing)
73 | - [HTTP 测试](/docs/{{version}}/http-tests)
74 | - [浏览器测试 Dusk](/docs/{{version}}/dusk)
75 | - [数据库测试](/docs/{{version}}/database-testing)
76 | - [测试模拟器](/docs/{{version}}/mocking)
77 | - ## 官方扩展包
78 | - [Cashier 交易工具包](/docs/{{version}}/billing)
79 | - [Envoy 部署工具](/docs/{{version}}/envoy)
80 | - [Horizon](/docs/{{version}}/horizon)
81 | - [Passport OAuth 认证](/docs/{{version}}/passport)
82 | - [Scout 全文搜索](/docs/{{version}}/scout)
83 | - [Socialite 社会化登录](/docs/{{version}}/socialite)
84 |
--------------------------------------------------------------------------------
/eloquent-collections.md:
--------------------------------------------------------------------------------
1 | # Eloquent:集合
2 |
3 | - [简介](#introduction)
4 | - [可用的方法](#available-methods)
5 | - [自定义集合](#custom-collections)
6 |
7 |
8 | ## 简介
9 |
10 | Eloquent 返回的所有多结果集都是 `Illuminate\Database\Eloquent\Collection` 对象的实例,
11 |
12 | 默认情况下 Eloquent 返回的都是一个 `Illuminate\Database\Eloquent\Collection` 对象的实例,包括通过 `get` 方法检索或通过访问关联关系获取到的结果。Eloquent 的集合对象继承了 Laravel 的 [集合基类](/docs/{{version}}/collections),因此它自然也继承了数十种能优雅地处理 Eloquent 模型底层数组的方法。
13 |
14 | 当然,所有的集合都可以作为迭代器,可以就像简单的 PHP 数组一样来遍历它们:
15 |
16 | $users = App\User::where('active', 1)->get();
17 |
18 | foreach ($users as $user) {
19 | echo $user->name;
20 | }
21 |
22 | 然而,集合比数组更加强大,它通过更直观的接口暴露出可链式调用的 map/reduce 等操作。举个例子,我们要删除模型中所有未激活的并收集剩余用户的名字:
23 |
24 | $users = App\User::where('active', 1)->get();
25 |
26 | $names = $users->reject(function ($user) {
27 | return $user->active === false;
28 | })
29 | ->map(function ($user) {
30 | return $user->name;
31 | });
32 |
33 | > {note} 大多数 Eloquent 集合方法会返回新的 Eloquent 集合实例,但是 `pluck`, `keys`, `zip`, `collapse`, `flatten` 和 `flip` 方法除外,它们会返回 [集合基类](/docs/{{version}}/collections) 实例。同样,如果 `map` 操作返回的集合不包含任何 Eloquent 模型,那么它会被自动转换成集合基类。
34 |
35 |
36 |
37 | ## 可用的方法
38 |
39 | ### 集合基类
40 |
41 | 所有 Eloquent 集合都继承了基础的 [Laravel 集合](/docs/{{version}}/collections) 对象。因此,它们也继承了所有集合基类提供的强大的方法:
42 |
43 |
53 |
54 |
55 |
56 | [all](/docs/{{version}}/collections#method-all)
57 | [average](/docs/{{version}}/collections#method-average)
58 | [avg](/docs/{{version}}/collections#method-avg)
59 | [chunk](/docs/{{version}}/collections#method-chunk)
60 | [collapse](/docs/{{version}}/collections#method-collapse)
61 | [combine](/docs/{{version}}/collections#method-combine)
62 | [contains](/docs/{{version}}/collections#method-contains)
63 | [containsStrict](/docs/{{version}}/collections#method-containsstrict)
64 | [count](/docs/{{version}}/collections#method-count)
65 | [diff](/docs/{{version}}/collections#method-diff)
66 | [diffKeys](/docs/{{version}}/collections#method-diffkeys)
67 | [each](/docs/{{version}}/collections#method-each)
68 | [every](/docs/{{version}}/collections#method-every)
69 | [except](/docs/{{version}}/collections#method-except)
70 | [filter](/docs/{{version}}/collections#method-filter)
71 | [first](/docs/{{version}}/collections#method-first)
72 | [flatMap](/docs/{{version}}/collections#method-flatmap)
73 | [flatten](/docs/{{version}}/collections#method-flatten)
74 | [flip](/docs/{{version}}/collections#method-flip)
75 | [forget](/docs/{{version}}/collections#method-forget)
76 | [forPage](/docs/{{version}}/collections#method-forpage)
77 | [get](/docs/{{version}}/collections#method-get)
78 | [groupBy](/docs/{{version}}/collections#method-groupby)
79 | [has](/docs/{{version}}/collections#method-has)
80 | [implode](/docs/{{version}}/collections#method-implode)
81 | [intersect](/docs/{{version}}/collections#method-intersect)
82 | [isEmpty](/docs/{{version}}/collections#method-isempty)
83 | [isNotEmpty](/docs/{{version}}/collections#method-isnotempty)
84 | [keyBy](/docs/{{version}}/collections#method-keyby)
85 | [keys](/docs/{{version}}/collections#method-keys)
86 | [last](/docs/{{version}}/collections#method-last)
87 | [map](/docs/{{version}}/collections#method-map)
88 | [mapWithKeys](/docs/{{version}}/collections#method-mapwithkeys)
89 | [max](/docs/{{version}}/collections#method-max)
90 | [median](/docs/{{version}}/collections#method-median)
91 | [merge](/docs/{{version}}/collections#method-merge)
92 | [min](/docs/{{version}}/collections#method-min)
93 | [mode](/docs/{{version}}/collections#method-mode)
94 | [nth](/docs/{{version}}/collections#method-nth)
95 | [only](/docs/{{version}}/collections#method-only)
96 | [partition](/docs/{{version}}/collections#method-partition)
97 | [pipe](/docs/{{version}}/collections#method-pipe)
98 | [pluck](/docs/{{version}}/collections#method-pluck)
99 | [pop](/docs/{{version}}/collections#method-pop)
100 | [prepend](/docs/{{version}}/collections#method-prepend)
101 | [pull](/docs/{{version}}/collections#method-pull)
102 | [push](/docs/{{version}}/collections#method-push)
103 | [put](/docs/{{version}}/collections#method-put)
104 | [random](/docs/{{version}}/collections#method-random)
105 | [reduce](/docs/{{version}}/collections#method-reduce)
106 | [reject](/docs/{{version}}/collections#method-reject)
107 | [reverse](/docs/{{version}}/collections#method-reverse)
108 | [search](/docs/{{version}}/collections#method-search)
109 | [shift](/docs/{{version}}/collections#method-shift)
110 | [shuffle](/docs/{{version}}/collections#method-shuffle)
111 | [slice](/docs/{{version}}/collections#method-slice)
112 | [sort](/docs/{{version}}/collections#method-sort)
113 | [sortBy](/docs/{{version}}/collections#method-sortby)
114 | [sortByDesc](/docs/{{version}}/collections#method-sortbydesc)
115 | [splice](/docs/{{version}}/collections#method-splice)
116 | [split](/docs/{{version}}/collections#method-split)
117 | [sum](/docs/{{version}}/collections#method-sum)
118 | [take](/docs/{{version}}/collections#method-take)
119 | [tap](/docs/{{version}}/collections#method-tap)
120 | [toArray](/docs/{{version}}/collections#method-toarray)
121 | [toJson](/docs/{{version}}/collections#method-tojson)
122 | [transform](/docs/{{version}}/collections#method-transform)
123 | [union](/docs/{{version}}/collections#method-union)
124 | [unique](/docs/{{version}}/collections#method-unique)
125 | [uniqueStrict](/docs/{{version}}/collections#method-uniquestrict)
126 | [values](/docs/{{version}}/collections#method-values)
127 | [when](/docs/{{version}}/collections#method-when)
128 | [where](/docs/{{version}}/collections#method-where)
129 | [whereStrict](/docs/{{version}}/collections#method-wherestrict)
130 | [whereIn](/docs/{{version}}/collections#method-wherein)
131 | [whereInStrict](/docs/{{version}}/collections#method-whereinstrict)
132 | [whereNotIn](/docs/{{version}}/collections#method-wherenotin)
133 | [whereNotInStrict](/docs/{{version}}/collections#method-wherenotinstrict)
134 | [zip](/docs/{{version}}/collections#method-zip)
135 |
136 |
137 |
138 |
139 | ## 自定义集合
140 |
141 |
142 | 如果你需要在自己的扩展方法中使用自定义的 `Collection` 对象,可以在你自己的模型中重写 `newCollection` 方法:
143 |
144 | | 翻译 | 再怎么说我也是我西北一匹狼 |
172 |
173 |
174 | ---
175 |
176 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
177 | >
178 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
179 | >
180 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/eloquent-mutators.md:
--------------------------------------------------------------------------------
1 | # Eloquent: 修改器
2 |
3 | - [简介](#introduction)
4 | - [访问器 & 修改器](#accessors-and-mutators)
5 | - [定义一个访问器](#defining-an-accessor)
6 | - [定义一个修改器](#defining-a-mutator)
7 | - [日期转换器](#date-mutators)
8 | - [属性类型转换](#attribute-casting)
9 | - [数组 & JSON 转换](#array-and-json-casting)
10 |
11 |
12 |
13 | ## 简介
14 |
15 | 当你在 Eloquent 模型实例中获取或设置某些属性值的时候,访问器和修改器允许你对 Eloquent 属性值进行格式化。例如,你可能想要使用 [Laravel 加密器](/docs/{{version}}/encryption) 来加密一个即将被保存在数据库中的值,当你从 Eloquent 模型访问该属性时,其值将被自动解密。
16 |
17 | 除了自定义访问器和修改器之外,Eloquent 也会自动将日期字段类型转换成 [Carbon](https://github.com/briannesbitt/Carbon) 实例或将 [文本字段类型转换成 JSON](#attribute-casting)。
18 |
19 |
20 | ## 访问器 & 修改器
21 |
22 |
23 | ### 定义一个访问器
24 |
25 | 若要定义一个访问器,则须在你的模型上创建一个 `getFooAttribute` 方法。要访问的 `Foo` 字段需使用「驼峰式」来命名。在这个例子中,我们将为 `first_name` 属性定义一个访问器。当 Eloquent 尝试获取 `first_name` 的值时,将会自动调用此访问器:
26 |
27 | first_name;
52 |
53 | 当然,你也可以通过已有的属性,使用访问器返回新的计算值:
54 |
55 | ```
56 | /**
57 | * 获取用户名全称
58 | *
59 | * @return string
60 | */
61 | public function getFullNameAttribute()
62 | {
63 | return "{$this->first_name} {$this->last_name}";
64 | }
65 | ```
66 |
67 |
68 | ### 定义一个修改器
69 |
70 | 若要定义一个修改器,则须在模型上定义一个 `setFooAttribute` 方法。要访问的 `Foo` 字段需使用「驼峰式」来命名。让我们再来定义 `first_name` 属性的修改器。当我们尝试在模型上设置 `first_name` 的值时,该修改器将被自动调用:
71 |
72 | attributes['first_name'] = strtolower($value);
89 | }
90 | }
91 |
92 | 修改器会获取属性已经被设置的值,允许你操作该值并将其设置到 Eloquent 模型内部的 `$attributes` 属性上。举个例子,如果我们尝试将 `first_name` 属性设置成 `Sally`:
93 |
94 | $user = App\User::find(1);
95 |
96 | $user->first_name = 'Sally';
97 |
98 | 在这个例子中,`setFirstNameAttribute` 方法在调用的时候会接收 `Sally` 这个值作为参数。接着修改器会使用 `strtolower` 函数并将其值设置到内部的 `$attributes` 数组。
99 |
100 |
101 | ## 日期转换器
102 |
103 | 默认情况下,Eloquent 将会把 `created_at` 和 `updated_at` 字段转换成 [Carbon](https://github.com/briannesbitt/Carbon) 实例,它继承了 PHP 原生的 DateTime 类,并提供了各种有用的方法。你可以通过重写模型的 `$dates` 属性,自行定义哪些日期类型字段会被自动转换,或者完全禁止所有日期类型字段的转换:
104 |
105 | deleted_at = Carbon::now();
130 |
131 | $user->save();
132 |
133 | 就如上面所说的,当获取到的属性包含在 `$dates` 属性时,都将会自动转换成 [Carbon](https://github.com/briannesbitt/Carbon) 实例,允许你在属性上使用任意的 `Carbon` 方法:
134 |
135 | $user = App\User::find(1);
136 |
137 | return $user->deleted_at->getTimestamp();
138 |
139 | #### 日期格式
140 |
141 | 默认情况下,时间戳将会以 `'Y-m-d H:i:s'` 的形式格式化。如果你想要自定义自己的时间戳格式,可在模型中设置 `$dateFormat` 属性。该属性决定了日期属性应以何种格式被保存到数据表中,以及当模型被序列化成数组或是 JSON 格式时,这些日期属性以何种格式被保存:
142 |
143 |
160 | ## 属性类型转换
161 |
162 | `$casts` 属性在模型中提供了一个便利的方法来将属性转换为常见的数据类型。`$casts` 属性应是一个数组,且数组的键是那些需要被转换的属性名称,值则是你希望转换的数据类型。支持转换数据类型有:
163 |
164 | + integer
165 | + real
166 | + float
167 | + double
168 | + string
169 | + boolean
170 | + object
171 | + array
172 | + collection
173 | + date
174 | + datetime
175 | + timestamp
176 |
177 | 例如,让我们转换 `is_admin` 属性,将整数(`0` 或 `1`)转换为布尔值:
178 |
179 | 'boolean',
194 | ];
195 | }
196 |
197 | 现在当你访问 `is_admin` 属性时,它将会被转换成布尔值类型,即便保存在数据库里的的值是一个整数类型:
198 |
199 | $user = App\User::find(1);
200 |
201 | if ($user->is_admin) {
202 | //
203 | }
204 |
205 |
206 | ### 数组 & JSON 转换
207 |
208 | 如果一个字段是以被序列化的 JSON 来存储在数据库中, `array` 类型转换将会非常有用。例如,当你在 Eloquent 模型上访问的某个属性在数据库里是一个 `JSON` 或 `TEXT` 字段类型,它包含了被序列化的 JSON,而且你对该字段添加了 `array` 类型转换,那么它将会自动反序列化成一个 PHP 数组:
209 |
210 | 'array',
225 | ];
226 | }
227 |
228 | 一旦类型转换被定义,你就可以访问 `options` 属性,它将会自动把 JSON 反序列化成一个 PHP 数组。当你设置 `options` 属性的值时,接收到的数组将会被自动序列化成 JSON 以便进行保存:
229 |
230 | $user = App\User::find(1);
231 |
232 | $options = $user->options;
233 |
234 | $options['key'] = 'value';
235 |
236 | $user->options = $options;
237 |
238 | $user->save();
239 | ## 译者署名
240 | | 用户名 | 头像 | 职能 | 签名 |
241 | |---|---|---|---|
242 | | [@Ucer](http://codehaoshi.com) |
| 翻译 | Php 工程师,[Code好事](http://codehaoshi.com) |
243 |
244 |
245 | ---
246 |
247 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
248 | >
249 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
250 | >
251 | > 文档永久地址: https://d.laravel-china.org
252 |
--------------------------------------------------------------------------------
/eloquent-serialization.md:
--------------------------------------------------------------------------------
1 | # Eloquent: 序列化
2 |
3 | - [简介](#introduction)
4 | - [序列化模型 & 集合](#serializing-models-and-collections)
5 | - [序列化成数组](#serializing-to-arrays)
6 | - [序列化成 JSON](#serializing-to-json)
7 | - [隐藏来自 JSON 的属性](#hiding-attributes-from-json)
8 | - [添加参数到 JSON 中](#appending-values-to-json)
9 |
10 |
11 | ## 简介
12 |
13 | 当你在创建 JSON API 的时候,经常会需要将模型和关联转换成数组或 JSON。Eloquent 提供了一些便捷的方法来让我们可以完成这些转换,以及控制哪些属性需要被包括在序列化中。
14 |
15 |
16 | ## 序列化模型 & 集合
17 |
18 |
19 | ### 序列化成数组
20 |
21 | 如果要将模型还有其加载的[关联](/docs/{{version}}/eloquent-relationships)转换成一个数组,则可以使用 toArray 方法。这个方法是递归的,因此,所有属性和关联(包含关联中的关联)都会被转换成数组:
22 |
23 | $user = App\User::with('roles')->first();
24 |
25 | return $user->toArray();
26 |
27 | 你也可以将整个[集合](/docs/{{version}}/eloquent-collections)转换成数组:
28 |
29 | $users = App\User::all();
30 |
31 | return $users->toArray();
32 |
33 |
34 | ### 序列化成 JSON
35 |
36 | 如果要将模型转换成 JSON,则可以使用 `toJson` 方法。如同 `toArray`方法一样, `toJson` 方法也是递归的。因此,所有的属性以及关联都会被转换成 JSON:
37 |
38 | $user = App\User::find(1);
39 |
40 | return $user->toJson();
41 |
42 | 或者,你也可以强制把一个模型或集合转型成一个字符串,它将会自动调用 `toJson` 方法:
43 |
44 | $user = App\User::find(1);
45 |
46 | return (string) $user;
47 |
48 | 当模型或集合被转型成字符串时,模型或集合便会被转换成 JSON 格式,因此你可以直接从应用程序的路由或者控制器中返回 Eloquent 对象:
49 |
50 | Route::get('users', function () {
51 | return App\User::all();
52 | });
53 |
54 |
55 | ## 隐藏来自 JSON 的属性
56 |
57 | 有时候你可能会想要限制包含在模型数组或 JSON 表示中的属性,比如说密码。则可以通过在模型中增加 `$hidden` 属性定义来实现:
58 |
59 | {note} 当你要对关联进行隐藏时,需使用关联的 方法 名称,而不是它的动态属性名称。
76 |
77 | 另外,你也可以使用 `visible` 属性来定义应该包含在你的模型数组和 JSON 表示中的属性白名单。白名单外的其他属性将隐藏,不会出现在转换后的数组或 JSON 中:
78 |
79 | makeVisible('attribute')->toArray();
100 |
101 | 相应的,你可以在模型实例后使用 `makeHidden` 方法来隐藏通常显示的属性:
102 |
103 | return $user->makeHidden('attribute')->toArray();
104 |
105 |
106 | ## 添加参数到 JSON 中
107 |
108 | 有时候,在转换模型到 数组 或 JSON 时,你希望添加一个在数据库中没有对应字段的属性。首先你需要为这个值定义一个 [访问器](/docs/{{version}}/eloquent-mutators):
109 |
110 | attributes['admin'] == 'yes';
126 | }
127 | }
128 |
129 | 访问器创建成功后,只需添加该属性到该模型的 `appends` 属性中。注意,属性名称通常遵循 「Snake Case」, 的命名方式,即是访问器的名称是基于 「Camel Case」 的命名方式。
130 |
131 | | 翻译 | 争做一个 Full Stack Developer [@GanymedeNil](http://weibo.com/jinhongyang) |
154 |
155 | ---
156 |
157 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
158 | >
159 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
160 | >
161 | > 文档永久地址: https://d.laravel-china.org
162 |
--------------------------------------------------------------------------------
/encryption.md:
--------------------------------------------------------------------------------
1 | # Laravel 的加密解密机制
2 |
3 | - [简介](#introduction)
4 | - [设置](#configuration)
5 | - [使用](#using-the-encrypter)
6 |
7 |
8 | ## 简介
9 |
10 | Laravel 的加密机制使用 OpenSSL 提供 AES-256 和 AES-128 的加密。强烈建议你使用 Laravel 内置的加密机制,而不是用其他的加密算法。所有 Laravel 加密之后的结果都会使用消息认证码 (MAC) 去签名,使其底层值不能在加密后修改。
11 |
12 |
13 | ## 设置
14 |
15 | 在使用 Laravel 的加密程序之前, 你必须先设置 `config/app.php` 配置文件中的 `key` 选项。运行 Artisan命令 `php artisan key:generate`,它会使用 PHP 的安全随机字节生成器来构建密钥。如果这个 key 值没有被正确设置,则所有由 Laravel 加密的值都将是不安全的。
16 |
17 |
18 | ## 使用
19 |
20 | #### 加密一个值
21 |
22 | 你可以使用辅助函数 `encrypt` 来加密一个值。所有加密值都使用 OpenSSL 与 `AES-256-CBC` 来进行加密。此外,所有加密过的值都会使用消息认证码(MAC)进行签名,以检测加密字符串是否被篡改过:
23 |
24 | fill([
46 | 'secret' => encrypt($request->secret)
47 | ])->save();
48 | }
49 | }
50 |
51 | #### 无序列化加密
52 |
53 | 加密值在加密期间通过 `serialize` 传递,这允许对象和数组的加密。因此,接收加密值的非PHP客户端将需要 `unserialize` 数据。如果想在不序列化的情况下加密和解密值,可以使用 `Crypt` Facade 的 `encryptString` 和 `decryptString` 方法:
54 |
55 | use Illuminate\Support\Facades\Crypt;
56 |
57 | $encrypted = Crypt::encryptString('Hello world.');
58 |
59 | $decrypted = Crypt::decryptString($encrypted);
60 |
61 | #### 解密一个值
62 |
63 | 你可以使用辅助函数 `decrypt` 来解密一个值。如果该值不能被正确解密,例如当 MAC 无效时,会抛出异常 `Illuminate\Contracts\Encryption\DecryptException`:
64 |
65 | use Illuminate\Contracts\Encryption\DecryptException;
66 |
67 | try {
68 | $decrypted = decrypt($encryptedValue);
69 | } catch (DecryptException $e) {
70 | //
71 | }
72 |
73 | ## 译者署名
74 | | 用户名 | 头像 | 职能 | 签名 |
75 | |---|---|---|---|
76 | | [@GanymedeNil](https://github.com/GanymedeNil) |
| 翻译 | 争做一个 Full Stack Developer [@GanymedeNil](http://weibo.com/jinhongyang) |
77 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
78 |
79 | ---
80 |
81 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
82 | >
83 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
84 | >
85 | > 文档永久地址: https://d.laravel-china.org
86 |
--------------------------------------------------------------------------------
/envoy.md:
--------------------------------------------------------------------------------
1 | # Laravel 的远程服务器任务处理器 Envoy
2 |
3 | - [简介](#introduction)
4 | - [安装](#installation)
5 | - [编写任务](#writing-tasks)
6 | - [任务启动](#setup)
7 | - [任务变量](#variables)
8 | - [任务故事](#stories)
9 | - [多个服务器](#multiple-servers)
10 | - [运行任务](#running-tasks)
11 | - [任务确认](#confirming-task-execution)
12 | - [通知](#notifications)
13 | - [Slack](#slack)
14 |
15 |
16 | ## 简介
17 |
18 | [Laravel Envoy](https://github.com/laravel/envoy) 为定义在远程服务器上运行的通用任务提供了一种简洁、轻便的语法。它使用了 Blade 风格的语法,让你可以很方便的启动任务来进行项目部署、Artisan 命令运行等操作。目前,Envoy 只支持 Mac 及 Linux 操作系统。
19 |
20 |
21 | ### 安装
22 |
23 | 首先,使用 Composer `global require` 命令来安装 Enovy :
24 |
25 | composer global require laravel/envoy
26 |
27 | 因为 Composer 的全局库有时会导致包的版本冲突,所以你可以考虑使用 `cgr` ,它是 `composer global require` 命令的一种替代实现 `cgr` 库的安装指导可以在 [GitHub上找到](https://github.com/consolidation-org/cgr)。
28 |
29 | > {note} 一定要确保 `~/.composer/vendor/bin` 目录加入到了你的 PATH 中,这样才能在命令行运行 `envoy` 。
30 |
31 | #### 更新 Envoy
32 |
33 | 你也可以使用 Composer 来更新 Envoy 到最新版本。 要注意 `composer global update` 命令是更新你所有在全局安装的包:
34 |
35 | composer global update
36 |
37 |
38 | ## 编写任务
39 |
40 | 所有的 Envoy 任务都必须定义在项目根目录的 `Envoy.blade.php` 文件中,这里有个例子:
41 |
42 | @servers(['web' => ['user@192.168.1.1']])
43 |
44 | @task('foo', ['on' => 'web'])
45 | ls -la
46 | @endtask
47 |
48 | 如你所见, `@servers` 的数组被定义在文件的起始位置处,让你在声明任务时可以在 `on` 选项里参照使用这些服务器。在你的 `@task` 声明里,你可以放置当任务运行时想要在远程服务器运行的 Bash 命令。
49 |
50 | 你可以通过指定服务器的 IP 地址为 `127.0.0.1` 来执行本地任务:
51 |
52 | @servers(['localhost' => '127.0.0.1'])
53 |
54 |
55 | ### 任务启动
56 |
57 | 有时,你可能想在任务启动前运行一些 PHP 代码。这时可以使用 ```@setup``` 区块在 Envoy 文件中声明变量以及运行普通的 PHP 程序:
58 |
59 | @setup
60 | $now = new DateTime();
61 |
62 | $environment = isset($env) ? $env : "testing";
63 | @endsetup
64 |
65 | 如果你想在任务执行前引入其他 PHP 文件,可以直接在 `Envoy.blade.php` 文件起始位置使用 `@include` :
66 |
67 | @include('vendor/autoload.php')
68 |
69 | @task('foo')
70 | # ...
71 | @endtask
72 |
73 |
74 | ### 任务变量
75 |
76 | 如果需要的话,你也可以通过命令行选项来传递变量至 Envoy 文件,以便自定义你的任务:
77 |
78 | envoy run deploy --branch=master
79 |
80 | 你可以通过 Blade 的「echo」语法使用这些选项, 当然也能在任务里用「if」 和循环操作。举例来说,我们在执行 `git pull` 命令前,先检查 `$branch` 变量是否存在:
81 |
82 | @servers(['web' => '192.168.1.1'])
83 |
84 | @task('deploy', ['on' => 'web'])
85 | cd site
86 |
87 | @if ($branch)
88 | git pull origin {{ $branch }}
89 | @endif
90 |
91 | php artisan migrate
92 | @endtask
93 |
94 |
95 | ### 任务故事
96 |
97 | 任务故事通过一个统一的、便捷的名字来划分一组任务,来让你把小而专的子任务合并到大的任务里。比如说,一个名为 `deploy` 的任务故事可以在它定义范围内列出子任务名字 `git` 和 `composer` 来运行各自对应的任务:
98 |
99 | @servers(['web' => '192.168.1.1'])
100 |
101 | @story('deploy')
102 | git
103 | composer
104 | @endstory
105 |
106 | @task('git')
107 | git pull origin master
108 | @endtask
109 |
110 | @task('composer')
111 | composer install
112 | @endtask
113 |
114 | 当 story 写好后,像运行普通任务一样运行它就好了:
115 |
116 | envoy run deploy
117 |
118 |
119 | ### 多个服务器
120 |
121 | 你可以在多个服务器上运行任务。首先,增加额外的服务器至你的 `@servers` 声明,每个服务器必须分配一个唯一的名称。一旦你定义好其它服务器,就能够在任务声明的 `on` 数组中列出这些服务器:
122 |
123 | @servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])
124 |
125 | @task('deploy', ['on' => ['web-1', 'web-2']])
126 | cd site
127 | git pull origin {{ $branch }}
128 | php artisan migrate
129 | @endtask
130 |
131 | #### 并行运行
132 |
133 | 默认情况下,任务会按照顺序在每个服务器上运行。这意味着任务会在第一个服务器运行完后才跳到第二个。如果你想在多个服务器上并行运行任务,只需简单的在任务声明里加上 `parallel` 选项即可:
134 |
135 | @servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])
136 |
137 | @task('deploy', ['on' => ['web-1', 'web-2'], 'parallel' => true])
138 | cd site
139 | git pull origin {{ $branch }}
140 | php artisan migrate
141 | @endtask
142 |
143 |
144 | ## 运行任务
145 |
146 | 要想运行一个在 `Envoy.blade.php` 文件中定义好的任务或者故事,就执行 Envoy 的 `run` 命令,并将这个任务的名字传递给它。Envoy 会去执行这个任务并且把任务执行过程中的输出给打印出来:
147 |
148 | envoy run task
149 |
150 |
151 | ### 任务确认
152 |
153 | 如果你想要在运行任务之前进行提示确认,则可以增加 `confirm` 命令到任务声明。这个选项对于破坏性的操作来说是相当有用的:
154 |
155 | @task('deploy', ['on' => 'web', 'confirm' => true])
156 | cd site
157 | git pull origin {{ $branch }}
158 | php artisan migrate
159 | @endtask
160 |
161 |
162 |
163 | ## 通知
164 |
165 |
166 | ### Slack
167 |
168 | Envoy 也支持任务执行完毕后发送通知至 [Slack](https://slack.com)。`@slack` 命令接收 Slack hook 网址和频道名称。你可以通在在 Slack 的控制面板上创建 「Incoming WebHooks」 时来检索 webhook 网址。webhook-url 参数必须是 `@slack` 的 Incoming WebHooks 所提供的完整网址:
169 |
170 | @finished
171 | @slack('webhook-url', '#bots')
172 | @endfinished
173 |
174 | 你可以选择下方的任意一个来作为 channel 参数:
175 |
176 |
177 | - 如果要发送通知至一个频道: `#channel`
178 | - 如果要发送通知给一位用户: `@user`
179 |
180 |
181 | ## 译者署名
182 | | 用户名 | 头像 | 职能 | 签名 |
183 | |---|---|---|---|
184 | | [@司维](https://phphub.org/users/11602) |
| 翻译 | [@leon0204](https://github.com/leon0204) at Github |
185 |
186 |
187 | ---
188 |
189 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
190 | >
191 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
192 | >
193 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/errors.md:
--------------------------------------------------------------------------------
1 | # Laravel 的错误和日志记录
2 |
3 | - [简介](#introduction)
4 | - [配置](#configuration)
5 | - [错误的详细信息](#error-detail)
6 | - [日志存储](#log-storage)
7 | - [日志严重程度级别](#log-severity-levels)
8 | - [自定义 Monolog 配置](#custom-monolog-configuration)
9 | - [异常处理](#the-exception-handler)
10 | - [Report 方法](#report-method)
11 | - [Render 方法](#render-method)
12 | - [自定义异常的 report & render 方法](#renderable-exceptions)
13 | - [HTTP 异常](#http-exceptions)
14 | - [自定义 HTTP 错误页面](#custom-http-error-pages)
15 | - [日志](#logging)
16 |
17 |
18 | ## 简介
19 |
20 | Laravel 默认自带错误和异常处理机制。应用程序触发的所有异常都被 `App\Exceptions\Handler` 类记录下来,然后渲染给用户。 我们将在后续文档中深入介绍此类。
21 |
22 | Laravel 使用 [Monolog](https://github.com/Seldaek/monolog) 库为各种强大的日志处理程序提供支持。Laravel 配置了多种日志处理程序,方便你在单个日志文件、多个日志文件或将错误信息写入系统日志之间进行选择。
23 |
24 |
25 | ## 配置
26 |
27 |
28 | ### 错误的详细信息
29 |
30 | `config/app.php` 配置文件的 `debug` 选项决定了是否向用户显示错误信息。默认情况下,此选项设置为获取存储在 `.env` 文件中的 `APP_DEBUG` 环境变量的值。
31 |
32 | 对于本地开发,应该将 `APP_DEBUG` 环境变量设置为 `true` 。而在生产环境中,此值应始终保持 `false` 。如果你在生产中将该值设置为 `true` ,则有可能会将敏感的配置信息暴露给应用程序的最终用户。
33 |
34 |
35 | ### 日志存储
36 |
37 | Laravel 支持 `single` 、`daily` 、 `syslog` 和 `errorlog` 四种日志写入模式。通过修改 `config/app.php` 配置文件中的 `log` 选项来配置 Laravel 使用的存储机制。如果你希望每天产生日志都存放在不同的文件中,则应将 `app` 配置文件中的 `log` 值设置为 `daily`:
38 |
39 | 'log' => 'daily'
40 |
41 | #### 最大日志文件数
42 |
43 | 在使用 `daily` 日志模式时,Laravel 默认只保留五天份的日志文件。如果要调整保留文件的数量,就在 `app` 配置文件中添加一个 `log_max_files` 配置项:
44 |
45 | 'log_max_files' => 30
46 |
47 |
48 | ### 日志严重程度级别
49 |
50 | 使用 Monolog 时,日志消息可能具有不同程度的严重级别。默认情况下,Laravel 将存储所有级别的日志。你也可以在生产环境中通过将 `log_level` 选项添加到 `app.php` 配置文件中来配置应当记录的严重程度最低的日志级别。
51 |
52 | 配置之后,Laravel 就只会记录大于或等于指定严重级别的所有级别的错误。例如,默认的 `log_level` 被设置为 `error`,那么 Laravel 只会记录 **error**、**critical**、**alert** 和 **emergency** 级别的日志信息:
53 |
54 | 'log_level' => env('APP_LOG_LEVEL', 'error'),
55 |
56 | > {tip} Monolog 识别以下严重程度的级别,从低到高为: `debug`、 `info`、`notice`、 `warning`、`error`、`critical`、`alert`、`emergency`。
57 |
58 |
59 | ### 自定义 Monolog 配置
60 |
61 | 你可以使用 `configureMonologUsing` 方法来配置应用程序对 Monolog 的完全控制。在 `$app` 变量返回之前,在 `bootstrap/app.php` 文件中调用此方法:
62 |
63 | $app->configureMonologUsing(function ($monolog) {
64 | $monolog->pushHandler(...);
65 | });
66 |
67 | return $app;
68 |
69 | #### 自定义渠道名称
70 |
71 | 默认情况下,Monolog 用与当前环境匹配的名称进行实例化,如 `production` 或 `local`。要更改此值,可将 `log_channel` 选项添加到 `app.php` 配置文件中:
72 |
73 | ```
74 | 'log_channel' => env('APP_LOG_CHANNEL', 'my-app-name'),
75 | ```
76 |
77 |
78 |
79 | ## 异常处理
80 |
81 |
82 | ### Report 方法
83 |
84 | 所有异常都由 `App\Exceptions\Handler` 类处理。 这个类包含两个方法:`report` 和 `render`。`report` 方法用于记录异常或将其发送到外部服务,如 [Bugsnag](https://bugsnag.com) 或 [Sentry](https://github.com/getsentry/sentry-laravel)。默认情况下,`report` 方法只是简单地将异常传递给记录异常的基类。你可以根据需要来记录异常。
85 |
86 | 例如,如果你需要以不同的方式报告不同类型的异常,你可以使用 PHP 的比较运算符 `instanceof`:
87 |
88 | /**
89 | * 报告或记录一个异常
90 | *
91 | * 这是个给 Bugsnag 或 Sentry 发送异常的好地方
92 | *
93 | * @param \Exception $exception
94 | * @return void
95 | */
96 | public function report(Exception $exception)
97 | {
98 | if ($exception instanceof CustomException) {
99 | //
100 | }
101 |
102 | return parent::report($exception);
103 | }
104 |
105 | #### 辅助函数 `report`
106 |
107 | 某些时候你可能想要报告一个异常,但又想继续处理当前的请求。辅助函数 `report` 允许你使用异常处理程序的 `report` 方法快速报告一个异常而不抛出一个错误页面:
108 |
109 | public function isValid($value)
110 | {
111 | try {
112 | // 校验值...
113 | } catch (Exception $e) {
114 | report($e);
115 |
116 | return false;
117 | }
118 | }
119 |
120 | #### 按类型忽略异常
121 |
122 | 异常处理程序的 `$dontReport` 属性包含不会被记录的异常类型数组。例如,404错误导致的异常以及其他类型的错误不会写入日志文件。你可以根据需要向此数组添加其他异常类型:
123 |
124 | /**
125 | * 不应报告的异常类型列表。
126 | *
127 | * @var array
128 | */
129 | protected $dontReport = [
130 | \Illuminate\Auth\AuthenticationException::class,
131 | \Illuminate\Auth\Access\AuthorizationException::class,
132 | \Symfony\Component\HttpKernel\Exception\HttpException::class,
133 | \Illuminate\Database\Eloquent\ModelNotFoundException::class,
134 | \Illuminate\Validation\ValidationException::class,
135 | ];
136 |
137 |
138 | ### Render 方法
139 |
140 | `render` 方法负责将给定的异常转换成发送给浏览器的 HTTP 响应。默认情况下,异常会传递为你生成响应的基类。你还可以根据需要检查异常类型或返回自定义的响应:
141 |
142 | /**
143 | * 渲染异常到 HTTP 响应中.
144 | *
145 | * @param \Illuminate\Http\Request $request
146 | * @param \Exception $exception
147 | * @return \Illuminate\Http\Response
148 | */
149 | public function render($request, Exception $exception)
150 | {
151 | if ($exception instanceof CustomException) {
152 | return response()->view('errors.custom', [], 500);
153 | }
154 |
155 | return parent::render($request, $exception);
156 | }
157 |
158 |
159 | ### 自定义异常的 report & render 方法
160 |
161 | 你并不一定要在异常处理程序中的 `report` 和 `render` 方法中处理不同类型的异常,可以直接在自定义的异常处理程序中定义 `report` 和 `render` 方法。如果这些方法存的在话,框架会自动调用他们:
162 |
163 |
194 | ## HTTP 异常
195 |
196 | 一些异常描述了来自服务器的 HTTP 错误代码。例如,可能是错误代码 404 的「找不到页面」、401 的「未授权错误」甚至可能是由开发者造成的 500。你可以使用辅助函数 `abort` 在应用程序中的任何地方生成这样的响应:
197 |
198 | abort(404);
199 |
200 | 辅助函数 `abort` 会创建一个由异常处理程序渲染的异常。此外,你还可以提供响应文本:
201 |
202 | abort(403, 'Unauthorized action.');
203 |
204 |
205 | ### 自定义 HTTP 错误页面
206 |
207 | Laravel 可以轻松地显示各种 HTTP 状态代码的自定义错误页面。例如,如果你要自定义 404 HTTP 状态代码的错误页面,就创建一个 `resources/views/errors/404.blade.php` 。此文件将会用于渲染你应用中产生的所有 404 错误。此目录中的视图文件的命名应该与它们对应的 HTTP 状态代码匹配。由 `abort` 函数引发的 `HttpException` 实例将作为 `$exception` 变量传递给视图。
208 |
209 | {{ $exception->getMessage() }}
210 |
211 |
212 | ## 日志
213 |
214 | Laravel 在强大的 [Monolog](https://github.com/seldaek/monolog) 库上提供了一个简单的抽象层。默认情况下,Laravel 的日志文件的存储目录被配置为 `storage/logs` 。你可以使用 `Log` [facade](/docs/{{version}}/facades) 将信息写入日志:
215 |
216 | User::findOrFail($id)]);
237 | }
238 | }
239 |
240 | 该日志记录器提供 [RFC 5424](https://tools.ietf.org/html/rfc5424) 中定义的八种日志级别:**emergency**、**alert**、**critical**、**error**、**warning**、**notice**、**info** 和 **debug**。
241 |
242 | Log::emergency($message);
243 | Log::alert($message);
244 | Log::critical($message);
245 | Log::error($message);
246 | Log::warning($message);
247 | Log::notice($message);
248 | Log::info($message);
249 | Log::debug($message);
250 |
251 | #### 上下文信息
252 |
253 | 上下文数据也可以用数组的形式传递给日志方法。此上下文数据将被格式化并与日志消息一起显示:
254 |
255 | Log::info('User failed to login.', ['id' => $user->id]);
256 |
257 | #### 访问底层的 Monolog 实例
258 |
259 | Monolog 还提供了各种可用于记录的处理程序。如果需要,你可以访问 Laravel 使用的底层的 Monolog 实例:
260 |
261 | $monolog = Log::getMonolog();
262 |
263 | ## 译者署名
264 | | 用户名 | 头像 | 职能 | 签名 |
265 | |---|---|---|---|
266 | |[@ChrisonWang](https://github.com/ChrisonWang) |
| 翻译 | [@王欣](https://www.linkedin.com/in/ChrisonWang/) at LinkedIn|
267 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
268 |
269 | ---
270 |
271 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
272 | >
273 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
274 | >
275 | > 文档永久地址: https://d.laravel-china.org
276 |
--------------------------------------------------------------------------------
/frontend.md:
--------------------------------------------------------------------------------
1 | # Laravel 的前端资源处理 JavaScript&CSS 构建
2 |
3 | - [简介](#introduction)
4 | - [编写 CSS](#writing-css)
5 | - [编写 JavaScript](#writing-javascript)
6 | - [编写 Vue 组件](#writing-vue-components)
7 | - [使用 React](#using-react)
8 |
9 |
10 | ## 简介
11 |
12 | Laravel 并没有规定你使用哪个 JavaScript 或 CSS 预处理器,不过它还是提供了对大多数应用都很适用的 [Bootstrap](http://getbootstrap.com) 和 [Vue](https://vuejs.org) 来作为默认的起点。默认情况下,Laravel 使用 [NPM](https://npmjs.org) 安装这两个前端依赖。
13 |
14 | #### CSS
15 |
16 | [Laravel Mix](/docs/{{version}}/mix) 提供了一个内容丰富且简洁的 API 用以编译 SASS 或 Less,这些 CSS 预处理语言扩充了 CSS 语言,增加了诸如变量、mixins 及其他一些功能强大的扩展让编写 CSS 代码变得更加有趣。尽管我们会在这里简要的讨论 CSS 编译的内容,但你应该查阅 [Laravel Mix 文档](/docs/{{version}}/mix) 获取更多关于编译 SASS 或 Less 的信息。
17 |
18 | #### JavaScript
19 |
20 | Laravel 并不需要你使用特定的 JavsScript 框架或者库来构建应用程序。事实上,你也可以完全不用 JavaScript。不过,Laravel 自带了一些基本的脚手架,能更容易地使用 [Vue](https://vuejs.org) 编写 JavaScript。Vue 提供了健壮的组件化 API 用来构建强大的 JavaScript 应用程序。与 CSS 一样,我们可以使用 Laravel Mix 轻松地将 JavaScript 组件编译成一个浏览器可使用的 JavaScript 文件。
21 |
22 | #### 移除前端脚手架
23 |
24 | 如果要从你的应用程序中移除前端脚手架,可以使用 Artisan 命令 `preset`。该命令加上 `none` 选项时,将从应用程序中删除 Bootstrap 和 Vue 脚手架,只留下一个空白的 SASS 文件和一些常用的 JavaScript 实用程序库:
25 |
26 | php artisan preset none
27 |
28 | ## 编写 CSS
29 |
30 | Laravel 的 `package.json` 文件引入了 `bootstrap-sass` 依赖包,可以帮助你使用 Bootstrap 构建应用程序的前端原型。不过,你可以根据自己应用程序的需要在 `package.json` 灵活的添加或者移除依赖包。你不是一定要使用 Bootstrap 框架来构建你的 Laravel 应用程序,它只是给那些想用它的人提供一个很好的起点。
31 |
32 | 在编译 CSS 代码之前,需要你先使用 [Node 包管理工具(NPM)](https://www.npmjs.org/) 来安装项目的前端依赖:
33 |
34 | npm install
35 |
36 | 使用 `npm install` 成功安装依赖后,你就可以使用 [Laravel Mix](/docs/{{version}}/mix#working-with-stylesheets) 来将 SASS 文件编译为纯 CSS。`npm run dev` 命令会处理 `webpack.mix.js` 文件中的指令。通常情况下,编译好的 CSS 代码会被放置在 `public/css` 目录:
37 |
38 | npm run dev
39 |
40 | Laravel 自带的 `webpack.mix.js` 默认会编译 `resources/assets/sass/app.scss` SASS 文件。`app.scss` 文件导入了一个包含 SASS 变量的文件,并加载 Bootstrap,这对大多数程序来说很方便。你也可以根据自己的需要去定制 `app.scss` 文件的内容,甚至使用完全不同的预处理器,详细配置见 [配置 Laravel Mix](/docs/{{version}}/mix)。
41 |
42 |
43 | ## 编写 JavaScript
44 |
45 | 在项目根目录中的 `package.json` 可以找到应用程序的所有 JavaScript 依赖。它和 `composer.json` 文件类似,不同的是它指定的是 JavaScript 的依赖而不是 PHP 的依赖。使用 [Node 包管理器 (NPM)](https://npmjs.org) 来安装这些依赖包:
46 |
47 | npm install
48 | > {tip} 默认情况下,Laravel `package.json` 文件默认会包含一些依赖包来帮助你构建 JavaScript 应用程序,例如 `vue` 和 `axios` 。你可以根据需要在 `package.json` 中添加或者移除依赖。
49 |
50 | 安装依赖之后,就可以使用 `npm run dev` 命令来 [编译资源文件](/docs/{{version}}/mix) 。Webpack 是一个为现代 JavaScript 应用而生的模块构建工具。当你运行 `npm run dev` 命令时,Webpack 会执行 `webpack.mix.js` 文件中的指令:
51 |
52 | npm run dev
53 |
54 | 默认情况下,Laravel 的 `webpack.mix.js` 会编译 SASS 文件和 `resources/assets/js/app.js` 文件。你可以在 `app.js` 文件中注册你的 Vue 组件,或者如果你更喜欢其他的框架,请配置自己的 JavaScript 应用程序。编译好的 JavaScript 文件通常会放置在 `public/js` 目录。
55 |
56 | > {tip} `app.js` 会加载 `resources/assets/js/bootstrap.js` 文件来启动并 配置 Vue、Axios、jQuery 以及其他的 JavaScript 依赖。如果你有其他的 JavaScript 依赖需要去配置,你也可以在这个文件中完成。
57 |
58 |
59 | ### 编写 Vue 组件
60 |
61 | 新 Laravel 程序默认会在 `resources/assets/js/components` 中包含一个 `ExampleComponent.vue` 的 Vue 组件。`ExampleComponent.vue` 文件是在同一文件中定义其 JavaScript 和 HTML 模板的 [单文件 Vue 组件](https://vuejs.org/guide/application.html#Single-File-Components) 的示例。它为构建 JavaScript 驱动的应用程序提供了非常方便的方法。这个示例组件已经在 `app.js` 文件中注册:
62 |
63 | Vue.component('example-component', require('./components/ExampleConponent.vue'));
64 |
65 | 在应用程序中使用组件,你只需要简单的将其放到你的 HTML 模板之中。例如,运行 Artisan 命令 `make:auth` 去生成应用的用户认证和注册的框架页面后,可以把组件放到 `home.blade.php` Blade 模板中:
66 |
67 | @extends('layouts.app')
68 |
69 | @section('content')
70 |
71 | @endsection
72 |
73 | > {tip} 谨记,每次修改 Vue 组件后都应该运行 `npm run dev` 命令。或者,你可以使用 `npm run watch` 命令来监控并在每次文件被修改时自动重新编译组件。
74 |
75 | 当然,如果你对编写 Vue 组件的内容感兴趣,你可以读一下 [Vue 文档](http://vuejs.org/guide/),该文档内容全面又易于阅读。
76 |
77 |
78 | ### 使用 React
79 | 如果你喜欢用 React 来构建你的 JavaScript 应用程序,Laravel 很容易就能将 Vue 脚手架替换为 React 脚手架。在任何新建的 Laravel 应用程序下,你可以用 `preset` 命令加 `react` 选项:
80 |
81 | php artisan preset react
82 |
83 | 该命令将移除 Vue 脚手架并用 React 脚手架替换, 包括 Laravel 自带的示例组件。
84 |
85 | ## 译者署名
86 |
87 | | 用户名 | 头像 | 职能 | 签名 |
88 | |---|---|---|---|
89 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
90 |
91 | ---
92 |
93 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
94 | >
95 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
96 | >
97 | > 文档永久地址: https://d.laravel-china.org
98 |
--------------------------------------------------------------------------------
/hashing.md:
--------------------------------------------------------------------------------
1 | # Laravel 的哈希加密
2 |
3 | - [简介](#introduction)
4 | - [基本用法](#basic-usage)
5 |
6 |
7 | ## 简介
8 |
9 | Laravel `Hash` [Facade](/docs/{{version}}/facades) 提供安全的 Bcrypt 哈希保存用户密码。 如果应用程序中使用了 Laravel 内置的 `LoginController` 和 `RegisterController` 类,它们将自动使用 Bcrypt 进行注册和身份验证。
10 |
11 | > {tip} Bcrypt 是哈希密码的理想选择,因为它的「加密系数」可以任意调整,这意味着生成哈希所需的时间可以随着硬件功率的增加而增加。
12 |
13 |
14 | ## 基本用法
15 |
16 | 你可以通过调用 `Hash` Facade 的 `make` 方法来填写密码:
17 |
18 | user()->fill([
39 | 'password' => Hash::make($request->newPassword)
40 | ])->save();
41 | }
42 | }
43 |
44 | `make` 方法还能使用 `rounds` 选项来管理 bcrypt 哈希算法的加密系数。然而,大多数应用程序还是能接受默认值的:
45 |
46 | ```
47 | $hashed = Hash::make('password', [
48 | 'rounds' => 12
49 | ]);
50 | ```
51 |
52 | #### 根据哈希值验证密码
53 |
54 | `check` 方法可以验证给定的纯文本字符串对应于给定的散列。 如果使用 [Laravel 内置的](/docs/{{version}}/authentication) `LoginController`,则不需要直接使用该方法,因为该控制器会自动调用此方法:
55 |
56 | if (Hash::check('plain-text', $hashedPassword)) {
57 | // 密码对比...
58 | }
59 |
60 | #### 检查密码是否需要重新加密
61 |
62 | `needsRehash` 函数允许你检查已加密的密码所使用的加密系数是否被修改:
63 |
64 | if (Hash::needsRehash($hashed)) {
65 | $hashed = Hash::make('plain-text');
66 | }
67 |
68 | ## 译者署名
69 | | 用户名 | 头像 | 职能 | 签名 |
70 | |---|---|---|---|
71 | | [@GanymedeNil](https://github.com/GanymedeNil) |
| 翻译 | 争做一个 Full Stack Developer [@GanymedeNil](http://weibo.com/jinhongyang) |
72 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
73 |
74 | ---
75 |
76 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
77 | >
78 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
79 | >
80 | > 文档永久地址: https://d.laravel-china.org
81 |
--------------------------------------------------------------------------------
/horizon.md:
--------------------------------------------------------------------------------
1 | # Laravel 队列监控面板 - Horizon
2 |
3 | - [介绍](#introduction)
4 | - [安装](#installation)
5 | - [配置](#configuration)
6 | - [仪表盘授权](#dashboard-authentication)
7 | - [运行 Horizon](#running-horizon)
8 | - [部署 Horizon](#deploying-horizon)
9 | - [标签](#tags)
10 | - [通知](#notifications)
11 | - [Metrics](#metrics)
12 |
13 |
14 | ## 介绍
15 |
16 | Horizon 为 Laravel 官方出品的 Redis 队列提供了一个可以通过代码进行配置、并且非常漂亮的仪表盘,并且能够轻松监控队列的任务吞吐量、执行时间以及任务失败情况等关键指标。
17 |
18 | 队列执行者的所有配置项都存放在一个简单的配置文件中,所以团队可以通过版本控制进行协作维护。
19 |
20 |
21 | ## 安装
22 |
23 | > {note} 由于 Horizon 中使用了异步处理信号,所以需要 PHP 7.1+
24 |
25 | 可以使用 Composer 将 Horizon 安装进你的 Laravel 项目:
26 |
27 | composer require laravel/horizon
28 |
29 | 安装完成后,使用 `vendor:publish` Artisan 命令发布相关文件:
30 |
31 | php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"
32 |
33 |
34 | ### 配置
35 |
36 | 发布相关文件过程中,Horizon 的主要配置文件会被放置到 `config/horizon.php`,我们可以通过此文件配置队列执行者的所有配置项,此文件中的每个配置项都包含一份完整的使用说明,所以推荐认真阅读此文件。
37 |
38 | #### 负载均衡配置
39 |
40 | Horizon 有三种负载均衡策略:`simple`、`auto`、 和 `false`,默认策略是 `simple`,会将接收到的任务均分给队列进程:
41 |
42 | 'balance' => 'simple',
43 |
44 | 策略 `auto` 会根据每个队列的压力自动调整其执行者进程数目,例如:如果 `notifications` 有 1000 个待执行的任务,但是你的 `render` 队列是空的,Horizon 会分派更多执行者进程给 `notifications` 队列,直到队列任务全部执行完毕(即队列为空)。当配置项 `balance` 设置为 `false` 时,Horizon 的执行策略与 Laravel 默认行为一致,及根据队列在配置文件中配置的顺序处理队列任务。
45 |
46 |
47 | ### 仪表盘权限验证
48 |
49 | Horizon 仪表盘的路由是 `/horizon` ,默认只能在 `local` 环境中访问仪表盘。我们可以使用 `Horizon::auth` 函数定义更具体的访问策略。`auth` 函数能够接受一个回调函数,此回调函数需要返回 `true` 或 `false` ,从而确认当前用户是否有权限访问 Horizon 仪表盘:
50 |
51 | Horizon::auth(function ($request) {
52 | // return true / false;
53 | });
54 |
55 |
56 | ## 运行 Horizon
57 |
58 | 修改 `config/horizon.php` 完成队列执行者的配置之后,可以使用 Artisan 命令 `horizon` 启动 Horizon,下面一条命令可以启动所有已配置的执行者:
59 |
60 | php artisan horizon
61 |
62 | 使用 Artisan 命令 `horizon:pause` 和 `horizon:continue` 来暂停和恢复队列的执行:
63 |
64 | php artisan horizon:pause
65 |
66 | php artisan horizon:continue
67 |
68 | 使用 Artisan 命令 `horizon:terminate` 来正常停止系统中的 Horizon 主进程,此命令执行时,Horizon 当前执行中的任务会被正常完成,然后 Horizon 执行结束:
69 |
70 | php artisan horizon:terminate
71 |
72 |
73 | ### 部署 Horizon
74 |
75 | 生产环境中,我们需要配置一个进程管理工具来监控 `php artisan horizon` 命令的执行,以便在其意外退出时自动重启。当服务器部署新代码时,需要终止当前 Horizon 主进程,然后通过进程管理工具来重启,从而使用最新的代码。
76 |
77 | 使用 Artisan 命令 `horizon:terminate` 来正常停止系统中的 Horizon 主进程,此命令执行时,Horizon 当前执行中的任务会被正常完成,然后 Horizon 执行结束:
78 |
79 | php artisan horizon:terminate
80 |
81 | #### Supervisor 配置
82 |
83 | 可以使用进程管理工具 Supervisor 来管理 `horizon` 进程,下面配置文件就已够用:
84 |
85 | [program:horizon]
86 | process_name=%(program_name)
87 | command=php /home/forge/app.com/artisan horizon
88 | autostart=true
89 | autorestart=true
90 | user=forge
91 | redirect_stderr=true
92 | stdout_logfile=/home/forge/app.com/horizon.log
93 |
94 | > {tip} 如果你不喜欢自己维护服务器,可以考虑使用 [Laravel Forge](https://forge.laravel.com) ,Forge 提供了运行一个带有 Horizon 的现代、强大的 Laravel 应用所需的 PHP7+ 以及其他所有环境。
95 |
96 |
97 | ## 标签
98 |
99 | Horizon 允许我们给队列任务打上一系列标签,包括 mailables、事件广播、通知以及队列中的时间侦听器,事实上,Horizon 会智能并且自动根据任务携带的 Eloquent 模型给大多数任务打上标签,如下任务示例:
100 |
101 | video = $video;
132 | }
133 |
134 | /**
135 | * Execute the job.
136 | *
137 | * @return void
138 | */
139 | public function handle()
140 | {
141 | //
142 | }
143 | }
144 |
145 | 如果此任务放入队列时携带了一个 `App\Video` 实例,此实例的 `id` 为 `1`,这个任务会接收到一个 `App\Video:1` 标签,这是因为 Horizon 会检查任务的所有属性是否携带 Eloquent 模型,如果发现携带,Horizon 会给该任务标记上模型的类名和主键:
146 |
147 | $video = App\Video::find(1);
148 |
149 | App\Jobs\RenderVideo::dispatch($video);
150 |
151 | #### 自定义标签
152 |
153 | 如果需要自定义一个可被放入队列对象的标签,可以在此类中定义 `tags` 函数:
154 |
155 | class RenderVideo implements ShouldQueue
156 | {
157 | /**
158 | * Get the tags that should be assigned to the job.
159 | *
160 | * @return array
161 | */
162 | public function tags()
163 | {
164 | return ['render', 'video:'.$this->video->id];
165 | }
166 | }
167 |
168 |
169 | ## 通知
170 |
171 | > **Note:** 使用通知之前,需要将 Composer 包 `guzzlehttp/guzzle` 安装到目标项目,如果配置 Horizon 发送短信通知,也要注意阅读[Nexmo 通知驱动的依赖条件](https://laravel.com/docs/5.4/notifications#sms-notifications)。
172 |
173 | 如果需要在队列等待时间过长时发起通知,可以在应用的 `AppServiceProvider` 中调用 `Horizon::routeSlackNotificationsTo` 和 `Horizon::routeSmsNotificationsTo` 函数:
174 |
175 | Horizon::routeSlackNotificationsTo('slack-webhook-url');
176 |
177 | Horizon::routeSmsNotificationsTo('15556667777');
178 |
179 | #### 配置等待时间过长通知的阈值
180 |
181 | 可以在 `config/horizon.php` 中配置等待时间过长具体秒数,配置项 `waits` 可以针对每个 链接/队列 配置阈值:
182 |
183 | 'waits' => [
184 | 'redis:default' => 60,
185 | ],
186 |
187 |
188 | ## Metrics
189 |
190 | Horizon 包含一个 metrics 仪表盘,它可以提供任务和队列等待时间和吞吐量信息,为了填充此仪表盘,需要使用应用的 [scheduler](/docs/{{version}}/scheduling) 每五分钟运行一次 Horizon 的 Artisan 命令 `snapshot`:
191 |
192 | /**
193 | * Define the application's command schedule.
194 | *
195 | * @param \Illuminate\Console\Scheduling\Schedule $schedule
196 | * @return void
197 | */
198 | protected function schedule(Schedule $schedule)
199 | {
200 | $schedule->command('horizon:snapshot')->everyFiveMinutes();
201 | }
202 |
203 |
204 | ## 译者署名
205 | | 用户名 | 头像 | 职能 | 签名 |
206 | |---|---|---|---|
207 | | [@zhwei](https://github.com/zhwei) |
| 翻译 | [欢迎加入蛋壳公寓](http://www.dankegongyu.com/about/join.html?from=laravel-doc-55) |
208 |
209 |
210 | ---
211 |
212 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
213 | >
214 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
215 | >
216 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/http-tests.md:
--------------------------------------------------------------------------------
1 | # Laravel 测试之:HTTP 测试
2 |
3 | - [简介](#introduction)
4 | - [Session / 认证](#session-and-authentication)
5 | - [测试 JSON APIs](#testing-json-apis)
6 | - [测试文件上传](#testing-file-uploads)
7 | - [可用的断言方法](#available-assertions)
8 |
9 |
10 | ## 简介
11 |
12 | Laravel 为 HTTP 请求的生成和输出的检查都提供了非常流畅的 API。例如,你可以查看下面的这个测试用例:
13 |
14 | get('/');
33 |
34 | $response->assertStatus(200);
35 | }
36 | }
37 |
38 | `get` 方法会创建一个 `GET` 请求来请求你的应用,而 `assertStatus` 方法断言返回的响应是指定的 HTTP 状态码。除了这个简单的断言之外,Laravel 也包含检查响应标头、内容、JSON 结构等各种断言。
39 |
40 |
41 | ## Session / 认证
42 |
43 | Laravel 提供了几个可在测试时使用 Session 的辅助函数。首先,你需要传递一个数组给 `withSession` 方法来设置 Seesion 数据。这让你在应用程序的测试请求发送之前,先给数据加载 Session 变得简单:
44 |
45 | withSession(['foo' => 'bar'])
52 | ->get('/');
53 | }
54 | }
55 |
56 | 当然,一般使用 Session 时都是用于维持用户的状态,如认证用户。`actingAs` 辅助函数提供了简单的方式来让指定的用户认证为当前的用户。例如,我们可以使用 [模型工厂](/docs/{{version}}/database-testing#writing-factories) 来生成并认证用户:
57 |
58 | create();
67 |
68 | $response = $this->actingAs($user)
69 | ->withSession(['foo' => 'bar'])
70 | ->get('/');
71 | }
72 | }
73 |
74 | 你也可以通过传递 guard 名称作为 `actingAs` 的第二参数以指定用户通过哪种 guard 来认证:
75 |
76 | $this->actingAs($user, 'api')
77 |
78 |
79 | ## Testing JSON APIs
80 |
81 | Laravel 也提供了几个辅助函数来测试 JSON APIs 及其响应。例如,`json`,`get`,`post`,`put`,`patch` 和 `delete` 方法可以用于发出各种 HTTP 动作的请求。你也可以轻松的传入数据或标头到这些方法上。首先,让我们来编写一个测试,将一个 `POST` 请求发送至 `/user` ,并断言其会返回预期数据:
82 |
83 | json('POST', '/user', ['name' => 'Sally']);
95 |
96 | $response
97 | ->assertStatus(200)
98 | ->assertJson([
99 | 'created' => true,
100 | ]);
101 | }
102 | }
103 |
104 | > {tip} `assertJson` 方法会将响应转换为数组并且利用 `PHPUnit::assertArraySubset` 方法来验证传入的数组是否在应用返回的 JSON 中。也就是说,即使有其它的属性存在于该 JSON 响应中,但是只要指定的片段存在,此测试仍然会通过。
105 |
106 |
107 | ### 验证完全匹配
108 |
109 | 如果你想验证传入的数组是否与应用返回的 JSON **完全** 匹配,你可以使用 `assertExactJson` 方法:
110 |
111 | json('POST', '/user', ['name' => 'Sally']);
123 |
124 | $response
125 | ->assertStatus(200)
126 | ->assertExactJson([
127 | 'created' => true,
128 | ]);
129 | }
130 | }
131 |
132 |
133 | ## 测试文件上传
134 |
135 | `Illuminate\Http\UploadedFile` 类提供了一个 `fake` 方法,可用其生成用于测试的模拟文件或图像。将其与 `Storage` facade 的 `fake` 方法结合使用,可极大地简化文件上传的测试。例如,你可以结合这两个功能轻松测试头像上传表单:
136 |
137 | json('POST', '/avatar', [
155 | 'avatar' => UploadedFile::fake()->image('avatar.jpg')
156 | ]);
157 |
158 | // 断言文件已存储...
159 | Storage::disk('avatars')->assertExists('avatar.jpg');
160 |
161 | // 断言文件不存在...
162 | Storage::disk('avatars')->assertMissing('missing.jpg');
163 | }
164 | }
165 |
166 | #### 自定义模拟文件
167 |
168 | 当使用 `fake` 方法创建文件时,你可以指定图片的宽度、高度和大小,以便更好地测试你的验证规则:
169 |
170 | UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);
171 |
172 | 除了创建图片,你还可以使用 `create` 方法创建任何其他类型的文件:
173 |
174 | UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);
175 |
176 |
177 | ## 可用的断言方法
178 |
179 | Laravel 为你的 [PHPUnit](https://phpunit.de/) 测试提供了各种各样的自定义断言方法。`json`,`get`,`post`,`put` 和 `delete` 这些测试方法返回的响应都可以使用这些断言方法:
180 |
181 | Method | Description
182 | ------------- | -------------
183 | `$response->assertSuccessful();` | 断言该响应具有成功的状态码。
184 | `$response->assertStatus($code);` | 断言该响应具有指定的状态码。
185 | `$response->assertRedirect($uri);` | 断言该响应被重定向至指定的 URI。
186 | `$response->assertHeader($headerName, $value = null);` | 断言该响应存在指定的标头。
187 | `$response->assertCookie($cookieName, $value = null);` | 断言该响应包含了指定的 Cookie。
188 | `$response->assertPlainCookie($cookieName, $value = null);` | 断言该响应包含了指定的 Cookie(未加密)。
189 | `$response->assertSessionHas($key, $value = null);` | 断言该 Session 包含指定的数据。
190 | `$response->assertSessionHasErrors(array $keys, $errorBag = 'default');` | 断言该 Session 包含指定的字段的错误信息。
191 | `$response->assertSessionMissing($key);` | 断言该 Session 不包含指定的键。
192 | `$response->assertJson(array $data);` | 断言该响应包含指定的 JSON 数据。
193 | `$response->assertJsonFragment(array $data);` | 断言该响应包含指定的 JSON 片段。
194 | `$response->assertJsonMissing(array $data);` | 断言该响应不包含指定的 JSON 片段。
195 | `$response->assertExactJson(array $data);` | 断言该响应包含完全匹配指定的 JSON 数据。
196 | `$response->assertJsonStructure(array $structure);` | 断言该响应存在指定的 JSON 结构。
197 | `$response->assertViewIs($value);` | 断言该视图响应的视图名称为指定的值。
198 | `$response->assertViewHas($key, $value = null);` | 断言该视图响应存在指定的数据。
199 |
200 | ## 译者署名
201 |
202 | | 用户名 | 头像 | 职能 | 签名 |
203 | |---|---|---|---|
204 | | [@springjk](https://laravel-china.org/users/4550) |
| 翻译 | 再怎么说我也是我西北一匹狼 |
205 |
206 |
207 | ---
208 |
209 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
210 | >
211 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
212 | >
213 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/installation.md:
--------------------------------------------------------------------------------
1 | # Laravel 安装指南
2 |
3 | - [安装](#installation)
4 | - [服务器要求](#server-requirements)
5 | - [安装 Laravel](#installing-laravel)
6 | - [配置](#configuration)
7 | - [Web 服务器配置](#web-server-configuration)
8 | - [优雅链接](#pretty-urls)
9 |
10 |
11 | ## 安装
12 |
13 | > {video} 如果你喜欢看视频学习,Laracasts 为你提供了免费而又全面的 Laravel 教程。
14 |
15 |
16 | ### 服务器要求
17 |
18 | Laravel 框架对系统有一些要求。所有这些要求 Laravel Homestead 虚拟机都能满足,因此强烈建议你使用 Homestead 作为你本地的 Laravel 开发环境。
19 |
20 | 但如果你不使用 Homestead,则需要确保你的服务器符合以下要求:
21 |
22 |
23 | - PHP >= 7.0.0
24 | - PHP OpenSSL 扩展
25 | - PHP PDO 扩展
26 | - PHP Mbstring 扩展
27 | - PHP Tokenizer 扩展
28 | - PHP XML 扩展
29 |
30 |
31 |
32 | ### 安装 Laravel
33 |
34 | Laravel 利用 [Composer](https://getcomposer.org) 来管理依赖。所以,在使用 Laravel 之前,请确保你的机器上安装了 Composer。
35 |
36 | #### 通过 Laravel 安装器
37 |
38 | 首先,使用 Composer 下载 Laravel 安装程序:
39 |
40 | composer global require "laravel/installer"
41 | 确保 `$HOME/.composer/vendor/bin` 目录(或你的操作系统的等效目录)已经放在你的环境变量 $PATH 中,以便系统可以找到 `laravel` 的可执行文件。
42 |
43 | 安装之后, `laravel new` 命令会在你指定的目录中创建一个新的 Laravel 项目。例如,`laravel new blog` 命令会创建一个名为 `blog` 的目录,其中包含所有已经安装好的 Laravel 的依赖项:
44 |
45 | laravel new blog
46 |
47 | #### 通过 Composer 创建项目
48 |
49 | 或者,你还可以通过在终端中运行 `create-project` 命令来安装 Laravel:
50 |
51 | composer create-project --prefer-dist laravel/laravel blog "5.5.*"
52 |
53 | #### 本地开发服务器
54 |
55 | 如果你在本地安装了 PHP,并且想使用 PHP 内置的开发服务器来为你的应用程序提供服务,那就使用 Artisan 命令 `serve`。这个命令会在 `http://localhost:8000` 上启动开发服务器:
56 |
57 | php artisan serve
58 | 当然,对于本地开发来说,最好的选择还是 [Homestead](/docs/{{version}}/homestead) 和 [Valet](/docs/{{version}}/valet)。
59 |
60 |
61 | ### 配置
62 |
63 | #### Public 目录
64 |
65 | 安装 Laravel 之后,你要将 Web 服务器的根目录指向 `public` 目录。该目录下的 `index.php` 文件将作为所有进入应用程序的 HTTP 请求的前端控制器。
66 |
67 | #### 配置文件
68 |
69 | Laravel 框架的所有配置文件都放在 `config` 目录中。每个选项都有注释,方便你随时查看文件并熟悉可用的选项。
70 |
71 | #### 目录权限
72 |
73 | 安装完 Laravel 后,你可能需要给这两个文件配置读写权限:`storage` 目录和 `bootstrap/cache` 目录应该允许 Web 服务器写入,否则 Laravel 将无法运行。如果你使用的是 [Homestead](/docs/{{version}}/homestead) 虚拟机,这些权限已经为你设置好了。
74 |
75 | #### 应用密钥
76 |
77 | 安装 Laravel 之后下一件应该做的事就是将应用程序的密钥设置为随机字符串。如果你是通过 Composer 或 Laravel 安装器安装的 Laravel,那这个密钥已经为你通过 `php artisan key:generate` 命令设置好了。
78 |
79 | 通常来说,这个字符串长度为 32 个字符。密钥可以在 `.env` 环境文件中设置。前提是你要将 `.env.example` 文件重命名为 `.env`。**如果应用程序密钥没有被设置,就不能确保你的用户会话和其他加密数据的安全!**
80 |
81 | #### 更多的配置
82 |
83 | 除了以上的配置,Laravel 几乎就不需要再配置什么了。你随时就能开发!但是,可能的话,还是希望你查看 `config/app.php` 文件及其注释。它包含几个你可能想要根据你的应用来更改的选项,比如 `timezone` 和 `locale`。
84 |
85 | 你还可能想要配置 Laravel 的其他几个组件,例如:
86 |
87 |
88 | - [缓存](/docs/{{version}}/cache#configuration)
89 | - [数据库](/docs/{{version}}/database#configuration)
90 | - [会话](/docs/{{version}}/session#configuration)
91 |
92 |
93 |
94 | ## Web 服务器配置
95 |
96 |
97 | ### 优雅链接
98 |
99 | #### Apache
100 |
101 | Laravel 使用 `public/.htaccess` 文件来为前端控制器提供隐藏了 `index.php` 的优雅链接。如果你的 Laravel 使用了 Apache 作为服务容器,请务必启用 `mod_rewrite `模块,让服务器能够支持 `.htaccess` 文件的解析。
102 |
103 | 如果 Laravel 附带的 `.htaccess` 文件不起作用,就尝试用下面的方法代替:
104 |
105 | Options +FollowSymLinks
106 | RewriteEngine On
107 |
108 | RewriteCond %{REQUEST_FILENAME} !-d
109 | RewriteCond %{REQUEST_FILENAME} !-f
110 | RewriteRule ^ index.php [L]
111 |
112 | #### Nginx
113 |
114 | 如果你使用的是 Nginx,在你的站点配置中加入以下内容,它将会将所有请求都引导到 `index.php` 前端控制器:
115 |
116 | location / {
117 | try_files $uri $uri/ /index.php?$query_string;
118 | }
119 |
120 | 当然,使用 [Homestead](/docs/{{version}}/homestead) 或者 [Valet](/docs/{{version}}/valet) 时,你无需配置这些。
121 |
122 | ## 译者署名
123 |
124 | | 用户名 | 头像 | 职能 | 签名 |
125 | |---|---|---|---|
126 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| 翻译 | Stay Hungry. Stay Foolish. |
127 |
128 |
129 | ---
130 |
131 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
132 | >
133 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
134 | >
135 | > 文档永久地址: https://d.laravel-china.org
136 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright © Taylor Otwell
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/lifecycle.md:
--------------------------------------------------------------------------------
1 | # Laravel 的请求生命周期
2 |
3 | - [简介](#introduction)
4 | - [生命周期概述](#lifecycle-overview)
5 | - [聚焦服务提供器](#focus-on-service-providers)
6 |
7 |
8 | ## 简介
9 |
10 | 在日常生活中使用任何工具时,如果理解了该工具的工作原理,使用时能更加运用自如。这对于应用开发来说也一样,当你能真正懂得一个功能背后实现原理时,你就离成为大神不远了。
11 |
12 | 文档存在目的是为了让你更加清晰地了解 Laravel 框架是如何工作。通过更好地了解整个框架,让一切都不再感觉很「神奇」。相信我,这有助于你更加清楚自己在做什么,对自己想做的事情更加胸有成竹。就算你不明白所有的术语,也不用因此失去信心!只要多一点尝试、学着如何运用,随着你浏览文档的其他部分,你的知识一定会因此增长。
13 |
14 |
15 | ## 生命周期概述
16 |
17 | ### 开始
18 |
19 | `public/index.php` 文件是所有对 Laravel 应用程序的请求的入口点。而所有的请求都是经由你的 Web 服务器(Apache/Nginx)通过配置引导到这个文件。`index.php` 文件不包含太多的代码,却是加载框架的起点。
20 |
21 | `index.php` 文件加载 Composer 生成定义的自动加载器,然后从 `bootstrap/app.php` 脚本中检索 Laravel 应用程序的实例。Laravel 本身采取的第一个动作是创建一个 application/ [service container](/docs/{{version}}/container) 的实例。
22 |
23 | ### HTTP/控制器内核
24 |
25 | 接下来,根据进入应用程序的请求类型来将传入的请求发送到 HTTP 内核或控制台内核。而这两个内核是用来作为所有请求都要通过的中心位置。现在,我们先看看位于 `app/Http/Kernel.php` 中的 HTTP 内核。
26 |
27 | HTTP 内核继承了 `Illuminate\Foundation\Http\Kernel` 类,它定义了在执行请求之前运行的 `bootstrappers` 数组。这个数组负责在实际处理请求之前完成这些内容:配置错误处理、配置日志记录、[检测应用程序环境](/docs/{{version}}/configuration#environment-configuration) 以及执行其他需要完成的任务。
28 |
29 | HTTP 内核还定义了所有请求被应用程序处理之前必须经过的 HTTP 中间件的列表。这些中间件处理 [HTTP 会话](/docs/{{version}}/session) 的读写、确定应用程序是否处于维护模式、[验证 CSRF 令牌](/docs/{{version}}/csrf)等。
30 |
31 | HTTP 内核的 `handle` 方法的方法签名非常简单:接收 `Request` 并返回 `Response`。可以把内核当作是代表整个应用程序的大黑盒,给它 HTTP 请求,它就返回 HTTP 响应。
32 |
33 | #### 服务提供器
34 |
35 | 最重要的内核引导操作之一是加载应用程序的 [服务提供器](/docs/{{version}}/providers)。应用程序的所有服务提供器都在 `config/app.php` 配置文件的 `providers` 数组中配置。首先,所有提供器都会调用 `register` 方法,接着,由 `boot` 方法负责调用所有被注册提供器。
36 |
37 | 服务提供器负责引导所有框架的各种组件,如数据库、队列、验证和路由组件。也就是说,框架提供的每个功能都它们来引导并配置。因此也可以说,服务提供器是整个 Laravel 引导过程中最重要的方面。
38 |
39 | #### 分配请求
40 |
41 | 一旦引导了应用程序且注册所有服务提供器,`Request` 请求就会被转交给路由器来进行调度。路由器将请求发送到路由或控制器或任何运行于路由的特定中间件。
42 |
43 |
44 | ## 聚焦服务提供器
45 |
46 | 服务提供器是引导 Laravel 应用程序真正的关键。创建应用程序实例、注册服务提供器,并将请求交给被引导的应用程序。就是这么简单~
47 |
48 | 牢牢掌握 Laravel 应用程序如何通过服务提供器来构建和引导是非常有价值的。应用程序的默认服务提供器存储在 `app/Providers` 目录中。
49 |
50 | 默认情况下,`AppServiceProvider` 没什么内容。这个提供器是用来添加自定义的应用程序引导和服务容器绑定。对于大型应用程序来说,可以创建几个服务提供器,让每个服务提供器都具有更精细的引导类型。
51 |
52 | ## 译者署名
53 |
54 | | 用户名 | 头像 | 职能 | 签名 |
55 | |---|---|---|---|
56 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| 翻译 | Stay Hungry. Stay Foolish. |
57 |
58 |
59 | ---
60 |
61 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
62 | >
63 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
64 | >
65 | > 文档永久地址: https://d.laravel-china.org
66 |
--------------------------------------------------------------------------------
/links.php:
--------------------------------------------------------------------------------
1 | '翻译说明',
6 | 'link' => '/docs/{{version}}/about'
7 | ],
8 | [
9 | 'text' => '发行说明',
10 | 'link' => '/docs/{{version}}/releases'
11 | ],
12 | [
13 | 'text' => '升级说明',
14 | 'link' => '/docs/{{version}}/upgrade'
15 | ],
16 | [
17 | 'text' => '贡献导引',
18 | 'link' => '/docs/{{version}}/contributions'
19 | ],
20 | [
21 | 'text' => '安装',
22 | 'link' => '/docs/{{version}}/installation'
23 | ],
24 | [
25 | 'text' => '配置信息',
26 | 'link' => '/docs/{{version}}/configuration'
27 | ],
28 | [
29 | 'text' => '文件夹结构',
30 | 'link' => '/docs/{{version}}/structure'
31 | ],
32 | [
33 | 'text' => 'Homestead',
34 | 'link' => '/docs/{{version}}/homestead'
35 | ],
36 | [
37 | 'text' => 'Valet',
38 | 'link' => '/docs/{{version}}/valet'
39 | ],
40 | [
41 | 'text' => '部署',
42 | 'link' => '/docs/{{version}}/deployment'
43 | ],
44 | [
45 | 'text' => '请求周期',
46 | 'link' => '/docs/{{version}}/lifecycle'
47 | ],
48 | [
49 | 'text' => '服务容器',
50 | 'link' => '/docs/{{version}}/container'
51 | ],
52 | [
53 | 'text' => '服务提供者',
54 | 'link' => '/docs/{{version}}/providers'
55 | ],
56 | [
57 | 'text' => 'Facades',
58 | 'link' => '/docs/{{version}}/facades'
59 | ],
60 | [
61 | 'text' => 'Contracts',
62 | 'link' => '/docs/{{version}}/contracts'
63 | ],
64 | [
65 | 'text' => '路由',
66 | 'link' => '/docs/{{version}}/routing'
67 | ],
68 | [
69 | 'text' => '中间件',
70 | 'link' => '/docs/{{version}}/middleware'
71 | ],
72 | [
73 | 'text' => 'CSRF 保护',
74 | 'link' => '/docs/{{version}}/csrf'
75 | ],
76 | [
77 | 'text' => '控制器',
78 | 'link' => '/docs/{{version}}/controllers'
79 | ],
80 | [
81 | 'text' => '请求',
82 | 'link' => '/docs/{{version}}/requests'
83 | ],
84 | [
85 | 'text' => '响应',
86 | 'link' => '/docs/{{version}}/responses'
87 | ],
88 | [
89 | 'text' => '视图',
90 | 'link' => '/docs/{{version}}/views'
91 | ],
92 | [
93 | 'text' => '生成 URL',
94 | 'link' => '/docs/{{version}}/urls'
95 | ],
96 | [
97 | 'text' => 'Session',
98 | 'link' => '/docs/{{version}}/session'
99 | ],
100 | [
101 | 'text' => '表单验证',
102 | 'link' => '/docs/{{version}}/validation'
103 | ],
104 | [
105 | 'text' => '错误与日志',
106 | 'link' => '/docs/{{version}}/errors'
107 | ],
108 | [
109 | 'text' => 'Blade 模板',
110 | 'link' => '/docs/{{version}}/blade'
111 | ],
112 | [
113 | 'text' => '本地化',
114 | 'link' => '/docs/{{version}}/localization'
115 | ],
116 | [
117 | 'text' => '前端指南',
118 | 'link' => '/docs/{{version}}/frontend'
119 | ],
120 | [
121 | 'text' => '编辑资源 Mix',
122 | 'link' => '/docs/{{version}}/mix'
123 | ],
124 | [
125 | 'text' => '用户认证',
126 | 'link' => '/docs/{{version}}/authentication'
127 | ],
128 | [
129 | 'text' => 'API 认证',
130 | 'link' => '/docs/{{version}}/passport'
131 | ],
132 | [
133 | 'text' => '用户授权',
134 | 'link' => '/docs/{{version}}/authorization'
135 | ],
136 | [
137 | 'text' => '加密解密',
138 | 'link' => '/docs/{{version}}/encryption'
139 | ],
140 | [
141 | 'text' => '哈希',
142 | 'link' => '/docs/{{version}}/hashing'
143 | ],
144 | [
145 | 'text' => '重置密码',
146 | 'link' => '/docs/{{version}}/passwords'
147 | ],
148 | [
149 | 'text' => 'Artisan 命令行',
150 | 'link' => '/docs/{{version}}/artisan'
151 | ],
152 | [
153 | 'text' => '广播系统',
154 | 'link' => '/docs/{{version}}/broadcasting'
155 | ],
156 | [
157 | 'text' => '缓存系统',
158 | 'link' => '/docs/{{version}}/cache'
159 | ],
160 | [
161 | 'text' => '集合',
162 | 'link' => '/docs/{{version}}/collections'
163 | ],
164 | [
165 | 'text' => '事件系统',
166 | 'link' => '/docs/{{version}}/events'
167 | ],
168 | [
169 | 'text' => '文件存储',
170 | 'link' => '/docs/{{version}}/filesystem'
171 | ],
172 | [
173 | 'text' => '辅助函数',
174 | 'link' => '/docs/{{version}}/helpers'
175 | ],
176 | [
177 | 'text' => '邮件发送',
178 | 'link' => '/docs/{{version}}/mail'
179 | ],
180 | [
181 | 'text' => '消息通知',
182 | 'link' => '/docs/{{version}}/notifications'
183 | ],
184 | [
185 | 'text' => '扩展包开发',
186 | 'link' => '/docs/{{version}}/packages'
187 | ],
188 | [
189 | 'text' => '队列',
190 | 'link' => '/docs/{{version}}/queues'
191 | ],
192 | [
193 | 'text' => '任务调度',
194 | 'link' => '/docs/{{version}}/scheduling'
195 | ],
196 | [
197 | 'text' => '快速入门',
198 | 'link' => '/docs/{{version}}/database'
199 | ],
200 | [
201 | 'text' => '查询构造器',
202 | 'link' => '/docs/{{version}}/queries'
203 | ],
204 | [
205 | 'text' => '分页',
206 | 'link' => '/docs/{{version}}/pagination'
207 | ],
208 | [
209 | 'text' => '数据库迁移',
210 | 'link' => '/docs/{{version}}/migrations'
211 | ],
212 | [
213 | 'text' => '数据填充',
214 | 'link' => '/docs/{{version}}/seeding'
215 | ],
216 | [
217 | 'text' => 'Redis',
218 | 'link' => '/docs/{{version}}/redis'
219 | ],
220 | [
221 | 'text' => '快速入门',
222 | 'link' => '/docs/{{version}}/eloquent'
223 | ],
224 | [
225 | 'text' => '模型关联',
226 | 'link' => '/docs/{{version}}/eloquent-relationships'
227 | ],
228 | [
229 | 'text' => 'Eloquent 集合',
230 | 'link' => '/docs/{{version}}/eloquent-collections'
231 | ],
232 | [
233 | 'text' => '修改器',
234 | 'link' => '/docs/{{version}}/eloquent-mutators'
235 | ],
236 | [
237 | 'text' => 'API 资源',
238 | 'link' => '/docs/{{version}}/eloquent-resources'
239 | ],
240 | [
241 | 'text' => '序列化',
242 | 'link' => '/docs/{{version}}/eloquent-serialization'
243 | ],
244 | [
245 | 'text' => '快速入门',
246 | 'link' => '/docs/{{version}}/testing'
247 | ],
248 | [
249 | 'text' => 'HTTP 测试',
250 | 'link' => '/docs/{{version}}/http-tests'
251 | ],
252 | [
253 | 'text' => '浏览器测试 Dusk',
254 | 'link' => '/docs/{{version}}/dusk'
255 | ],
256 | [
257 | 'text' => '数据库测试',
258 | 'link' => '/docs/{{version}}/database-testing'
259 | ],
260 | [
261 | 'text' => '测试模拟器',
262 | 'link' => '/docs/{{version}}/mocking'
263 | ],
264 | [
265 | 'text' => 'Cashier 交易工具包',
266 | 'link' => '/docs/{{version}}/billing'
267 | ],
268 | [
269 | 'text' => 'Envoy 部署工具',
270 | 'link' => '/docs/{{version}}/envoy'
271 | ],
272 | [
273 | 'text' => 'Horizon',
274 | 'link' => '/docs/{{version}}/horizon'
275 | ],
276 | [
277 | 'text' => 'Passport OAuth 认证',
278 | 'link' => '/docs/{{version}}/passport'
279 | ],
280 | [
281 | 'text' => 'Scout 全文搜索',
282 | 'link' => '/docs/{{version}}/scout'
283 | ],
284 | [
285 | 'text' => 'Socialite 社会化登录',
286 | 'link' => '/docs/{{version}}/socialite'
287 | ]
288 | ];
289 |
290 |
--------------------------------------------------------------------------------
/localization.md:
--------------------------------------------------------------------------------
1 | # Laravel 的本地化功能
2 |
3 | - [简介](#introduction)
4 | - [定义翻译字符串](#defining-translation-strings)
5 | - [使用短键](#using-short-keys)
6 | - [使用翻译字符串作为键](#using-translation-strings-as-keys)
7 | - [检索翻译字符串](#retrieving-translation-strings)
8 | - [翻译语句中的参数替换](#replacing-parameters-in-translation-strings)
9 | - [复数](#pluralization)
10 | - [重写扩展包的语言文件](#overriding-package-language-files)
11 |
12 |
13 | ## 简介
14 |
15 | Laravel 的本地化功能为在应用程序中支持多种语言提供方便的方法来检索各种语言的字符串。语言字符串存储在 `resources/lang` 目录下的文件里。在此目录中,但凡应用支持的语言都应该有一个对应的子目录:
16 |
17 | /resources
18 | /lang
19 | /en
20 | messages.php
21 | /es
22 | messages.php
23 |
24 | 所有语言文件只返回键值对数组,例如:
25 |
26 | 'Welcome to our application'
30 | ];
31 |
32 | ### 区域设置
33 |
34 | 应用的默认语言保存在 `config/app.php` 配置文件中。你可以根据需要修改当前设置。还可以使用 `App` Facade 的 `setLocale` 方法动态地更改当前语言:
35 |
36 | Route::get('welcome/{locale}', function ($locale) {
37 | App::setLocale($locale);
38 |
39 | //
40 | });
41 |
42 | 你也可以设置 「备用语言」 ,它将会在当前语言不包含给定的翻译字符串时被使用。像默认语言一样,备用语言也可以在 `config/app.php` 配置文件设置:
43 |
44 | 'fallback_locale' => 'en',
45 |
46 | #### 确定当前语言环境
47 |
48 | 你可以使用 `App` Facade 的 `getLocale` 及 `isLocale` 方法确定当前的区域设置或者检查语言环境是否为给定值:
49 |
50 | $locale = App::getLocale();
51 |
52 | if (App::isLocale('en')) {
53 | //
54 | }
55 |
56 |
57 | ## 定义翻译字符串
58 |
59 |
60 | ### 使用短键
61 |
62 | 通常,翻译字符串存放在 `resources/lang` 目录下的文件里。在此目录中但凡应用支持的语言都应该有一个对应的子目录:
63 |
64 | /resources
65 | /lang
66 | /en
67 | messages.php
68 | /es
69 | messages.php
70 |
71 | 所有语言文件只返回键值对数组,例如:
72 |
73 | 'Welcome to our application'
79 | ];
80 |
81 |
82 | ### 使用翻译字符串作为键
83 |
84 | 对于有大量翻译需求的应用, 如果每一条翻译语句都使用 「短键」 来定义,那么当你在视图中尝试去引用这些 「短键」 的时候,很容易变得混乱。因此,Laravel 也提供支持使用字符串的「默认」翻译作为关键字定义翻译字符串。
85 |
86 | 使用翻译字符串作为键的翻译文件作为 JSON 文件存储在 `resources/lang` 目录中。例如,如果你的应用中有西班牙语翻译,你应该新建一个 `resources/lang/es.json` 文件:
87 |
88 | {
89 | "I love programming.": "Me encanta programar."
90 | }
91 |
92 |
93 | ## 检索翻译字符串
94 |
95 | 你可以使用辅助函数 `__` 从语言文件中检索,`__` 方法接受翻译字符串的文件名和键值作为其第一个参数。例如,让我们检索 `resources/lang/messages.php` 语言文件中的 `welcome` 翻译字符串:
96 |
97 | echo __('messages.welcome');
98 |
99 | echo __('I love programming.');
100 |
101 | 如果使用 [Blade 模板引擎](/docs/{{version}}/blade),可以在视图文件中使用 `{{ }}` 语法或者使用 `@lang` 指令来打印翻译字符串:
102 |
103 | {{ __('messages.welcome') }}
104 |
105 | @lang('messages.welcome')
106 |
107 | 如果指定的翻译字符串不存在,`__` 方法则会简单地返回指定的翻译字符串键名。所以,如果上述示例中的翻译字符串键不存在,那么 `__` 方法则会返回 `messages.welcome` 。
108 |
109 |
110 | ### 翻译语句中的参数替换
111 |
112 | 如果需要也可以在翻译字符串中定义占位符。所有的占位符都有一个前缀 `:`。例如,你可以使用持有人名称定义欢迎消息:
113 |
114 | 'welcome' => 'Welcome, :name',
115 |
116 | 你可以在 `__` 方法中传递一个数组作为第二个参数,它会将数组的值替换到翻译字符串的占位符中:
117 |
118 | echo __('messages.welcome', ['name' => 'dayle']);
119 |
120 | 如果你的占位符中包含了首字母大写或者全体大写,翻译过来的内容也会做相应的处理:
121 |
122 | 'welcome' => 'Welcome, :NAME', // Welcome, DAYLE
123 | 'goodbye' => 'Goodbye, :Name', // Goodbye, Dayle
124 |
125 |
126 |
127 | ### 复数
128 |
129 | 复数是个复杂的问题,不同语言对于复数有不同的规则。使用管道符 `|` ,可以区分字符串的单复数形式:
130 |
131 | 'apples' => 'There is one apple|There are many apples',
132 |
133 | 你甚至可以创建更复杂的复数规则,为多个数字范围指定翻译字符串:
134 |
135 | 'apples' => '{0} There are none|[1,19] There are some|[20,*] There are many',
136 |
137 | 在定义具有复数选项的翻译字符串之后,你可以使用 `trans_choice` 方法来检索给定「数量」的内容。在这个例子中,设置「总数」为 10 ,符合数量范围 1 至 19,所以会得到 `There are some` 这条复数语句:
138 |
139 | echo trans_choice('messages.apples', 10);
140 |
141 |
142 | ## 重写扩展包的语言文件
143 |
144 | 部分扩展包可能会附带自己的语言文件。你可以通过在 `resources/lang/vendor/{package}/{locale}` 放置文件来重写它们,而不是直接修改扩展包的核心文件。
145 |
146 | 例如,你需要重写 `skyrim/hearthfire` 扩展包的英文语言文件 `messages.php` ,则需要把文件放置在 `resources/lang/vendor/hearthfire/en/messages.php` 。在这个文件中只应定义要覆盖的翻译字符串。任何没有被覆盖的翻译字符串仍将从扩展包的原始语言文件中加载。
147 |
148 | ## 译者署名
149 |
150 | | 用户名 | 头像 | 职能 | 签名 |
151 | |---|---|---|---|
152 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
153 |
154 | ---
155 |
156 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
157 | >
158 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
159 | >
160 | > 文档永久地址: https://d.laravel-china.org
161 |
--------------------------------------------------------------------------------
/middleware.md:
--------------------------------------------------------------------------------
1 | # Laravel 的路由中间件
2 |
3 | - [简介](#introduction)
4 | - [定义中间件](#defining-middleware)
5 | - [注册中间件](#registering-middleware)
6 | - [全局中间件](#global-middleware)
7 | - [为路由分配中间件](#assigning-middleware-to-routes)
8 | - [中间件组](#middleware-groups)
9 | - [中间件参数](#middleware-parameters)
10 | - [Terminable 中间件](#terminable-middleware)
11 |
12 |
13 | ## 简介
14 |
15 | Laravel 中间件提供了一种方便的机制来过滤进入应用的 HTTP 请求。例如,Laravel 内置了一个中间件来验证用户的身份认证。如果用户没有通过身份认证,中间件会将用户重定向到登录界面。但是,如果用户被认证,中间件将允许该请求进一步进入该应用。
16 |
17 | 当然,除了身份认证以外,还可以编写另外的中间件来执行各种任务。例如:CORS 中间件可以负责为所有离开应用的响应添加合适的头部信息;日志中间件可以记录所有传入应用的请求。
18 |
19 | Laravel 自带了一些中间件,包括身份验证、CSRF 保护等。所有这些中间件都位于 `app/Http/Middleware` 目录。
20 |
21 |
22 | ## 定义中间件
23 |
24 | 运行Artisan 命令 `make:middleware` 创建新的中间件:
25 |
26 | php artisan make:middleware CheckAge
27 |
28 | 该命令将会在 `app/Http/Middleware` 目录内新建一个 `CheckAge` 类。在这个中间件里,我们仅允许提供的参数 `age` 大于 200 的请求访问该路由。否则,我们会将用户重定向到 `home` 。
29 |
30 | age <= 200) {
48 | return redirect('home');
49 | }
50 |
51 | return $next($request);
52 | }
53 |
54 | }
55 |
56 | 如你所见,若给定的 `age` 小于等于 `200`,那中间件将返回一个 HTTP 重定向到客户端;否则,请求将进一步传递到应用中。要让请求继续传递到应用程序中(即允许「通过」中间件验证的),只需使用 `$request` 作为参数去调用回调函数 `$next` 。
57 |
58 | 最好将中间件想象为一系列 HTTP 请求必须经过才能触发你应用的「层」。每一层都会检查请求(是否符合某些条件),(如果不符合)甚至可以(在请求访问你的应用之前)完全拒绝掉。
59 |
60 | ### 前置 & 后置中间件
61 |
62 | 中间件是在请求之前或之后运行取决于中间件本身。例如,以下的中间件会在应用处理请求 **之前** 执行一些任务:
63 |
64 |
101 | ## 注册中间件
102 |
103 |
104 | ### 全局中间件
105 |
106 | 如果你想让中间件在你应用的每个 HTTP 请求期间运行,只需在 `app/Http/Kernel.php` 类中的 `$middleware` 属性里列出这个中间件类 。
107 |
108 |
109 | ### 为路由分配中间件
110 |
111 | 如果要为特定的路由分配中间件,
112 |
113 | 如果想为特殊的路由指定中间件,首先应该在 `app/Http/Kernel.php` 文件内为该中间件指定一个 `键`。默认情况下,`Kernel` 类的 `$routeMiddleware` 属性包含 Laravel 内置的中间件条目。要加入自定义的,只需把它附加到列表后并为其分配一个自定义 `键` 即可。例如:
114 |
115 | // 在 App\Http\Kernel 类中
116 |
117 | protected $routeMiddleware = [
118 | 'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
119 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
120 | 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
121 | 'can' => \Illuminate\Auth\Middleware\Authorize::class,
122 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
123 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
124 | ];
125 |
126 | 一旦在 Kernel 中定义了中间件,就可使用 `middleware` 方法将中间件分配给路由:
127 |
128 | Route::get('admin/profile', function () {
129 | //
130 | })->middleware('auth');
131 |
132 | 你还可以为路由分配多个中间件:
133 |
134 | Route::get('/', function () {
135 | //
136 | })->middleware('first', 'second');
137 |
138 | 分配中间件时,你还可以传递完整的类名:
139 |
140 | use App\Http\Middleware\CheckAge;
141 |
142 | Route::get('admin/profile', function () {
143 | //
144 | })->middleware(CheckAge::class);
145 |
146 |
147 | ### 中间件组
148 |
149 | 有时你可能想用单一的 `键` 为几个中间件分组,使其更容易分配到路由。可以使用 Kernel 类的 `$middlewareGroups` 属性来实现。
150 |
151 | Laravel 自带的 `web` 和 `api` 中间件组包含了你可能会应用到 Web UI 和 API 路由的常见的中间件:
152 |
153 | /**
154 | * 应用程序的路由中间件组
155 | *
156 | * @var array
157 | */
158 | protected $middlewareGroups = [
159 | 'web' => [
160 | \App\Http\Middleware\EncryptCookies::class,
161 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
162 | \Illuminate\Session\Middleware\StartSession::class,
163 | \Illuminate\View\Middleware\ShareErrorsFromSession::class,
164 | \App\Http\Middleware\VerifyCsrfToken::class,
165 | \Illuminate\Routing\Middleware\SubstituteBindings::class,
166 | ],
167 |
168 | 'api' => [
169 | 'throttle:60,1',
170 | 'auth:api',
171 | ],
172 | ];
173 |
174 | 可以使用与单个中间件相同的语法将中间件组分配给路由和控制器操作。重申一遍,中间件组只是更方便地实现了一次为路由分配多个中间件。
175 |
176 | Route::get('/', function () {
177 | //
178 | })->middleware('web');
179 |
180 | Route::group(['middleware' => ['web']], function () {
181 | //
182 | });
183 |
184 | > {tip} 无需任何操作,`RouteServiceProvider` 会自动将 `web` 中间件组应用于你的的 `routes/web.php` 文件。
185 |
186 |
187 | ## 中间件参数
188 |
189 | 中间件也可以接受额外的参数。例如,如果应用需要在运行特定操作前验证经过身份认证的用户是否具备给定的「角色」,你可以新建一个 `CheckRole` 中间件,由它来接收「角色」名称作为附加参数。
190 |
191 | 附加的中间件参数应该在 `$next` 参数之后被传递:
192 |
193 | user()->hasRole($role)) {
212 | // 重定向...
213 | }
214 |
215 | return $next($request);
216 | }
217 |
218 | }
219 |
220 | 定义路由时通过一个 `:` 来隔开中间件名称和参数来指定中间件参数。多个参数就使用逗号分隔:
221 |
222 | Route::put('post/{id}', function ($id) {
223 | //
224 | })->middleware('role:editor');
225 |
226 |
227 | ## Terminable 中间件
228 |
229 | 有时中间件可能需要在 HTTP 响应发送到浏览器之后处理一些工作。比如,Laravel 内置的「session」中间件会在响应发送到浏览器之后将会话数据写入存储器中。如果你在中间件中定义一个 `terminate` 方法,则会在响应发送到浏览器后自动调用:
230 |
231 | | 翻译 | [@半夏](https://github.com/mintgreen1108) |
259 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
260 |
261 |
262 | ---
263 |
264 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
265 | >
266 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
267 | >
268 | > 文档永久地址: https://d.laravel-china.org
269 |
--------------------------------------------------------------------------------
/pagination.md:
--------------------------------------------------------------------------------
1 | # Laravel 的分页功能
2 |
3 | - [简介](#introduction)
4 | - [基本用法](#basic-usage)
5 | - [查询构造器分页](#paginating-query-builder-results)
6 | - [Eloquent 分页](#paginating-eloquent-results)
7 | - [手动创建分页](#manually-creating-a-paginator)
8 | - [显示分页结果](#displaying-pagination-results)
9 | - [将结果转换为 JSON](#converting-results-to-json)
10 | - [自定义分页视图](#customizing-the-pagination-view)
11 | - [分页器实例方法](#paginator-instance-methods)
12 |
13 |
14 | ## 简介
15 |
16 | 在大多数的框架中,分页无不令人十分头疼。 Laravel 的分页器与[查询构造器](/docs/{{version}}/queries)、[Eloquent ORM](/docs/{{version}}/eloquent) 集成在一起,并提供方便易用的数据结果集分页。分页器生成的 HTML 与 Bootstrap CSS 框架兼容。
17 |
18 |
19 | ## 基本用法
20 |
21 |
22 | ### 查询构造器分页
23 |
24 | 有几种方法可以对数据进行分页。最简单的是在 [查询语句构造器](/docs/{{version}}/queries) 或 [Eloquent 查询](/docs/{{version}}/eloquent) 中使用 `paginate` 方法。 `paginate` 方法会自动根据用户正在查看的页面来设置限制和偏移量。默认情况下,当前页面通过 HTTP 请求所带的参数 `page` 的值来检测。这个值是被 Laravel 自动检测到的,也会自动插入到由分页器生产的链接中。
25 |
26 | 在下面这个例子中,传递给 `paginate` 方法的唯一参数是「每页」显示的项目数量。下面是每页显示 `15` 条数据的例子:
27 |
28 | paginate(15);
45 |
46 | return view('user.index', ['users' => $users]);
47 | }
48 | }
49 |
50 | > {note} 目前,Laravel 无法高效执行使用 `groupBy` 语句的分页操作。如果你需要在分页结果集中使用 `groupBy`,建议你查询数据库并手动创建分页器。
51 |
52 | #### 「简单分页」
53 |
54 | 如果你只需要在分页视图中显示简单的「下一页」和「上一页」的链接,即不需要显示每个页码的链接,更推荐使用 `simplePaginate` 方法来执行更高效的查询:
55 |
56 | $users = DB::table('users')->simplePaginate(15);
57 |
58 |
59 | ### Eloquent 模型分页
60 |
61 | 你也可以对 [Eloquent](/docs/{{version}}/eloquent) 查询进行分页。下面的例子中对 `User` 模型进行了分页并且每页显示 `15` 条数据。正如你看到的,所使用的语法几乎与基于查询语句构造器分页时的完全相同:
62 |
63 | $users = App\User::paginate(15);
64 |
65 | 当然,你可以在设置了查询的其他约束条件之后调用 `paginate` 方法,例如 `where` 语句:
66 |
67 | $users = User::where('votes', '>', 100)->paginate(15);
68 |
69 | 你也可以在 `Eloquent` 模型中使用 `simplePaginate` 方法进行分页:
70 |
71 | $users = User::where('votes', '>', 100)->simplePaginate(15);
72 |
73 |
74 | ### 手动创建分页
75 |
76 | 如果你想手动创建分页实例并且最终得到一个数组类型的结果,可以根据需求来创建 `Illuminate\Pagination\Paginator` 或者 `Illuminate\Pagination\LengthAwarePaginator` 实例来实现。
77 |
78 | `Paginator` 类不需要知道结果集中的数据量,因此该类没有检索最后一页索引的方法。而 `LengthAwarePaginator` 接收的参数几乎和 `Paginator` 一样,但它却需要计算结果集中的数据量。
79 |
80 | 说白了就是,`Paginator` 相当于查询语句构造器和 Eloquent 中的 `simplePaginate` 方法,而 `LengthAwarePaginator` 相当于 `paginate` 方法。
81 |
82 | > {note} 手动创建分页器实例时,你应该手动「切割」传递给分页器的结果集数组。如果你不确定如何去做到这一点,请查阅 PHP 的 [array_slice](https://secure.php.net/manual/en/function.array-slice.php) 函数。
83 |
84 |
85 | ## 显示分页结果
86 |
87 | 在调用 `paginate` 方法时,你将会接收到一个 `Illuminate\Pagination\LengthAwarePaginator` 实例。当调用 `simplePaginate` 方法时,你将会接收到一个 `Illuminate\Pagination\Paginator` 实例。这些对象提供了一些用于渲染结果集的函数。除了这些辅助函数,分页器实例是一个迭代器,也可以作为数组循环。因此,一旦检测到结果集,你可以使用 [Blade](/docs/{{version}}/blade) 模板显示结果集并渲染页面链接:
88 |
89 |
90 | @foreach ($users as $user)
91 | {{ $user->name }}
92 | @endforeach
93 |
94 |
95 | {{ $users->links() }}
96 |
97 | `links` 方法将会链接渲染到结果集中其余的页面。每个链接都包含了正确的 `page` 查询字符串变量。记住,`links` 方法生成的 HTML 与 [Bootstrap CSS 框架](https://getbootstrap.com) 兼容。
98 |
99 | #### 自定义分页器的 URI
100 |
101 | `withPath` 方法允许你在生成链接时自定义分页器所使用的 URI。例如,如果你想要分页器生成像 `http://example.com/custom/url?page=N` 这样的链接,那就传递 `custom/url` 到 `withPath` 方法:
102 |
103 | Route::get('users', function () {
104 | $users = App\User::paginate(15);
105 |
106 | $users->withPath('custom/url');
107 |
108 | //
109 | });
110 |
111 | #### 附加参数到分页链接中
112 |
113 | 你可以使用 `appends` 方法将查询参数附加到分页链接中。例如,要将 `sort=votes` 附加到每个分页链接,可以这样调用 `appends` 方法:
114 |
115 | {{ $users->appends(['sort' => 'votes'])->links() }}
116 |
117 | 如果想将「哈希片段」附加到分页器的链接中,就使用 `fragment` 方法。例如,要将 `#foo` 附加到每个分页链接的末尾,应该这样调用 `fragment` 方法:
118 |
119 | {{ $users->fragment('foo')->links() }}
120 |
121 |
122 | ### 将结果转换为 JSON
123 |
124 | Laravel 分页器结果类实现了 `Illuminate\Contracts\Support\Jsonable` 接口契约并且提供 `toJson` 方法,因此将分页结果转换为 JSON 非常简单。你也可以在路由或控制器操作中简单地将分页实例转换为 JSON 返回:
125 |
126 | Route::get('users', function () {
127 | return App\User::paginate();
128 | });
129 |
130 | 分页器中获取的 JSON 将包含元信息,如:`total`、`current_page`、`last_page` 等等。实际的结果对象将通过 JSON 数组中的 `data` 键来获取。 以下是一个从路由返回的分页器实例创建的 JSON 示例:
131 |
132 | {
133 | "total": 50,
134 | "per_page": 15,
135 | "current_page": 1,
136 | "last_page": 4,
137 | "first_page_url": "http://laravel.app?page=1",
138 | "last_page_url": "http://laravel.app?page=4",
139 | "next_page_url": "http://laravel.app?page=2",
140 | "prev_page_url": null,
141 | "path": "http://laravel.app",
142 | "from": 1,
143 | "to": 15,
144 | "data":[
145 | {
146 | // Result Object
147 | },
148 | {
149 | // Result Object
150 | }
151 | ]
152 | }
153 |
154 |
155 | ## 自定义分页视图
156 |
157 | 默认情况下,渲染分页链接的视图与 Bootstrap CSS 框架兼容。但是,如果你不使用 Bootstrap,可以自由定义视图来渲染这些链接。在分页器实例中调用 `links` 方法时,只需将视图名称作为第一个参数传递给方法:
158 |
159 | {{ $paginator->links('view.name') }}
160 |
161 | // Passing data to the view...
162 | {{ $paginator->links('view.name', ['foo' => 'bar']) }}
163 |
164 | 自定义分页视图的制作最简单的方法是使用 `vendor:publish` 命令将它们导出到 `resources/views/vendor` 目录:
165 |
166 | php artisan vendor:publish --tag=laravel-pagination
167 |
168 | 这个命令将这些视图放置在 `resources/views/vendor/pagination` 目录中。这个目录下的 `default.blade.php` 文件对应默认的分页视图,你可以简单地编辑这个文件来修改分页的 HTML 。
169 |
170 |
171 | ## 分页器实例方法
172 |
173 | 每个分页器实例可以通过以下方法获取额外的分页信息:
174 |
175 | - `$results->count()`
176 | - `$results->currentPage()`
177 | - `$results->firstItem()`
178 | - `$results->hasMorePages()`
179 | - `$results->lastItem()`
180 | - `$results->lastPage()` (使用 simplePaginate 时不可用)
181 | - `$results->nextPageUrl()`
182 | - `$results->perPage()`
183 | - `$results->previousPageUrl()`
184 | - `$results->total()` (使用 simplePaginate 时不可用)
185 | - `$results->url($page)`
186 |
187 | ## 译者署名
188 | | 用户名 | 头像 | 职能 | 签名 |
189 | |---|---|---|---|
190 | |
[@ChrisonWang](https://github.com/ChrisonWang) |
|
翻译 |
[@王欣](https://www.linkedin.com/in/ChrisonWang/) at LinkedIn |
191 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
192 |
193 | ---
194 |
195 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
196 | >
197 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
198 | >
199 | > 文档永久地址: https://d.laravel-china.org
200 |
--------------------------------------------------------------------------------
/passwords.md:
--------------------------------------------------------------------------------
1 | # Laravel 的密码重置功能
2 |
3 | - [简介](#introduction)
4 | - [数据库注意事项](#resetting-database)
5 | - [路由](#resetting-routing)
6 | - [视图](#resetting-views)
7 | - [重置密码后](#after-resetting-passwords)
8 | - [自定义](#password-customization)
9 |
10 |
11 | ## 简介
12 |
13 | > {tip} **想要快速上手此功能?** 只需在新的 Laravel 应用中运行 `php artisan make:auth` 命令,然后在浏览器中打开 `http://your-app.dev/register`,或者给应用分配任何一个 URL。这个命令会负责构建整个身份验证系统,包括重置密码!
14 |
15 | 大部分 web 应用为用户提供了重置密码的功能。 Laravel 并不是强迫每个应用程序都要使用这个,仅仅只是想提供方法来发送密码提醒和执行密码重置。
16 |
17 | > {note} 在使用 Laravel 的密码重置功能之前,你的用户模型必须使用 `Illuminate\Notifications\Notifiable` trait。
18 |
19 |
20 | ## 数据库注意事项
21 |
22 | 开始之前,请确认你的 `App\User` 模型实现了 `Illuminate\Contracts\Auth\CanResetPassword` 契约。当然,Laravel 框架中包含的 `App\User` 模型已经实现了这个接口,并且使用 `Illuminate\Auth\Passwords\CanResetPassword` trait 来包含实现接口所需的方法。
23 |
24 | #### 生成重置令牌的表迁移
25 |
26 | 接下来,必须创建一个表来存储密码重置令牌。因为 Laravel 已经自带了用于生成这张表的迁移,就存放在 `database/migrations` 目录下。因此只需要运行数据库迁移:
27 |
28 | php artisan migrate
29 |
30 |
31 | ## 路由
32 |
33 | Laravel 在 `Auth\ForgotPasswordController` 和 `Auth\ResetPasswordController` 这两个类中分别实现了通过邮件发送重置密码链接和重置密码的逻辑。执行密码重置所需的所有路由都可以使用 Artisan 命令 `make:auth` 生成:
34 |
35 | php artisan make:auth
36 |
37 |
38 | ## 视图
39 |
40 | 当 Laravel 执行 `make:auth` 命令时,会在 `resources/views/auth/passwords` 目录下生成重置密码所需要的视图文件。你可以根据需要随意修改这些视图文件。
41 |
42 |
43 | ## 重置密码后
44 |
45 | 一旦你生成了用于重置用户密码的路由和视图,你就可以在浏览器中访问 `/password/reset` 这个路由来重置密码。框架中的 `ForgotPasswordController` 已经包含通过邮件发送重置密码链接的逻辑,而 `ResetPasswordController` 包含重置密码的逻辑。
46 |
47 | 重置密码后,用户就会自动登录并重定向到 `/home`。你可以修改 `ResetPasswordController` 中定义的 `redirectTo` 属性来自定义重置密码后重定向的位置:
48 |
49 | protected $redirectTo = '/dashboard';
50 |
51 | > {note} 默认情况下,重置密码的令牌一小时后会失效。你可以修改 `config/auth.php` 文件中的 `expire` 选项来修改这个过期时间。
52 |
53 |
54 | ## 自定义
55 |
56 | #### 自定义认证看守器
57 |
58 | 在 `auth.php` 配置文件中,你可以配置多个「看守器」,可用于定义多个用户表的身份验证行为。可以通过在 `ResetPasswordController` 控制器上重写 `guard` 方法来指定你想使用的自定义的看守器。这个方法需要返回一个看守器实例:
59 |
60 | use Illuminate\Support\Facades\Auth;
61 |
62 | protected function guard()
63 | {
64 | return Auth::guard('guard-name');
65 | }
66 |
67 | #### 自定义密码 Broker
68 |
69 | 在 `auth.php` 配置文件中,你可以配置多个密码 「brokers」,用于多个用户表上的密码重置。你可以通过重写 `ForgotPasswordController` 和 `ResetPasswordController` 中的 `broker` 方法来选择你想使用的自定义 broker:
70 |
71 | use Illuminate\Support\Facades\Password;
72 |
73 | /**
74 | * 在密码重置期间获取使用代理。
75 | *
76 | * @return PasswordBroker
77 | */
78 | protected function broker()
79 | {
80 | return Password::broker('name');
81 | }
82 |
83 | #### 自定义用于重置的邮件
84 |
85 | 你可以轻松地修改用于向用户发送密码重置链接的通知类。首先,重写 `User` 模型中的 `sendPasswordResetNotification` 方法。在这个方法中,你可以选择任何的通知类来发送通知。这个方法的第一个参数是用于重置密码的令牌 `$token` :
86 |
87 | /**
88 | * 发送密码重置通知。
89 | *
90 | * @param string $token
91 | * @return void
92 | */
93 | public function sendPasswordResetNotification($token)
94 | {
95 | $this->notify(new ResetPasswordNotification($token));
96 | }
97 |
98 | ## 译者署名
99 | | 用户名 | 头像 | 职能 | 签名 |
100 | |---|---|---|---|
101 | | [@lockdown56](https://laravel-china.org/users/7083) |
| 翻译 | 农闲出来敲代码,农忙回家种玉米 |
102 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
103 |
104 | ---
105 |
106 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
107 | >
108 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
109 | >
110 | > 文档永久地址: https://d.laravel-china.org
111 |
--------------------------------------------------------------------------------
/providers.md:
--------------------------------------------------------------------------------
1 | # Laravel 的服务提供器
2 |
3 | - [简介](#introduction)
4 | - [编写服务提供器](#writing-service-providers)
5 | - [注册方法](#the-register-method)
6 | - [引导方法](#the-boot-method)
7 | - [注册提供器](#registering-providers)
8 | - [延迟提供器](#deferred-providers)
9 |
10 |
11 | ## 简介
12 |
13 | 服务提供器是所有 Laravel 应用程序引导中心。你的应用程序以及 Laravel 的所有核心服务都是通过服务提供器进行引导。
14 |
15 | 在这里,我们说的「引导」其实是指**注册**,比如注册服务容器绑定、事件监听器、中间件,甚至是路由的注册。服务提供器是配置你的应用程序的中心。
16 |
17 | Laravel 的 `config/app.php` 文件中有一个 `providers` 数组。数组中的内容是应用程序要加载的所有服务提供器类。这其中有许多提供器并不会在每次请求时都被加载,只有当它们提供的服务实际需要时才会加载。这种我们称之为「延迟」提供器。
18 |
19 | 本篇将带你学习如何编写自己的服务提供器,并将其注册到 Laravel 应用程序中。
20 |
21 |
22 | ## 编写服务提供器
23 |
24 | 所有服务提供器都会继承 `Illuminate\Support\ServiceProvider` 类。大多数服务提供器都包含 `register` 和 `boot` 方法。在 `register` 方法中,你**只需要绑定类到 [服务容器](/docs/{{version}}/container)**中。而不需要尝试在 `register` 方法中注册任何事件监听器、路由或任何其他功能。
25 |
26 | 使用 Artisan 命令行界面,通过 `make:provider` 命令生成一个新的提供器:
27 |
28 | php artisan make:provider RiakServiceProvider
29 |
30 |
31 | ### 注册方法
32 |
33 | 在 `register` 方法中,你只需要将类绑定到 [服务容器](/docs/{{version}}/container) 中。而不需要尝试在 `register` 方法中注册任何事件监听器、路由或者任何其他功能。否则,你可能会意外使用到尚未加载的服务提供器提供的服务。
34 |
35 | 让我们来看一个基本的服务提供器。在你的任何服务提供器方法中,你可以通过 `$app` 属性来访问服务容器:
36 |
37 | app->singleton(Connection::class, function ($app) {
54 | return new Connection(config('riak'));
55 | });
56 | }
57 | }
58 |
59 | 这个服务提供器只定义了一个 `register` 方法,并使用该方法在服务容器中定义了一个 `Riak\Connection` 实现。 如果你不了解服务容器的工作原理,请查看其 [文档](/docs/{{version}}/container).
60 |
61 |
62 | ### 引导方法
63 |
64 | 那么,如果我们需要在我们的服务提供器中注册一个视图组件呢?这应该在 `boot` 方法中完成。**此方法在所有其他服务提供器都注册之后才能调用**,这意味着你可以访问已经被框架注册的所有服务:
65 |
66 | composer('view', function () {
82 | //
83 | });
84 | }
85 | }
86 |
87 | #### 引导方法依赖注入
88 |
89 | 你可以为服务提供器的 `boot` 方法设置类型提示。[服务容器](/docs/{{version}}/container) 会自动注入你需要的任何依赖项:
90 |
91 | use Illuminate\Contracts\Routing\ResponseFactory;
92 |
93 | public function boot(ResponseFactory $response)
94 | {
95 | $response->macro('caps', function ($value) {
96 | //
97 | });
98 | }
99 |
100 |
101 | ## 注册提供器
102 |
103 | 所有服务提供器都在 `config/app.php` 配置文件中注册。该文件中有一个 `providers` 数组,用于存放服务提供器的类名 。默认情况下,这个数组列出了一系列 Laravel 核心服务提供器。这些服务提供器引导 Laravel 核心组件,例如邮件、队列、缓存等。
104 |
105 | 要注册提供器,只需要将其添加到数组:
106 |
107 | 'providers' => [
108 | // 其他服务提供器
109 |
110 | App\Providers\ComposerServiceProvider::class,
111 | ],
112 |
113 |
114 | ## 延迟提供器
115 |
116 | 如果你的提供器**仅**在 [服务容器](/docs/{{version}}/container) 中注册绑定,就可以选择推迟其注册,直到当它真正需要注册绑定。推迟加载这种提供器会提高应用程序的性能,因为它不会在每次请求时都从文件系统中加载。
117 |
118 | Laravel 编译并保存延迟服务提供器提供的所有服务的列表,以及其服务提供器类的名称。因此,只有当你在尝试解析其中一项服务时,Laravel 才会加载服务提供器。
119 |
120 | 要延迟提供器的加载,请将 `defer` 属性设置为 `true` ,并定义 `provides` 方法。`provides` 方法应该返回由提供器注册的服务容器绑定:
121 |
122 | app->singleton(Connection::class, function ($app) {
146 | return new Connection($app['config']['riak']);
147 | });
148 | }
149 |
150 | /**
151 | * 获取提供器提供的服务。
152 | *
153 | * @return array
154 | */
155 | public function provides()
156 | {
157 | return [Connection::class];
158 | }
159 |
160 | }
161 |
162 | ## 译者署名
163 |
164 | | 用户名 | 头像 | 职能 | 签名 |
165 | |---|---|---|---|
166 | | [@devindwan](https://github.com/devindwan) |
| 翻译 | There are only two kinds of languages: the ones people complain about and the ones nobody uses. |
167 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
168 |
169 |
170 | ---
171 |
172 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
173 | >
174 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
175 | >
176 | > 文档永久地址: https://d.laravel-china.org
177 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 | > 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
3 | >
4 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
5 | >
6 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/redirects.md:
--------------------------------------------------------------------------------
1 | # Laravel 的 HTTP 重定向 Redirect
2 |
3 | - [创建重定向](#creating-redirects)
4 | - [重定向到命名路由](#redirecting-named-routes)
5 | - [重定向到控制器动作](#redirecting-controller-actions)
6 | - [闪存 Session 数据重定向](#redirecting-with-flashed-session-data)
7 |
8 |
9 | ## 创建重定向
10 |
11 | 重定向响应是类 `Illuminate\Http\RedirectResponse` 的实例, 包含了重定向用户到其他 URL 所需要的合适头信息。有很多方式生成 `RedirectResponse` 实例。最简单的方法是使用全局的 `redirect` 辅助函数:
12 |
13 | Route::get('dashboard', function () {
14 | return redirect('home/dashboard');
15 | });
16 |
17 | 有时候你希望将用户重定向到他们的上一个访问位置,例如当提交的表单不合法时,你就可以通过全局的 `back` 辅助函数来这样做。 因为该特性使用了 [session](/docs/{{version}}/session),请确保路由调用 `back` 函数时使用了 `web` 中间件组或者应用了全部的 session 中间件:
18 |
19 | Route::post('user/profile', function () {
20 | // Validate the request...
21 |
22 | return back()->withInput();
23 | });
24 |
25 |
26 | ## 重定向到命名路由
27 |
28 | 当你不带参数调用 `redirect` 辅助函数时,会返回一个 `Illuminate\Routing\Redirector` 实例,它允许你调用 `Redirector` 实例上的任何方法。例如,你可以这样使用 `route` 方法为命名路由生成一个 `RedirectResponse` :
29 |
30 | return redirect()->route('login');
31 |
32 | 如果你的路由包含参数,你可以把它们当做第二参数传给 `route` 方法:
33 |
34 | // For a route with the following URI: profile/{id}
35 |
36 | return redirect()->route('profile', ['id' => 1]);
37 |
38 | #### 通过 Eloquent 模型填充参数
39 |
40 | 如果你要携带一个从 Eloquent 模型中填充过来的 "ID" 参数进行重定向,你可以简单的把该模型本身传进去。 ID 会被自动解析:
41 |
42 | // For a route with the following URI: profile/{id}
43 |
44 | return redirect()->route('profile', [$user]);
45 |
46 | 如果你想自定义路由参数的值,你应该在 Eloquent 模型中重写 `getRouteKey` 方法:
47 |
48 | /**
49 | * Get the value of the model's route key.
50 | *
51 | * @return mixed
52 | */
53 | public function getRouteKey()
54 | {
55 | return $this->slug;
56 | }
57 |
58 |
59 | ## 重定向到控制器动作
60 |
61 | 你也可以生成重定向到 [控制器动作](/docs/{{version}}/controllers)。要达到这个目的,传递控制器名和动作名到 `action` 方法即可。记住,你不需要指定完整的控制器命名空间,因为 Laravel 的 `RouteServiceProvider` 会自动设置基础的控制器命名空间:
62 |
63 | return redirect()->action('HomeController@index');
64 |
65 | 如果你的控制器路由需要参数,你可以把它们当做第二个参数传递给 `action` 方法:
66 |
67 | return redirect()->action(
68 | 'UserController@profile', ['id' => 1]
69 | );
70 |
71 |
72 | ## 闪存 Session 数据重定向
73 |
74 | 重定向到新的 URL 并且 [闪存数据到 session](/docs/{{version}}/session#flash-data) 常常在同时完成。 通常的,这会在你成功的执行一个动作、闪存消息到 session 后完成。方便起见,你可以创建一个 `RedirectResponse` 实例并在单个的、流畅的方法链上闪存数据到 session :
75 |
76 | Route::post('user/profile', function () {
77 | // Update the user's profile...
78 |
79 | return redirect('dashboard')->with('status', 'Profile updated!');
80 | });
81 |
82 | 用户被重定向后,你可以从 [session](/docs/{{version}}/session) 中显示闪存消息。例如,使用 [Blade 语法](/docs/{{version}}/blade):
83 |
84 | @if (session('status'))
85 |
86 | {{ session('status') }}
87 |
88 | @endif
89 |
90 | ## 译者署名
91 |
92 | | 用户名 | 头像 | 职能 | 签名 |
93 | |---|---|---|---|
94 | | [@limxx](https://github.com/limxx) |
| 翻译 | Winter is coming. |
95 |
96 |
97 | ---
98 |
99 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
100 | >
101 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
102 | >
103 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/redis.md:
--------------------------------------------------------------------------------
1 | # Laravel 的 Redis 使用指南
2 |
3 | - [简介](#introduction)
4 | - [配置](#configuration)
5 | - [Predis](#predis)
6 | - [PhpRedis](#phpredis)
7 | - [与 Redis 交互](#interacting-with-redis)
8 | - [管道命令](#pipelining-commands)
9 | - [发布与订阅](#pubsub)
10 |
11 |
12 | ## 简介
13 |
14 | [Redis](http://redis.io) 是一个开源的高级键值对存储库。它的键值可以包含 [字符串](http://redis.io/topics/data-types#strings)、[哈希](http://redis.io/topics/data-types#hashes)、[列表](http://redis.io/topics/data-types#lists)、[集合](http://redis.io/topics/data-types#sets) 和 [有序集合](http://redis.io/topics/data-types#sorted-sets) 这些数据类型,因此它通常被称为数据结构服务器。
15 |
16 | 在使用 Laravel 的 Redis 之前,你需要通过 Composer 安装 `predis/predis` 扩展包:
17 |
18 | composer require predis/predis
19 |
20 | 或者,你可以通过 PECL 安装 [PhpRedis](https://github.com/phpredis/phpredis) PHP 扩展。这个扩展安装起来比较复杂,但对于大量使用 Redis 的应用程序来说可能会产生更好的性能。
21 |
22 |
23 |
24 | ### 配置
25 |
26 |
27 | 应用程序的 Redis 配置都在配置文件 `config/database.php` 中。在这个文件里,你可以看到 `redis` 数组里面包含了应用程序使用的 Redis 服务器:
28 |
29 | 'redis' => [
30 |
31 | 'client' => 'predis',
32 |
33 | 'default' => [
34 | 'host' => env('REDIS_HOST', 'localhost'),
35 | 'password' => env('REDIS_PASSWORD', null),
36 | 'port' => env('REDIS_PORT', 6379),
37 | 'database' => 0,
38 | ],
39 |
40 | ],
41 |
42 | 默认的服务器配置应该足以进行开发。当然,你也可以根据使用的环境来随意更改这个数组。只需在配置文件中给每个 Redis 服务器指定名称、host 和 port 即可。
43 |
44 | #### 集群配置
45 |
46 | 如果你的程序使用 redis 服务器集群,你应该在 redis 配置文件中使用 `clusters` 键来定义这些集群:
47 |
48 | 'redis' => [
49 |
50 | 'client' => 'predis',
51 |
52 | 'clusters' => [
53 | 'default' => [
54 | [
55 | 'host' => env('REDIS_HOST', 'localhost'),
56 | 'password' => env('REDIS_PASSWORD', null),
57 | 'port' => env('REDIS_PORT', 6379),
58 | 'database' => 0,
59 | ],
60 | ],
61 | ],
62 |
63 | ],
64 |
65 | 默认情况下,集群可以实现跨节点间客户端共享,允许你实现节点池以及创建大量可用内存。这里要注意,客户端共享不会处理失败的情况;因此,这个功能主要适用于从另一个主数据库获取的缓存数据。如果要使用 redis 原生集群,要在配置文件的 `options` 键中如下指定:
66 |
67 | 'redis' => [
68 |
69 | 'client' => 'predis',
70 |
71 | 'options' => [
72 | 'cluster' => 'redis',
73 | ],
74 |
75 | 'clusters' => [
76 | // ...
77 | ],
78 |
79 | ],
80 |
81 |
82 | ### Predis
83 |
84 | 除了默认的 `Host`、`port`、`database` 和 `password` 这些服务配置选项之外,Predis 还支持为每个 redis 服务器定义其他的 [连接参数](https://github.com/nrk/predis/wiki/Connection-Parameters)。如果要使用这些额外的配置选项,就将它们添加到配置文件 `config/database.php` 的 Redis 服务器配置中:
85 |
86 | 'default' => [
87 | 'host' => env('REDIS_HOST', 'localhost'),
88 | 'password' => env('REDIS_PASSWORD', null),
89 | 'port' => env('REDIS_PORT', 6379),
90 | 'database' => 0,
91 | 'read_write_timeout' => 60,
92 | ],
93 |
94 |
95 | ### PhpRedis
96 |
97 | > {note} 如果你是通过 PECL 安装 Redis PHP 扩展,就需要重命名 `config/app.php` 文件里 Redis 的别名。
98 |
99 | 如果要使用 Phpredis 扩展,就需要将配置文件 `config/database.php` 中 Redis 配置的 `client` 选项更改为 `phpredis`:
100 |
101 | 'redis' => [
102 |
103 | 'client' => 'phpredis',
104 |
105 | // Rest of Redis configuration...
106 | ],
107 |
108 | 除了默认的 `Host`、`port`、`database` 和 `password` 这些服务配置项之外,Phpredis 还支持以下几个额外的连接参数:`persistent`、`prefix`、`read_timeout` 和 `timeout`。你可以将这些选项加到配置文件 `config/database.php` 中 redis 服务器配置项下:
109 |
110 | 'default' => [
111 | 'host' => env('REDIS_HOST', 'localhost'),
112 | 'password' => env('REDIS_PASSWORD', null),
113 | 'port' => env('REDIS_PORT', 6379),
114 | 'database' => 0,
115 | 'read_timeout' => 60,
116 | ],
117 |
118 |
119 | ## 与 Redis 交互
120 |
121 | 你可以调用 `Redis` [facade](/docs/{{version}}/facades) 上的各种方法来与 `Redis` 进行交互。`Redis` facade 支持动态方法,这意味着你可以在 facade 上调用任何 [Redis 命令](http://redis.io/commands),还能将该命令直接传递给 Redis。在本例中,通过调用 `Redis` facade 上的 `get` 方法来调用 Redis 的 `GET` 命令:
122 |
123 | $user]);
143 | }
144 | }
145 |
146 | 也就是说,你可以在 `Redis` facade 上调用任何的 Redis 命令。Laravel 使用魔术方法将传递命令给 Redis 服务器,因此只需传递 Redis 命令所需的参数即可:
147 |
148 | Redis::set('name', 'Taylor');
149 |
150 | $values = Redis::lrange('names', 5, 10);
151 | 或者,你也可以使用 `command` 方法将命令传递给服务器,它接受命令的名称作为其第一个参数,并将值的数组作为其第二个参数:
152 |
153 | $values = Redis::command('lrange', ['name', 5, 10]);
154 |
155 | #### 使用多个 Redis 连接
156 |
157 | 你可以通过 `Redis::connection` 方法来获取 Redis 实例:
158 |
159 | $redis = Redis::connection();
160 | 这会返回一个默认的 redis 服务器的实例。你也可以将连接或者集群的名称传递给 `connection` 方法,来获取在 Redis 配置文件中定义的特定的服务器或者集群:
161 |
162 | $redis = Redis::connection('my-connection');
163 |
164 |
165 | ### 管道命令
166 |
167 | 如果你需要在一个操作中向服务器发送很多命令,推荐你使用管道命令。`pipeline` 方法接收一个带有 Redis 实例的 `闭包` 。你可以将所有的命令发送给这个 Redis 实例,它们都会一次过执行完:
168 |
169 | Redis::pipeline(function ($pipe) {
170 | for ($i = 0; $i < 1000; $i++) {
171 | $pipe->set("key:$i", $i);
172 | }
173 | });
174 |
175 |
176 | ## 发布与订阅
177 |
178 | Laravel 为 Redis 的 `publish` 及 `subscribe` 提供了方便的接口。这些 Redis 命令让你可以监听指定「频道」上的消息。你可以从另一个应用程序发布消息给另一个应用程序,甚至使用其它编程语言,让应用程序和进程之间能够轻松进行通信。
179 |
180 | 首先,我们使用 `subscribe` 方法设置频道监听器。我们将这个方法调用放在 [Artisan 命令](/docs/{{version}}/artisan) 中,因为调用 `subscribe` 方法会启动一个长时间运行的进程:
181 |
182 | 'bar']));
224 | });
225 |
226 | #### 通配符订阅
227 |
228 | 使用 `psubscribe` 方法可以订阅通配符频道,可以用来在所有频道上获取所有消息。`$channel` 名称将作为第二个参数传递给提供的回调 `闭包` :
229 |
230 | Redis::psubscribe(['*'], function ($message, $channel) {
231 | echo $message;
232 | });
233 |
234 | Redis::psubscribe(['users.*'], function ($message, $channel) {
235 | echo $message;
236 | });
237 |
238 | ## 译者署名
239 | | 用户名 | 头像 | 职能 | 签名 |
240 | |---|---|---|---|
241 | | [@daydaygo](https://github.com/daydaygo) |
| 翻译 | [Coder at Work](http://blog.daydaygo.top) |
242 | | [@大袋鼠](https://github.com/FaithPatrick) |
| 校对 | [暮光博客](https://muguang.me/) |
243 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
244 |
245 | ---
246 |
247 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
248 | >
249 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
250 | >
251 | > 文档永久地址: https://d.laravel-china.org
252 |
253 |
--------------------------------------------------------------------------------
/responses.md:
--------------------------------------------------------------------------------
1 | # Laravel 的请求响应
2 |
3 | - [创建响应](#creating-responses)
4 | - [为响应增加头信息](#attaching-headers-to-responses)
5 | - [为响应增加 Cookies](#attaching-cookies-to-responses)
6 | - [Cookies & 加密](#cookies-and-encryption)
7 | - [重定向](#redirects)
8 | - [重定向至命名路由](#redirecting-named-routes)
9 | - [重定向至控制器行为](#redirecting-controller-actions)
10 | - [重定向并使用闪存的 Session 数据](#redirecting-with-flashed-session-data)
11 | - [其他响应类型](#other-response-types)
12 | - [视图响应](#view-responses)
13 | - [JSON 响应](#json-responses)
14 | - [文件下载](#file-downloads)
15 | - [文件响应](#file-responses)
16 | - [响应宏](#response-macros)
17 |
18 |
19 | ## 创建响应
20 |
21 | #### 字符串 & 数组
22 |
23 | 所有路由和控制器都会返回一个响应并发送给用户的浏览器。Laravel 提供了几种不同的方式来返回响应。最基本的响应就是从路由或控制器返回一个字符串。框架会自动将字符串转换为一个完整的 HTTP 响应:
24 |
25 | Route::get('/', function () {
26 | return 'Hello World';
27 | });
28 |
29 | 除了从路由和控制器返回字符串之外,还可以返回数组。框架也会自动地将数组转为 JSON 响应:
30 |
31 | Route::get('/', function () {
32 | return [1, 2, 3];
33 | });
34 |
35 | > {tip} 你还可以从路由或控制器中直接返回 [Eloquent 集合](/docs/{{version}}/eloquent-collections),它们会自动转为 JSON 响应。
36 |
37 | #### 响应对象
38 |
39 | 一般来说,你不会只从路由行为返回简单的字符串或数组。你也许会返回完整的 `Illuminate\Http\Response` 实例或 [视图](/docs/{{version}}/views)。
40 |
41 | 返回完整的 `Response` 实例允许你自定义响应的 HTTP 状态码和响应头信息。`Response` 实例继承自 `Symfony\Component\HttpFoundation\Response` 类,该类提供了各种构建 HTTP 响应的方法:
42 |
43 | Route::get('home', function () {
44 | return response('Hello World', 200)
45 | ->header('Content-Type', 'text/plain');
46 | });
47 |
48 |
49 | #### 为响应增加头信息
50 |
51 | 大部分的响应方法都是可链式调用的,使得创建响应实例的过程更具可读性。例如,你可以在响应返回给用户前使用 `header` 方法为其添加一系列的头信息:
52 |
53 | return response($content)
54 | ->header('Content-Type', $type)
55 | ->header('X-Header-One', 'Header Value')
56 | ->header('X-Header-Two', 'Header Value');
57 |
58 | 或者,你可以使用 `withHeaders` 方法来指定要添加到响应的头信息数组:
59 |
60 | return response($content)
61 | ->withHeaders([
62 | 'Content-Type' => $type,
63 | 'X-Header-One' => 'Header Value',
64 | 'X-Header-Two' => 'Header Value',
65 | ]);
66 |
67 |
68 | #### 为响应增加 Cookie
69 |
70 | 你可以使用响应上的 `cookie` 方法轻松地将为响应增加 Cookies。例如,你可以像这样使用 `cookie` 方法生成一个 cookie 并轻松地将其附加到响应上:
71 |
72 | return response($content)
73 | ->header('Content-Type', $type)
74 | ->cookie('name', 'value', $minutes);
75 |
76 | `cookie` 方法还接受一些不太频繁使用的参数。通常,这些参数与原生 PHP 的 [setcookie](https://secure.php.net/manual/en/function.setcookie.php) 方法的参数有着相同的目的和含义:
77 |
78 | ->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)
79 |
80 |
81 | #### Cookies 和 加密
82 |
83 | 默认情况下,Laravel 生成的所有 Cookie 都是经过加密和签名,因此不能被客户端修改或读取。 如果你想要应用程序生成的部分 Cookie 不被加密,那么可以使用在 `app/Http/Middleware` 目录中 `App\Http\Middleware\EncryptCookies` 中间件的 `$except` 属性:
84 |
85 | /**
86 | * 不需要加密的 Cookie 名称。
87 | *
88 | * @var array
89 | */
90 | protected $except = [
91 | 'cookie_name',
92 | ];
93 |
94 |
95 | ## 重定向
96 |
97 | 重定向响应是 `Illuminate\Http\RedirectResponse` 类的实例,并且包含用户需要重定向至另一个 URL 所需的头信息。Laravel 提供了几种方法用于生成 `RedirectResponse` 实例。其中最简单的方法是使用全局辅助函数 `redirect`:
98 |
99 | Route::get('dashboard', function () {
100 | return redirect('home/dashboard');
101 | });
102 |
103 | 有时候你可能希望将用户重定向到之前的位置,比如提交的表单无效时。这时你可以使用全局辅助函数 `back` 来执行此操作。由于这个功能利用了 [Session](/docs/{{version}}/session),请确保调用 `back` 函数的路由使用 `web` 中间件组或所有 Session 中间件:
104 |
105 | Route::post('user/profile', function () {
106 | // 验证请求...
107 |
108 | return back()->withInput();
109 | });
110 |
111 |
112 | ### 重定向至命名路由
113 |
114 | 当你不带参数调用辅助函数 `redirect` 时,会返回 `Illuminate\Routing\Redirector` 实例。这个实例允许你调用 `Redirector` 上的任何方法。例如为命名路由生成 `RedirectResponse`,可以使用 `route` 方法:
115 |
116 | return redirect()->route('login');
117 |
118 | 如果你的路由有参数,你可以把它们作为 `route` 方法的第二个参数来传递:
119 |
120 | // 对于具有以下 URI 的路由: profile/{id}
121 |
122 | return redirect()->route('profile', ['id' => 1]);
123 |
124 | #### 通过 Eloquent 模型填充参数
125 |
126 | 如果你要重定向到使用从 Eloquent 模型填充「ID」参数的路由,可以简单地传递模型本身。ID 会被自动提取:
127 |
128 | // 对于此路由: profile/{id}
129 |
130 | return redirect()->route('profile', [$user]);
131 |
132 | 如果要自定义路由参数中的值,那么应该覆盖 Eloquent 模型里面的 `getRouteKey` 方法:
133 |
134 | /**
135 | * 获取模型的路由键.
136 | *
137 | * @return mixed
138 | */
139 | public function getRouteKey()
140 | {
141 | return $this->slug;
142 | }
143 |
144 |
145 | ### 重定向至控制器行为
146 |
147 | 你可能需要生成重定向到 [控制器行为](/docs/{{version}}/controllers) 的响应。为此,你要将控制器和行为名称传递给 `action` 方法来实现。另外,你不一定要为控制器指定完整的命名空间,因为 Laravel 的 `RouteServiceProvider` 会自动设置基本的控制器命名空间:
148 |
149 | return redirect()->action('HomeController@index');
150 |
151 | 如果你的控制器路由需要参数,你可以将它们作为第二个参数传递给 `action` 方法:
152 |
153 | return redirect()->action(
154 | 'UserController@profile', ['id' => 1]
155 | );
156 |
157 |
158 | ### 重定向并使用闪存的 Session 数据
159 |
160 | 通常,重定向到新的 URL 的同时会将 [数据闪存到 Session](/docs/{{version}}/session#flash-data)。并且成功执行将信息闪存到 Seesion 后才算完成此操作。方便起见,你可以创建一个 `RedirectResponse` 的实例并链式调用 `with` 方法将数据闪存在 Session 中:
161 |
162 | Route::post('user/profile', function () {
163 | // 更新用户的信息...
164 |
165 | return redirect('dashboard')->with('status', 'Profile updated!');
166 | });
167 |
168 | 用户重定向后,你可以从 [session](/docs/{{version}}/session) 中读取闪存的信息。例如,使用 [Blade 语法](/docs/{{version}}/blade):
169 |
170 | @if (session('status'))
171 |
172 | {{ session('status') }}
173 |
174 | @endif
175 |
176 |
177 | ## 其他响应类型
178 |
179 | 使用辅助函数 `response` 可以用来生成其他类型的响应实例。当不带参数调用辅助函数 `response` 时,会返回 `Illuminate\Contracts\Routing\ResponseFactory` [契约](/docs/{{version}}/contracts) 的实例。 契约提供了几种辅助生成响应的方法。
180 |
181 |
182 | ### 视图响应
183 |
184 | 如果你需要控制响应的状态和标题,还需要返回 [视图](/docs/{{version}}/views) 作为响应的内容,则应使用 `view` 方法:
185 |
186 | return response()
187 | ->view('hello', $data, 200)
188 | ->header('Content-Type', $type);
189 |
190 | 当然,如果你不需要传递自定义 HTTP 状态码或者自定义头信息,则应该使用全局辅助函数 `view`。
191 |
192 |
193 | ### JSON 响应
194 |
195 | `json` 方法会自动把 `Content-Type` 响应头信息设置为 `application/json`,并使用 PHP函数 `json_encode` 将给定的数组转换为 JSON:
196 |
197 | return response()->json([
198 | 'name' => 'Abigail',
199 | 'state' => 'CA'
200 | ]);
201 |
202 | 如果要创建一个 JSONP 响应,你可以使用 `json` 方法并与 `withCallback` 方法配合使用:
203 |
204 | return response()
205 | ->json(['name' => 'Abigail', 'state' => 'CA'])
206 | ->withCallback($request->input('callback'));
207 |
208 |
209 | ### 文件下载
210 |
211 | `download` 方法可以用来生成强制用户浏览器下载指定路径文件的响应。`download` 方法的第二个参数接受一个文件名,它将作为用户下载的时所看见的文件名。最后,你可以传递一个 HTTP 响应头数组最为该方法的第三个参数:
212 |
213 | return response()->download($pathToFile);
214 |
215 | return response()->download($pathToFile, $name, $headers);
216 |
217 | return response()->download($pathToFile)->deleteFileAfterSend(true);
218 |
219 |
220 | > {note} 管理文件下载的扩展包 Symfony HttpFoundation,要求下载文件名必须是 ASCII 编码的。
221 |
222 |
223 | ### 文件响应
224 |
225 | `file` 方法可以直接在用户浏览器中显示文件(不是发起下载),例如图像或者 PDF。此方法接受文件的路径作为其第一个参数和头信息数组作为其第二个参数:
226 |
227 | return response()->file($pathToFile);
228 |
229 | return response()->file($pathToFile, $headers);
230 |
231 |
232 | ## 响应宏
233 |
234 | 如果要定义可以在各种路由和控制器中重复使用的自定义响应,可以在 `Response` Facade 上使用 `macro` 方法。例如,你可以在 [服务提供器](/docs/{{version}}/providers) 的 `boot` 方法中这样写:
235 |
236 | caps('foo');
261 |
262 | ## 译者署名
263 |
264 | | 用户名 | 头像 | 职能 | 签名 |
265 | |---|---|---|---|
266 | | [Seven Du](https://github.com/medz) |
| 翻译 | 基于 Laravel 的社交开源系统 [ThinkSNS+](https://github.com/slimkit/thinksns-plus) 欢迎 Star。 |
267 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
268 |
269 | ---
270 |
271 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
272 | >
273 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
274 | >
275 | > 文档永久地址: https://d.laravel-china.org
276 |
--------------------------------------------------------------------------------
/scheduling.md:
--------------------------------------------------------------------------------
1 | # Laravel 的任务调度(计划任务)功能 Task Scheduling
2 |
3 | - [简介](#introduction)
4 |
5 | - [定义调度](#defining-schedules)
6 |
7 | - [Artisan 命令调度](#scheduling-artisan-commands)
8 | - [队列任务调度](#scheduling-queued-jobs)
9 | - [Shell 调度命令](#scheduling-shell-commands)
10 | - [调度频率设置](#schedule-frequency-options)
11 | - [避免任务重复](#preventing-task-overlaps)
12 | - [维护模式](#maintenance-mode)
13 |
14 | - [任务输出](#task-output)
15 | - [任务钩子](#task-hooks)
16 |
17 |
18 | ## 简介
19 |
20 | 在过去,开发者必须在服务器上为每个任务生成单独的 Cron 项目。而令人头疼的是任务调度不受源代码控制,而且必须通过 SSH 连接到服务器上来增加 Cron 项目。
21 |
22 | Laravel 的命令调度程序允许你在 Laravel 中对命令调度进行清晰流畅的定义。并且在使用调度程序时,只需要在服务器上增加一条 Cron 项目即可。调度是在 `app/Console/Kernel.php` 文件的 `schedule` 方法中定义的。为了方便你开始,该方法已经包含了一个简单的例子。
23 |
24 | ### 启动调度器
25 |
26 | 使用调度器时,只需将以下 Cron 项目添加到服务器。如果你不知道如何将 Cron 项目添加到服务器,可以考虑使用 [Laravel Forge](https://forge.laravel.com) 等服务来管理你的 Cron 项目:
27 |
28 | ````
29 | * * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
30 | ````
31 |
32 | 上面这个 Cron 会每分钟调用一次 Laravel 命令调度器。执行 `schedule:run` 命令时, Laravel 会根据你的调度运行预定任务。
33 |
34 |
35 | ## 定义调度
36 |
37 | 你可以在 `App\Console\Kernel` 类的 `schedule` 方法中定义所有调度任务。在开始之前,先看看一个调度任务的例子。在该例子中,我们将计划在每天午夜调用一个 `Closure`。在这个 `Closure` 中,将执行一个数据库查询来清除一个表:
38 |
39 | ````
40 | call(function () {
68 | DB::table('recent_users')->delete();
69 | })->daily();
70 | }
71 | }
72 | ````
73 |
74 |
75 |
76 | ### Artisan 命令调度
77 |
78 | 除了计划 `Closure` 调用,你还能调度 [Artisan 命令](/docs/{{version}}/artisan) 和操作系统命令。举个例子,你可以给 `command` 方法传递命令名称或者类名称来调度一个 `Artisan` 命令:
79 |
80 | ````
81 | $schedule->command('emails:send --force')->daily();
82 |
83 | $schedule->command(EmailsCommand::class, ['--force'])->daily();
84 | ````
85 |
86 |
87 | ### 队列任务调度
88 |
89 | `job` 方法可以用来调度 [队列任务](/docs/{{version}}/queues)。这个方法提供了一种快捷方式来调度任务,无需使用 `call` 方法手动创建闭包来调度任务:
90 |
91 | ````
92 | $schedule->job(new Heartbeat)->everyFiveMinutes();
93 | ````
94 |
95 |
96 | ### Shell 命令调度
97 |
98 | `exec` 方法可用于向操作系统发出命令:
99 |
100 | ````
101 | $schedule->exec('node /home/forge/script.js')->daily();
102 | ````
103 |
104 |
105 | ### 调度频率设置
106 |
107 | 当然,你可以为你的任务分配多种调度计划:
108 |
109 | | 方法 | 描述 |
110 | | --------------------------------- | ------------------------- |
111 | | `->cron('* * * * * *');` | 在自定义的 Cron 时间表上执行该任务 |
112 | | `->everyMinute();` | 每分钟执行一次任务 |
113 | | `->everyFiveMinutes();` | 每五分钟执行一次任务 |
114 | | `->everyTenMinutes();` | 每十分钟执行一次任务 |
115 | | `->everyFifteenMinutes();` | 每十五分钟执行一次任务 |
116 | | `->everyThirtyMinutes();` | 每半小时执行一次任务 |
117 | | `->hourly();` | 每小时执行一次任务 |
118 | | `->hourlyAt(17);` | 每小时的第 17 分钟执行一次任务 |
119 | | `->daily();` | 每天午夜执行一次任务 |
120 | | `->dailyAt('13:00');` | 每天的 13:00 执行一次任务 |
121 | | `->twiceDaily(1, 13);` | 每天的 1:00 和 13:00 分别执行一次任务 |
122 | | `->weekly();` | 每周执行一次任务 |
123 | | `->monthly();` | 每月执行一次任务 |
124 | | `->monthlyOn(4, '15:00');` | 在每个月的第四天的 15:00 执行一次任务 |
125 | | `->quarterly();` | 每季度执行一次任务 |
126 | | `->yearly();` | 每年执行一次任务 |
127 | | `->timezone('America/New_York');` | 设置时区 |
128 |
129 | 这些方法可以合并其它限制条件以生成更精确的调度。例如,计划每周周一的调度:
130 |
131 | ````
132 | // 每周一的下午一点钟运行
133 | $schedule->call(function () {
134 | //
135 | })->weekly()->mondays()->at('13:00');
136 |
137 | // 周一至周五上午 8 点至下午 5 点每小时运行一次...
138 | $schedule->command('foo')
139 | ->weekdays()
140 | ->hourly()
141 | ->timezone('America/Chicago')
142 | ->between('8:00', '17:00');
143 | ````
144 |
145 | 以下是额外限制条件的列表:
146 |
147 | | 方法 | 描述 |
148 | | -------------------------- | ----------------- |
149 | | `->weekdays();` | 将任务限制在工作日 |
150 | | `->sundays();` | 将任务限制在星期天 |
151 | | `->mondays();` | 将任务限制在星期一 |
152 | | `->tuesdays();` | 将任务限制在星期二 |
153 | | `->wednesdays();` | 将任务限制在星期三 |
154 | | `->thursdays();` | 将任务限制在星期四 |
155 | | `->fridays();` | 将任务限制在星期五 |
156 | | `->saturdays();` | 将任务限制在星期六 |
157 | | `->between($start, $end);` | 限制任务运行在开始到结束时间范围内 |
158 | | `->when(Closure);` | 根据闭包函数的返回来限制任务 |
159 |
160 | #### 时间范围限制
161 |
162 | `between` 方法可以用来限制一天中某个时间范围内的任务执行:
163 |
164 | ````
165 | $schedule->command('reminders:send')
166 | ->hourly()
167 | ->between('7:00', '22:00');
168 | ````
169 |
170 | 类似的,`unlessBetween` 方法可以用来在一段时间内排除任务的执行:
171 |
172 | ````
173 | $schedule->command('reminders:send')
174 | ->hourly()
175 | ->unlessBetween('23:00', '4:00');
176 | ````
177 |
178 | #### 闭包测试限制
179 |
180 | `when` 方法可以用来根据给定的测试的结果来限制任务的执行。换句话说,如果给定的 `Closure` 返回 `true`,那么只要没有其他约束条件阻止任务运行,任务就会执行:
181 |
182 | ````
183 | $schedule->command('emails:send')->daily()->when(function () {
184 | return true;
185 | });
186 | ````
187 |
188 | `skip` 方法可以被看作是 `when` 的逆过程。如果 `skip` 方法返回 `true` 的话,那么任务将不会运行:
189 |
190 | ````
191 | $schedule->command('emails:send')->daily()->skip(function () {
192 | return true;
193 | });
194 | ````
195 |
196 | 当链式调用多个 `when` 方法时,调度命令只有在所有的 `when` 条件返回 `true` 时才运行。
197 |
198 |
199 | ### 避免任务重复
200 |
201 | 默认情况,即便有相同的任务还在运行,调度内的任务依旧会被执行。为了避免这个问题,你可以使用 `withoutOverlapping` 方法:
202 |
203 | ````
204 | $schedule->command('emails:send')->withoutOverlapping();
205 | ````
206 |
207 | 在上面这个例子中,如果没有其它 [Artisan 命令](/docs/{{version}}/artisan) `emails:send` 在运行的话,此任务将于每分钟被运行一次。如果你的任务在执行时间上有很大的不同,你无法准确预测给定任务需要多长时间,`withoutOverlapping` 方法将会特别有帮助。
208 |
209 |
210 | ### 维护模式
211 |
212 | 当 Laravel 处于 [维护模式](/docs/{{version}}/configuration#maintenance-mode) 时,Laravel 的调度功能将不会生效。这是因为我们不想让任务调度干扰你服务器上可能还未完成的项目。然而,如果你想强制某个任务在维护模式下运行的话,你可以使用 `evenInMaintenanceMode` 方法:
213 |
214 | ````
215 | $schedule->command('emails:send')->evenInMaintenanceMode();
216 | ````
217 |
218 |
219 | ## 任务输出
220 |
221 | Laravel 调度器提供了几个方便的方法来处理调度任务生成的输出。首先,使用 `sendOutputTo` 方法可以将输出发送到单个文件上以便后续检查:
222 |
223 | ````
224 | $schedule->command('emails:send')
225 | ->daily()
226 | ->sendOutputTo($filePath);
227 | ````
228 |
229 | 如果想将输出附加到指定的文件上,则可以使用 `appendOutputTo` 方法:
230 |
231 | ````
232 | $schedule->command('emails:send')
233 | ->daily()
234 | ->appendOutputTo($filePath);
235 | ````
236 |
237 | 使用 `emailOutputTo` 方法,你可以通过电子邮件将输出发送到你所指定的邮箱上。在发送任务的输出之前,你应该先配置 Laravel 的 [电子邮件服务](/docs/{{version}}/mail):
238 |
239 | ````
240 | $schedule->command('foo')
241 | ->daily()
242 | ->sendOutputTo($filePath)
243 | ->emailOutputTo('foo@example.com');
244 | ````
245 |
246 | > {note} `emailOutputTo`、`sendOutputTo` 和 `appendOutputTo` 方法是 `command` 方法才有的,不支持在 `call` 方法上使用。
247 |
248 |
249 | ## 任务钩子
250 |
251 | 通过 `before` 与 `after` 方法,你可以指定要在调度任务完成之前和之后执行的代码:
252 |
253 | ````
254 | $schedule->command('emails:send')
255 | ->daily()
256 | ->before(function () {
257 | // 任务就要开始了…
258 | })
259 | ->after(function () {
260 | // 任务完成…
261 | });
262 | ````
263 |
264 | #### Ping 网址
265 |
266 | 使用 `pingBefore` 与 `thenPing` 方法,调度器可以在任务完成之前或之后自动 ping 给定的 URL。这个方法对于通知外部服务(例如 [Laravel Envoyer](https://envoyer.io))你的调度任务正在开始或已经完成执行很有用:
267 |
268 | ````
269 | $schedule->command('emails:send')
270 | ->daily()
271 | ->pingBefore($url)
272 | ->thenPing($url);
273 | ````
274 |
275 | 无论是使用 `pingBefore($url)` 还是 `thenPing($url)` 的功能,都需要 Guzzle HTTP 函数库的支持。你可以使用 `Composer` 将 Guzzle 函数库添加到你的项目中:
276 |
277 | ````
278 | composer require guzzlehttp/guzzle
279 | ````
280 |
281 | ## 译者署名
282 | | 用户名 | 头像 | 职能 | 签名 |
283 | |---|---|---|---|
284 | | [@沈益飞](https://laravel-china.org/users/13655) |
| 翻译 | [@m809745357](https://github.com/m809745357) at Github |
285 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
286 |
287 | ---
288 |
289 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
290 | >
291 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
292 | >
293 | > 文档永久地址: https://d.laravel-china.org
294 |
--------------------------------------------------------------------------------
/seeding.md:
--------------------------------------------------------------------------------
1 | # Laravel 数据库之:数据填充
2 |
3 | - [简介](#introduction)
4 | - [编写 Seeders](#writing-seeders)
5 | - [使用模型工厂](#using-model-factories)
6 | - [调用其他 Seeders](#calling-additional-seeders)
7 | - [ 运行 Seeders](#running-seeders)
8 |
9 |
10 | ## 简介
11 |
12 | Laravel 可以用 seed 类轻松地为数据库填充测试数据。所有的 seed 类都存放在 `database/seeds` 目录下。你可以任意为 seed 类命名,但是更应该遵守类似 `UsersTableSeeder` 的命名规范。Laravel 默认定义的一个 `DatabaseSeeder` 类。可以在这个类中使用 `call` 方法来运行其它的 seed 类从而控制数据填充的顺序。
13 |
14 |
15 | ## 编写 Seeders
16 |
17 | 通过运行 [Artisan 命令](/docs/{{version}}/artisan) `make:seeder` 来生成 Seeder。由框架生成的 seeders 都将被放置在 `database/seeds` 目录下:
18 |
19 | php artisan make:seeder UsersTableSeeder
20 | 一个 seeder 类只包含一个默认方法:`run`。这个方法会在 [Artisan 命令](/docs/{{version}}/artisan) `db:seed` 被执行时调用。在 `run` 方法里你可以根据需要在数据库中插入数据。你也可以用 [查询构造器](/docs/{{version}}/queries) 或 [Eloquent 模型工厂](/docs/{{version}}/database-testing#writing-factories) 来手动插入数据。
21 |
22 | > {tip} 在数据填充期间,[批量赋值保护](https://laravel.com/docs/5.5/eloquent#mass-assignment) 会自动禁用。
23 |
24 | 如下所示,在默认的 `DatabaseSeeder` 类中的 `run` 方法中添加一条数据插入语句:
25 |
26 | insert([
41 | 'name' => str_random(10),
42 | 'email' => str_random(10).'@gmail.com',
43 | 'password' => bcrypt('secret'),
44 | ]);
45 | }
46 | }
47 |
48 |
49 | ### 使用模型工厂
50 |
51 | 手动为每个模型填充指定属性很麻烦。作为替代方案,你可以使用 [模型工厂](/docs/{{version}}/database-testing#writing-factories) 来轻松地生成大量数据库数据。首先,阅读 [模型工厂文档](/docs/{{version}}/database-testing#writing-factories) 来学习如何使用工厂,然后就可以使用 `factory` 这个辅助函数来向数据库中插入数据。
52 |
53 | 例如,创建 50 个用户并为每个用户创建关联:
54 |
55 | /**
56 | * 运行数据库填充
57 | *
58 | * @return void
59 | */
60 | public function run()
61 | {
62 | factory(App\User::class, 50)->create()->each(function ($u) {
63 | $u->posts()->save(factory(App\Post::class)->make());
64 | });
65 | }
66 |
67 |
68 | ### 调用其他 Seeders
69 |
70 | 在 `DatabaseSeeder` 类中,你可以使用 `call` 方法来运行其他的 seed 类。使用 `call` 方法可以将数据填充拆分成多个文件,这样就不会使单个 seeder 变得非常大。只需简单传递要运行的 seeder 类名称即可:
71 |
72 | /**
73 | * Run the database seeds.
74 | *
75 | * @return void
76 | */
77 | public function run()
78 | {
79 | $this->call([
80 | UsersTableSeeder::class,
81 | PostsTableSeeder::class,
82 | CommentsTableSeeder::class,
83 | ]);
84 | }
85 |
86 |
87 | ## 运行 Seeders
88 |
89 | 完成 seeder 类的编写之后,你可能需要使用 `dump-autoload` 命令重新生成 Composer 的自动加载器:
90 |
91 | ```
92 | composer dump-autoload
93 | ```
94 |
95 | 接着就可以使用 Artisan 命令 `db:seed` 来填充数据库了。默认情况下,`db:seed` 命令将运行 `DatabaseSeeder` 类,这个类可以用来调用其它 Seed 类。不过,你也可以使用 `--class` 选项来指定一个特定的 seeder 类:
96 |
97 | php artisan db:seed
98 |
99 | php artisan db:seed --class=UsersTableSeeder
100 | 你也可以使用 `migrate:refresh` 命令来填充数据库,该命令会回滚并重新运行所有迁移。这个命令可以用来重建数据库:
101 |
102 | php artisan migrate:refresh --seed
103 |
104 | ## 译者署名
105 | | 用户名 | 头像 | 职能 | 签名 |
106 | |---|---|---|---|
107 | | [@wqer1019](https://laravel-china.org/users/5435) |
| 翻译 | laravel是世界上最优雅的框架,[@wqer1019](https://github.com/wqer1019) at Github |
108 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
109 |
110 | ---
111 |
112 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
113 | >
114 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
115 | >
116 | > 文档永久地址: https://d.laravel-china.org
117 |
--------------------------------------------------------------------------------
/socialite.md:
--------------------------------------------------------------------------------
1 | # Laravel 的 社会化登录功能
2 |
3 | - [简介](#introduction)
4 | - [授权](#license)
5 | - [官方文档](#official-documentation)
6 | - [配置](#configuration)
7 | - [基本用法](#basic-usage)
8 | - [无状态身份验证](#stateless-authentication)
9 | - [检索用户详细信息](#retrieving-user-details)
10 | - [从令牌检索用户详细信息](#retrieving-user-details-from-token)
11 |
12 |
13 | ## 简介
14 |
15 | Laravel 社会化登录通过 Facebook , Twitter ,Google ,LinkedIn ,GitHub 和 Bitbucket 提供了一个富有表现力的,流畅的 OAuth 身份验证界面。它几乎能处理所有你害怕处理的各种样板社会认证代码。
16 |
17 | > 翻译自 Readme: https://github.com/laravel/socialite
18 |
19 | **我们不接受新的适配器。**
20 |
21 | **如果你使用 Laravel 5.3 或更低版本,请使用 [Socialite 2.0](https://github.com/laravel/socialite/tree/2.0)。**
22 |
23 | 社区驱动的社会化登录提供商网站上可以找到为其他平台提供的适配器列表。
24 |
25 |
26 | ## 授权
27 |
28 | Laravel 社会化登录是根据 [MIT 授权](http://opensource.org/licenses/MIT) 许可的开源软件
29 |
30 |
31 | ## 官方文档
32 |
33 | 除了常规的基于表单的身份验证之外, Laravel 也提供了一种简单,方便的办法来使用 [Laravel 社会化登录](https://github.com/laravel/socialite) 向 OAuth 提供程序进行身份验证。社公化登录目前支持 `Facebook` , `Twitter` , `LinkedIn` ,`Google` ,`GitHub` 和 `Bitbucket` 的身份验证。
34 |
35 | 要开始社会化登录,使用 `composer` 将相应包加入到你项目的依赖项中。
36 |
37 | composer require laravel/socialite
38 |
39 |
40 | ### 配置
41 |
42 | 安装完社会化登录库之后,在你的 `config/app.php` 文件中注册 `Laravel\Socialite\SocialiteServiceProvider` 。
43 |
44 | ```php
45 | 'providers' => [
46 | // Other service providers...
47 |
48 | Laravel\Socialite\SocialiteServiceProvider::class,
49 | ],
50 | ```
51 |
52 | 同时,在你的 `app` 配置文件中,把 `Socialite` facade 加入到 `aliases` 数组中。
53 |
54 | ```php
55 | 'Socialite' => Laravel\Socialite\Facades\Socialite::class,
56 | ```
57 |
58 | 你还需要为你应用使用的 OAuth 服务加入凭据。这些凭据应该放在你的 `config/services.php` 文件中,并且使用 `facebook` , `twitter` , `linkedin` , `google` , `github` 或 `bitbucket` 作为键名,具体取决于在你的应用中由哪个程序来提供验证服务,比如:
59 |
60 | ```php
61 | 'github' => [
62 | 'client_id' => 'your-github-app-id',
63 | 'client_secret' => 'your-github-app-secret',
64 | 'redirect' => 'http://your-callback-url',
65 | ],
66 | ```
67 |
68 | ### 基本用法
69 |
70 | 接下来,你已经准备好了验证用户了!你需要两个路由:一个重定向用户到 OAuth 提供商,另一个在提供商验证之后接收回调。我们用 `Socialite` facade 来访问:
71 |
72 | ```php
73 | redirect();
89 | }
90 |
91 | /**
92 | * Obtain the user information from GitHub.
93 | *
94 | * @return Response
95 | */
96 | public function handleProviderCallback()
97 | {
98 | $user = Socialite::driver('github')->user();
99 |
100 | // $user->token;
101 | }
102 | }
103 | ```
104 |
105 | `redirect` 方法负责发送用户到 OAuth 提供商,而 `user` 方法将读取传入的请求并从提供商处检索用户信息。在重定向用户之前,你还可以加入附加的 `scope` 方法来设置请求的「scope」。这个方法会覆盖所有现有的范围。
106 |
107 | ```php
108 | return Socialite::driver('github')
109 | ->scopes(['scope1', 'scope2'])->redirect();
110 | ```
111 |
112 | 你可以使用 `setScopes` 方法覆盖所有已经存在的 scopes:
113 |
114 | ```php
115 | return Socialite::driver('github')
116 | ->setScopes(['scope1', 'scope2'])->redirect();
117 | ```
118 |
119 | 当然,你需要定义通往你的控制器方法的路由。
120 |
121 | ```php
122 | Route::get('login/github', 'Auth\LoginController@redirectToProvider');
123 | Route::get('login/github/callback', 'Auth\LoginController@handleProviderCallback');
124 | ```
125 |
126 | 一部分 OAuth 提供商在重定向请求中支持携带可选参数。要在请求中包含任何可选参数,调用 `with` 方法时传入可选的数组即可。
127 |
128 | ```php
129 | return Socialite::driver('google')
130 | ->with(['hd' => 'example.com'])->redirect();
131 | ```
132 |
133 | 当使用 `with` 方法时,注意不要传递保留关键字,比如 `state` 或 `response_type` 。
134 |
135 |
136 | #### 无状态身份验证
137 |
138 | `stateless` 方法可以用于禁用 session 状态的验证,这个方法在向 API 添加社会化身份验证时非常有用。
139 |
140 | ```php
141 | return Socialite::driver('google')->stateless()->user();
142 | ```
143 |
144 |
145 | #### 检索用户详细信息
146 |
147 | 一旦你有了一个用户实例,你可以获取这个用户的更多详细信息:
148 |
149 | ```php
150 | $user = Socialite::driver('github')->user();
151 |
152 | // OAuth Two Providers
153 | $token = $user->token;
154 | $refreshToken = $user->refreshToken; // not always provided
155 | $expiresIn = $user->expiresIn;
156 |
157 | // OAuth One Providers
158 | $token = $user->token;
159 | $tokenSecret = $user->tokenSecret;
160 |
161 | // All Providers
162 | $user->getId();
163 | $user->getNickname();
164 | $user->getName();
165 | $user->getEmail();
166 | $user->getAvatar();
167 | ```
168 |
169 | #### 从令牌检索用户详细信息
170 |
171 | 如果你已经有了一个用户的有效访问令牌,你可以使用 `userFromToken` 方法检索用户的详细信息。
172 |
173 | ```php
174 | $user = Socialite::driver('github')->userFromToken($token);
175 | ```
176 |
177 |
178 | ## 译者署名
179 |
180 | | 用户名 | 头像 | 职能 | 签名 |
181 | |---|---|---|---|
182 | | [@qufo](https://github.com/qufo) |
| 翻译 | 欢迎共同探讨。[@Qufo](https://github.com/qufo) |
183 |
184 |
185 | ---
186 |
187 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
188 | >
189 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
190 | >
191 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/structure.md:
--------------------------------------------------------------------------------
1 | # Laravel 的文件夹结构
2 |
3 | - [简介](#introduction)
4 | - [根目录](#the-root-directory)
5 | - [`app` 目录](#the-root-app-directory)
6 | - [`bootstrap` 目录](#the-bootstrap-directory)
7 | - [`config` 目录](#the-config-directory)
8 | - [`database` 目录](#the-database-directory)
9 | - [`public` 目录](#the-public-directory)
10 | - [`resources` 目录](#the-resources-directory)
11 | - [`routes` 目录](#the-routes-directory)
12 | - [`storage` 目录](#the-storage-directory)
13 | - [`tests` 目录](#the-tests-directory)
14 | - [`vendor` 目录](#the-vendor-directory)
15 | - [App 目录](#the-app-directory)
16 | - [`Console` 目录](#the-console-directory)
17 | - [`Events` 目录](#the-events-directory)
18 | - [`Exceptions` 目录](#the-exceptions-directory)
19 | - [`Http` 目录](#the-http-directory)
20 | - [`Jobs` 目录](#the-jobs-directory)
21 | - [`Listeners` 目录](#the-listeners-directory)
22 | - [`Mail` 目录](#the-mail-directory)
23 | - [`Notifications` 目录](#the-notifications-directory)
24 | - [`Policies` 目录](#the-policies-directory)
25 | - [`Providers` 目录](#the-providers-directory)
26 | - [`Rules` 目录](#the-rules-directory)
27 |
28 |
29 | ## 简介
30 |
31 | 默认的 Laravel 应用结构旨在为不同大小的应用提供一个好的起点。当然,你可以按照喜好整理应用的目录结构。Laravel 没有严格地限制任何给定的类的位置,只要它们能被 Composer 自动加载。
32 |
33 | #### 为什么没有模型目录?
34 |
35 | 当开始使用 Laravel 时,许多开发人员都因缺少 `models` 目录而感到困惑。然而,缺少这样的目录是故意的。我们发现「模型」含糊不清,因为对许多不同的人来说有着各自不同的理解。一些开发者把应用的「模型」称为其所有业务逻辑的总体,而另一些人将「模型」称为与关系数据库交互的类。
36 |
37 | 因此,我们默认把 Eloquernt 的模型放在 `app` 目录下,并且允许开发者自行选择放置在何处。
38 |
39 |
40 | ## 根目录
41 |
42 |
43 | #### `app` 目录
44 |
45 | `app` 目录包含应用程序的核心代码。你应用中几乎所有的类都应该放在这里。稍后我们会更深入地了解这个目录的细节。
46 |
47 |
48 | #### `Bootstrap` 目录
49 |
50 | `bootstrap` 目录包含引导框架并配置自动加载的文件。该目录还包含了一个 `cache` 目录,存放着框架生成的用来提升性能的文件,比如路由和服务缓存文件。
51 |
52 |
53 | #### `Config` 目录
54 |
55 | `config` 目录,顾名思义,包含应用程序所有的配置文件。我们鼓励你通读这些文件,以便帮助你熟悉所有可用的选项。
56 |
57 |
58 | #### `Database` 目录
59 |
60 | `database` 目录包含数据填充和迁移文件。你还可以把它作为 SQLite 数据库存放目录。
61 |
62 |
63 | #### `Public` 目录
64 |
65 | `public` 目录包含了入口文件 `index.php`,它是进入应用程序的所有请求的入口点。此目录还包含了一些你的资源文件(如图片、JavaScript 和 CSS)。
66 |
67 |
68 | #### `Resources` 目录
69 |
70 | `resource` 目录包含了视图和未编译的资源文件(如 LESS、SASS 或 JavaScript)。此目录还包含你所有的语言文件。
71 |
72 |
73 | #### `Routes` 目录
74 |
75 | `routes` 目录包含了应用的所有路由定义,Laravel 默认包含了几个路由文件:`web.php`、`api.php`、 `console.php` 和 `channels.php`。
76 |
77 | `web.php` 文件包含 `RouteServiceProvider` 放置在 `web` 中间件组中的路由,它提供会话状态、CSRF 防护和 cookie 加密。如果你的应用不提供无状态的、RESTful 风格的 API,则所有的路由都应该在 `web.php` 文件中定义。
78 |
79 | `api.php` 文件包含 `RouteServiceProvider` 放置在 `api` 中间件组中的路由,它提供了频率限制。这些路由都是无状态的,所以通过这些路由进入应用请求旨在通过令牌进行身份认证,并且不能访问会话状态。
80 |
81 | `console.php` 文件是定义所有基于闭包的控制台命令的地方。每个闭包都被绑定到一个命令实例并且允许和命令行 IO 方法进行简单的交互。尽管这些文件没有定义 HTTP 路由,但它也将基于控制台的入口点(路由)定义到应用程序中。
82 |
83 | `channels.php` 用来注册你的应用支持的所有的事件广播渠道的地方。
84 |
85 |
86 | #### `Storage` 目录
87 |
88 | `storage` 目录包含编译的 Blade 模板、基于文件的会话和文件缓存、以及框架生成的其他文件。这个目录被细分成 `app `、`framework` 和 `logs` 三个子目录。`app` 目录可以用来存储应用生成的任何文件。`framework` 目录用来存储框架生成的文件和缓存。最后,`logs` 目录包含应用的日志文件。
89 |
90 | `storage/app/public` 可以用来存储用户生成的文件,比如需要公开访问的用户头像。你应该创建一个 `public/storage` 的软链接指向这个目录。你可以直接通过 `php artisan storage:link` 命令来创建此链接。
91 |
92 |
93 | #### `Tests` 目录
94 |
95 | `tests` 目录包含自动化测试文件。Laravel 已内置了 [PHPUnit](https://phpunit.de/) 的测试范例供你参考。每个测试类都应该以 `Test` 作为后缀。你可以使用 `phpunit` 或者 `php vendor/bin/phpunit` 命令来运行测试。
96 |
97 |
98 | #### `Vendor` 目录
99 |
100 | `vendor` 目录包含了你的 [Composer](https://getcomposer.org) 依赖包。
101 |
102 |
103 | ## `App` 目录
104 |
105 | 应用程序的核心代码位于 `app` 目录内。默认情况下,这个目录位于命名空间 `App` 下,并由 Composer 按照 [PSR-4 自动载入标准](http://www.php-fig.org/psr/psr-4/) 来自动加载。
106 |
107 | `app` 目录包含了各种各样的目录,比如 `Console`、`Http` 和 `Providers` 等。其中 `Console` 和 `Http` 提供进入应用核心的 API。HTTP 协议和 CLI 都只是应用交互的机制,实际上并不包含应用逻辑。也就是说,它们只是两种向应用发出命令的方法。`Console` 目录里包含了所有的 Artisan 命令,`Http` 目录包含了应用的控制器、中间件和请求。
108 |
109 | 当你通过 Artisan 提供的 make 命令来生成类时,会在 `app` 中生成各种各样的目录。例如,在执行 Artisan 命令 `make:job` 来生成任务类之前,`app/Jobs` 目录都不会存在。
110 |
111 | > {tip} `app` 目录里的许多类都可以通过 Artisan 命令来生成。要查看可用的命令,只要在终端里运行 `php artisan list make` 命令即可。
112 |
113 |
114 | #### `Console` 目录
115 |
116 | `Console` 目录包含了所有自定义的 Artisan 命令。这些命令可以通过 `make:command` 来生成。这个目录还包含了控制台内核,可以用来注册你的自定义 Artisan 命令和你定义的 [计划任务](/docs/{{version}}/scheduling) 的地方。
117 |
118 |
119 | #### `Events` 目录
120 |
121 | `Events` 目录默认是不存在的,它会在你运行 Artisan 命令 `event:generate` 或 `event:make` 时生成。`Events` 目录存放了 [事件类](/docs/{{version}}/events)。可以使用事件来提醒应用其他部分发生了特定的操作,为应用提供了大量的灵活性和解耦。
122 |
123 |
124 | #### `Exceptions` 目录
125 |
126 | `Exceptions` 目录包含了应用的异常处理器,也是应用抛出异常的好地方。如果想自定义记录或者渲染异常的方式,你就要修改此目录下的 Handler 类。
127 |
128 |
129 | #### `Http` 目录
130 |
131 | `Http` 目录包含了控制器、中间件和表单请求。几乎所有的进入应用的请求的处理逻辑都被放在这里。
132 |
133 |
134 | #### `Jobs` 目录
135 |
136 | `Jobs` 目录默认是不存在的,它会在你运行Artisan 命令 `make:job` 时生成。这个目录存放了应用中的 [队列任务](/docs/{{version}}/queues)。应用的任务可以被推送到队列或者在当前请求的生命周期内同步运行。在当前请求期间同步运行的任务可以看做是一个「命令」,因为它们是 [命令模式](https://en.wikipedia.org/wiki/Command_pattern) 的实现。
137 |
138 |
139 | #### `Listeners` 目录
140 |
141 | `Listeners` 目录默认是不存在的,它会在你运行 Artisan 命令 `event:generate` 或 `make:listener` 时生成。`Listeners` 目录包含了用来处理 [事件](/docs/{{version}}/events) 的类。事件监听器接收事件实例并执行响应该事件被触发的逻辑。例如,`UserRegistered` 事件可能由 `SendWelcomeEmail` 监听器处理。
142 |
143 |
144 | #### `Mail` 目录
145 |
146 | `Mail` 目录默认不存在,它会在你运行 Artisan 命令 `make:mail` 时生成。`Mail` 目录包含应用所有的邮件发送类。邮件对象允许你将构建邮件的逻辑封装在可以使用 `Mail::send` 方法来发送邮件的地方。
147 |
148 |
149 | #### `Notifications` 目录
150 |
151 | `Notifications` 目录默认不存在,它会在你运行 Artisan 命令 `make:notification` 时生成。`Notifications` 目录包含应用发送的所有「事务性」通知,比如关于在应用中发生的事件的简单通知。Laravel 的通知功能抽象了通知发送,可以通过各种驱动(例如邮件、Slack、短信)发送通知,或是存储在数据库中。
152 |
153 |
154 | #### `Policies` 目录
155 |
156 | `Policies` 目录默认不存在,它会通过运行 Artisan 命令 `make:policy` 来创建。`Policies` 目录包含了应用的授权策略类。策略可以用来决定一个用户是否有权限去操作指定资源。更多详情可以查看 [授权文档](/docs/{{version}}/authorization)。
157 |
158 |
159 | #### `Providers` 目录
160 |
161 | `Providers` 目录包含了应用的所有 [服务提供器](/docs/{{version}}/providers)。服务提供器通过在服务容器中绑定服务、注册事件、以及执行其他任务来为即将到来的请求做准备来启动应用。
162 |
163 | 在一个新的 Laravel 应用里,这个目录已经包含了一些服务提供器。你可以按照需要把自由添加自己的服务提供器到该目录。
164 |
165 |
166 | #### `Rules` 目录
167 |
168 | `Rules` 目录默认不存在,它会在运行 Artisan 命令 `make:rule` 命令时被创建。`Rules` 目录包含应用自定义验证规则对象。这些规则意在将复杂的验证逻辑封装在一个简单的对象中。更多详情可以查看 [验证文档](/docs/{{version}}/validation)。
169 |
170 | ## 译者署名
171 | | 用户名 | 头像 | 职能 | 签名 |
172 | | --- | --- | --- | --- |
173 | | [@huiren](https://laravel-china.org/users/5583) |
| 翻译 | 认领翻译,只是起点。 |
174 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
175 |
176 |
177 | ---
178 |
179 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
180 | >
181 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
182 | >
183 | > 文档永久地址: https://d.laravel-china.org
184 |
--------------------------------------------------------------------------------
/testing.md:
--------------------------------------------------------------------------------
1 | # Laravel 测试: 入门指南
2 |
3 | - [简介](#introduction)
4 | - [测试环境](#environment)
5 | - [定义并运行测试](#creating-and-running-tests)
6 |
7 |
8 | ## 简介
9 |
10 | Laravel 天生就具有测试的基因。事实上,Laravel 默认就支持用 PHPUnit 来做测试,并为你的应用程序配置好了 `phpunit.xml` 文件。框架还提供了一些便利的辅助函数,让你可以更直观的测试应用程序。
11 |
12 | 默认在你应用的 `tests` 目录下包含了两个子目录: `Feature` 和 `Unit`。单元测试是针对你代码中相对独立而且非常少的一部分代码来进行测试。实际上,大多数单元测试可能都是针对某一个方法来进行的。功能测试是针对你代码中大部分的代码来进行测试,包括几个对象的相互作用,甚至是一个完整的 HTTP 请求 JSON 实例。
13 |
14 | 在 `Feature` 和 `Unit` 目录中都有提供一个 `ExampleTest.php` 的示例文件。安装新的 Laravel 应用程序之后,只需在命令行上运行 `phpunit` 就可以进行测试。
15 |
16 |
17 | ## 测试环境
18 |
19 | 在运行测试时,Laravel 会根据 `phpunit.xml` 文件中设定好的环境变量自动将环境变量设置为 `testing`,并将 Session 及缓存以 `array` 的形式存储,也就是说在测试时不会持久化任何 Session 或缓存数据。
20 |
21 | 你可以随意创建其它必要的测试环境配置。`testing` 环境的变量可以在 `phpunit.xml` 文件中被修改,但是在运行测试之前,请确保使用 `config:clear` Artisan 命令来清除配置信息的缓存。
22 |
23 |
24 | ## 定义并运行测试
25 |
26 | 可以使用 `make:test` Artisan 命令,创建一个测试用例:
27 |
28 | // 在 Feature 目录下创建一个测试类...
29 | php artisan make:test UserTest
30 |
31 | // 在 Unit 目录下创建一个测试类...
32 | php artisan make:test UserTest --unit
33 |
34 | 测试类生成之后,你就可以像平常使用 PHPUnit 一样来定义测试方法。要运行测试只需要在终端上运行 `phpunit` 命令即可:
35 |
36 | assertTrue(true);
54 | }
55 | }
56 |
57 | > {note} 如果要在你的测试类自定义自己的 `setUp` 方法,请确保调用了 `parent::setUp()` 方法。
58 |
59 |
60 | ---
61 |
62 | ## 译者署名
63 | | 用户名 | 头像 | 职能 | 签名 |
64 | |---|---|---|---|
65 | | [@wqer1019](https://laravel-china.org/users/5435) |
| 翻译 | laravel是世界上最优雅的框架,[@wqer1019](https://github.com/wqer1019) at Github |
66 |
67 | ---
68 |
69 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
70 | >
71 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
72 | >
73 | > 文档永久地址: https://d.laravel-china.org
--------------------------------------------------------------------------------
/upgrade.md:
--------------------------------------------------------------------------------
1 | # Laravel 升级索引
2 |
3 | - [从 5.4 升级至 5.5.0](#upgrade-5.5.0)
4 |
5 |
6 |
7 | ## 从 5.4 升级到 5.5.0
8 |
9 | #### 预计升级耗时:1小时
10 |
11 | > {note}我们尽量记录每一个可能的破坏性变化。但因为其中一些不兼容变更只存在于框架很不起眼的地方,事实上只有一小部分可能会影响到你的应用程序。
12 |
13 | ### 更新依赖
14 |
15 | 在 `composer.json` 文件中将 `laravel/framework` 更新为 `5.5.*` 。 此外,你还应该将 `phpunit/phpunit` 依赖关系更新到 `~6.0`。
16 |
17 | > {tip} 如果你是通过使用 `laravel new` 来安装 Laravel 程序,则应该使用命令 `composer global update` 来更新 Laravel 安装程序包。
18 |
19 | #### Laravel Dusk
20 |
21 | Laravel Dusk `2.0.0` 已经发布,该版本同时兼容 Laravel 5.5 和 Chrome 的 headless 模式测试。
22 |
23 | #### Pusher
24 |
25 | Pusher 事件广播驱动现在需要 `~3.0` 版本的 Pusher SDK。
26 |
27 | ### Artisan
28 |
29 | #### `fire` 方法
30 |
31 | 该方法已重命名为 `handle` 方法。
32 |
33 | #### `optimize` 命令
34 |
35 | 随着对 PHP 操作码缓存的最新改进,不再需要优化 Artisan 命令。你应该从部署脚本中删除对此命令的任何引用,因为它在未来的 Laravel 版本中会被删除。
36 |
37 | ### 用户授权
38 |
39 | #### `authorizeResouce` 控制器方法
40 |
41 | 当将一个大驼峰命名的模型名称传递给 `authorizeResource` 方法时,为了和资源控制器的行为相匹配,生成的路由会用蛇形命名法来命名。
42 |
43 | #### `before` 策略方法
44 |
45 | 如果类中不包含与给定名称相匹配的方法,则不会调用策略类的 `before` 方法。
46 |
47 | ### 缓存
48 |
49 | #### 数据库驱动
50 |
51 | 如果你正在使用数据库缓存驱动,那在你第一次部署升级至 Laravel 5.5时,应该先运行 `php artisan cache:clear` 命令。
52 |
53 | ### Eloquent
54 |
55 | #### `belongsToMany` 方法
56 |
57 | 如果你在 Eloquent 模型中重写了 `belongsToMany` 方法,应该更新方法签名来映射新增的参数:
58 |
59 | /**
60 | * 定义多对多关系。
61 | *
62 | * @param string $related
63 | * @param string $table
64 | * @param string $foreignPivotKey
65 | * @param string $relatedPivotKey
66 | * @param string $parentKey
67 | * @param string $relatedKey
68 | * @param string $relation
69 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
70 | */
71 | public function belongsToMany($related, $table = null, $foreignPivotKey = null,
72 | $relatedPivotKey = null,$parentKey = null,
73 | $relatedKey = null, $relation = null)
74 | {
75 | //
76 | }
77 |
78 | #### 模型的 `is` 方法
79 |
80 | 如果你重写了 Eloquent 模型的 `is` 方法 ,则应该从该方法中删除 `Model` 的类型提示。这将允许 `is` 方法接受 `null` 作为参数。
81 |
82 | /**
83 | * 确定两个模型是否具有相同的ID并且属于同一个表。
84 | *
85 | * @param \Illuminate\Database\Eloquent\Model|null $model
86 | * @return bool
87 | */
88 | public function is($model)
89 | {
90 | //
91 | }
92 |
93 | #### 模型 `$events` 属性
94 |
95 | 模型上的 `$events` 属性应该重命名为 `$dispatchesEvents`。由于大量用户需要定义事件关系,导致与旧属性名称的冲突,因此进行了更改。
96 |
97 | #### 中间表 `$parent` 属性
98 |
99 | `Illuminate\Database\Eloquent\Relations\Pivot` 类中受保护的 `$parent` 属性已被重命名为 `$pivotParent` 。
100 |
101 | #### 关联 `create` 方法
102 |
103 | `BelongsToMany`、`HasOneOrMany` 以及 `MorphOneOrMany` 类中的 `create` 方法已被修改为 `$attributes` 参数提供默认值。如果你重写了这些方法,你应该更新你的签名来匹配新的定义。
104 |
105 | public function create(array $attributes = [])
106 | {
107 | //
108 | }
109 |
110 | #### 软删除模型
111 |
112 | 删除 「软删除」 模型时,模型上的 `exists` 属性将保持为 `true` 。
113 |
114 | #### `withCount` 列格式化
115 |
116 | 当使用别名时,`withCount` 方法将不再自动将 `_count` 附加到生成的列名称上。例如,在 Laravel 5.4 中,以下查询会将 `bar_count` 列添加到查询中:
117 |
118 | $users = User::withCount('foo as bar')->get();
119 |
120 | 但是在 Laravel 5.5 中,别名将严格按照给定的方式使用。如果要将 `_count` 追加到结果列,则必须在定义别名时指定该后缀:
121 |
122 | $users = User::withCount('foo as bar_count')->get();
123 |
124 | ### 异常格式
125 |
126 | 在 Laravel 5.5 中,所有的异常(包括验证异常)都被异常处理程序转换成 HTTP 响应。另外,验证错误默认返回的 JSON 格式已经更改。新格式遵循以下规则:
127 |
128 | {
129 | "message": "The given data was invalid.",
130 | "errors": {
131 | "field-1": [
132 | "Error 1",
133 | "Error 2"
134 | ],
135 | "field-2": [
136 | "Error 1",
137 | "Error 2"
138 | ],
139 | }
140 | }
141 |
142 | 但是,如果你想沿用 Laravel 5.4 错误提示的 JSON 格式,则可以将以下方法添加到 `App\Exceptions\Handler` 类中:
143 |
144 | use Illuminate\Validation\ValidationException;
145 |
146 | /**
147 | * 将验证异常转换成 JSON 响应
148 | *
149 | * @param \Illuminate\Http\Request $request
150 | * @param \Illuminate\Validation\ValidationException $exception
151 | * @return \Illuminate\Http\JsonResponse
152 | */
153 | protected function invalidJson($request, ValidationException $exception)
154 | {
155 | return response()->json($exception->errors(), $exception->status);
156 | }
157 |
158 | #### JSON 身份验证尝试
159 |
160 | 此更改也会影响通过 JSON 进行的身份验证尝试的验证错误返回的格式。在 Laravel 5.5 中,身份验证失败的 JSON 将按照上述新的格式约定返回错误消息。
161 |
162 | #### 表单请求注意事项
163 |
164 | 现在自定义了单个表单请求的响应格式,应重写该表单请求的 `failedValidation` 方法 ,并抛出一个包含自定义响应的 `HttpResponseException` 实例。
165 |
166 | use Illuminate\Http\Exceptions\HttpResponseException;
167 |
168 | /**
169 | * 处理失败的验证尝试。
170 | *
171 | * @param \Illuminate\Contracts\Validation\Validator $validator
172 | * @return void
173 | *
174 | * @throws \Illuminate\Validation\ValidationException
175 | */
176 | protected function failedValidation(Validator $validator)
177 | {
178 | throw new HttpResponseException(response()->json(..., 422));
179 | }
180 |
181 | ### 文件系统
182 |
183 | #### `files` 方法
184 |
185 | `files` 方法与 `allFiles` 方法类似,会返回一个 `SqlFileInfo` 对象的数组。之前的 `files` 方法会返回一个字符串路径名的数组。
186 |
187 | ### 邮件
188 |
189 | #### 未使用的参数
190 |
191 | 未使用的 `$data` 和 `$callback` 参数已从 `Illuminate\Contracts\Mail\MailQueue` 契约的 `queue` 和 `later` 方法中删除
192 |
193 | /**
194 | * 在队列中发送新的电子邮件
195 | *
196 | * @param string|array|MailableContract $view
197 | * @param string $queue
198 | * @return mixed
199 | */
200 | public function queue($view, $queue = null);
201 |
202 | /**
203 | * n 秒后在队列中发送新的电子邮件
204 | *
205 | * @param \DateTimeInterface|\DateInterval|int $delay
206 | * @param string|array|MailableContract $view
207 | * @param string $queue
208 | * @return mixed
209 | */
210 | public function later($delay, $view, $queue = null);
211 |
212 | ### 请求
213 |
214 | #### `has` 方法
215 |
216 | `$request->has` 方法现在对于空字符串和 `null` 将返回 `true`。新添加的 `$request->filled` 方法提供了之前的 `has` 方法的行为。
217 |
218 | #### `intersect` 方法
219 |
220 | `intersect` 方法已被移除。你只需在调用 `$request->only` 时使用 `array_filter` 来代替该方法:
221 |
222 | return array_filter($request->only('foo'));
223 |
224 | #### `only` 方法
225 |
226 | `only` 方法现在只会返回请求中实际存在的属性。如果你想保留该方法的旧功能,可以使用 `all` 方法来替代。
227 |
228 | return $request->all('foo');
229 |
230 | #### 辅助函数 `request()`
231 |
232 | 辅助函数 `request` 将不再检索嵌套的键。如果有需要,你可以使用 `request` 中的 `input` 方法来达成此目的:
233 |
234 | return request()->input('filters.date');
235 |
236 | ### 测试
237 |
238 | #### 认证声明
239 |
240 | 一些认证断言被重命名为与框架的其他断言更好的一致性:
241 |
242 |
243 | - `seeIsAuthenticated` 被重命名为 `assertAuthenticated` ;
244 | - `dontSeeIsAuthenticated` 被重命名为 `assertGuest` ;
245 | - `seeIsAuthenticatedAs` 被重命名为 `assertAuthenticatedAs` ;
246 | - `seeCredentials` 被重命名为 `assertCredentials` ;
247 | - `dontSeeCredentials` 被重命名为 `assertInvalidCredentials` 。
248 |
249 |
250 | #### 伪造邮件
251 |
252 | 如果你使用伪造 Mail 来请求中是否有可用的**队列** ,则应该使用 `Mail::assertQueued` 来代替 `Mail::assertSent` 。 这种区别允许你明确声明邮件已在队列中等待发送,而不是在请求期间发送。
253 |
254 | ### 翻译
255 |
256 | #### `LoaderInterface`
257 |
258 | `Illuminate\Translation\LoaderInterface` 该接口已被移动至 `Illuminate\Contracts\Translation\Loader`。
259 |
260 | ### 验证
261 |
262 | #### 验证方法
263 |
264 | 所有的验证器的验证方法已由 `protected` 改为 `public` 。
265 |
266 | ### 视图
267 |
268 | #### 动态的 「with」 变量
269 |
270 | 当允许动态的 `__call` 方法与视图共享变量时,该变量将会自动使用驼峰式命名。举例如下:
271 |
272 | return view('pool')->withMaximumVotes(100);
273 |
274 | `maximumVotes` 变量可以在模板中访问,如下所示:
275 |
276 | {{ $maximumVotes }}
277 | ### 其他
278 |
279 | 你还可以查看 `laravel/laravel` 在 GitHub 中的更改。虽然这些更改不是必需的,但你可能希望将这些文件与应用程序保持同步。本升级指南中将介绍其中一些更改,而其他的则不会被介绍,例如更改配置文件或注释。你可以使用 [GitHub 的比较工具](https://github.com/laravel/laravel/compare/5.4...master) 轻松查看你在意的变更的内容。
280 |
281 | ## 译者署名
282 | | 用户名 | 头像 | 职能 | 签名 |
283 | |---|---|---|---|
284 | | [@我做我的梦](https://laravel-china.org/users/18485) |
| 翻译 | A new to Laravel,and hope Laravel is the last framework for me. |
285 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
286 |
287 |
288 | ---
289 |
290 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
291 | >
292 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
293 | >
294 | > 文档永久地址: https://d.laravel-china.org
295 |
--------------------------------------------------------------------------------
/urls.md:
--------------------------------------------------------------------------------
1 | # Laravel 的 URL 生成
2 |
3 | - [简介](#introduction)
4 | - [基础](#the-basics)
5 | - [生成基础 URL](#generating-basic-urls)
6 | - [访问当前 URL](#accessing-the-current-url)
7 | - [命名路由的 URL](#urls-for-named-routes)
8 | - [控制器行为的 URL](#urls-for-controller-actions)
9 | - [默认值](#default-values)
10 |
11 |
12 | ## 简介
13 |
14 | Laravel 提供了几个辅助函数来为应用程序生成 URL。主要用于在模板和 API 响应中构建 URL 或者在应用程序的其他部分生成重定向响应。
15 |
16 |
17 | ## 基础
18 |
19 |
20 | ### 生成基础 URL
21 |
22 | 辅助函数 `url` 可以用于应用的任何一个 URL。生成的 URL 将自动使用当前请求中的方案( HTTP 或 HTTPS )和主机:
23 |
24 | $post = App\Post::find(1);
25 |
26 | echo url("/posts/{$post->id}");
27 |
28 | // http://example.com/posts/1
29 |
30 |
31 | ### 访问当前 URL
32 |
33 | 如果没有给辅助函数 `url` 提供路径,则会返回一个 `Illuminate\Routing\UrlGenerator` 实例,来允许你访问有关当前 URL 的信息:
34 |
35 | // 获取没有查询字符串的当前的 URL ...
36 | echo url()->current();
37 |
38 | // 获取包含查询字符串的当前的 URL ...
39 | echo url()->full();
40 |
41 | // 获取上一个请求的完整的 URL...
42 | echo url()->previous();
43 |
44 | 上面的这些方法都可以通过 `URL` [facade](/docs/{{version}}/facades) 访问:
45 |
46 | use Illuminate\Support\Facades\URL;
47 |
48 | echo URL::current();
49 |
50 |
51 | ## 命名路由的 URL
52 |
53 | 辅助函数 `route` 可以用于为指定路由生成 URL。命名路由生成的 URL 不与路由上定义的 URL 相耦合。因此,就算路由的 URL 有任何更改,都不需要对 `route` 函数调用进行任何更改。例如,假设你的应用程序包含以下路由:
54 |
55 | Route::get('/post/{post}', function () {
56 | //
57 | })->name('post.show');
58 |
59 | 要生成此路由的 URL,可以像这样使用辅助函数 `route`:
60 |
61 | echo route('post.show', ['post' => 1]);
62 |
63 | // http://example.com/post/1
64 | 将 [Eloquent 模型](/docs/{{version}}/eloquent) 作为参数值传给 `route` 方法,它会自动提取模型的主键来生成 URL。
65 |
66 | echo route('post.show', ['post' => $post]);
67 |
68 |
69 | ## 控制器行为的 URL
70 |
71 | `action` 功能可以为给定的控制器行为生成 URL。这个功能不需要你传递控制器的完整命名空间,但你需要传递相对于命名空间 `App\Http\Controllers` 的控制器类名:
72 |
73 | $url = action('HomeController@index');
74 | 如果控制器方法需要路由参数,那就将它们作为第二个参数传递给 `action` 函数:
75 |
76 | $url = action('UserController@profile', ['id' => 1]);
77 |
78 |
79 | ## 默认值
80 |
81 | For some applications, you may wish to specify request-wide default values for certain URL parameters. For example, imagine many of your routes define a `{locale}` parameter:
82 |
83 | 对于某些应用程序,你可能希望为某些 URL 参数的请求范围指定默认值。例如,假设有些路由定义了 `{locale}` 参数:
84 |
85 | Route::get('/{locale}/posts', function () {
86 | //
87 | })->name('post.index');
88 |
89 | 每次都通过 `locale` 来调用辅助函数 `route` 也是一件很麻烦的事情。因此,使用 `URL::defaults` 方法定义这个参数的默认值,可以让该参数始终存在当前请求中。然后就能从 [路由中间件](/docs/{{version}}/middleware#assigning-middleware-to-routes) 调用此方法来访问当前请求:
90 |
91 | $request->user()->locale]);
103 |
104 | return $next($request);
105 | }
106 | }
107 |
108 | 一旦设置了 `locale` 参数的默认值,就不需要在使用辅助函数 `route` 生成 URL 时传递这个值。
109 |
110 | ## 译者署名
111 | | 用户名 | 头像 | 职能 | 签名 |
112 | | --- | --- | --- | --- |
113 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| 翻译 | Stay Hungry. Stay Foolish. |
114 |
115 | ---
116 |
117 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
118 | >
119 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
120 | >
121 | > 文档永久地址: https://d.laravel-china.org
122 |
--------------------------------------------------------------------------------
/views.md:
--------------------------------------------------------------------------------
1 | # Laravel 的视图
2 |
3 | - [创建视图](#creating-views)
4 | - [向视图传递数据](#passing-data-to-views)
5 | - [与所有视图共享数据](#sharing-data-with-all-views)
6 | - [视图合成器](#view-composers)
7 |
8 |
9 | ## 创建视图
10 |
11 | > {tip} 想寻找有关如何编写 Blade 模板的更多信息?查看完整的 [Blade 文档](/docs/{{version}}/blade)。
12 |
13 | 视图包含应用程序的 HTML,并且将控制器/应用程序逻辑与演示逻辑分开。视图文件存放于 `resources/views` 目录下。一个简单的视图如下所示:
14 |
15 |
16 |
17 |
18 |
19 | Hello, {{ $name }}
20 |
21 |
22 |
23 | 该视图文件位于 `resources/views/greeting.blade.php`,使用全局辅助函数 `view` 来返回:
24 |
25 | Route::get('/', function () {
26 | return view('greeting', ['name' => 'James']);
27 | });
28 |
29 | 如你所见,`view` 函数中,传入的第一个参数对应着 `resources/views` 目录中视图文件的名称,第二个参数是可在视图文件中使用的数据数组。在示例中,我们传递 `name` 变量,该变量可以使用 [Blade 模板语言](/docs/{{version}}/blade) 在视图中显示。
30 |
31 | 当然,视图文件也可以嵌套在 `resources/views` 目录的子目录中。「点」符号可以用来引用嵌套视图。例如,如果你的视图存储在 `resources/views/admin/profile.blade.php`,则可以这样引用它:
32 |
33 | return view('admin.profile', $data);
34 |
35 | #### 判断视图文件是否存在
36 |
37 | 如果需要判断视图文件是否存在,可以使用 `View` Facade 上的 `exists` 方法。如果视图文件存在,该方法会返回 `true` :
38 |
39 | use Illuminate\Support\Facades\View;
40 |
41 | if (View::exists('emails.customer')) {
42 | //
43 | }
44 |
45 |
46 | ## 向视图传递数据
47 |
48 | 如上述例子所示,你可以使用数组将数据传递到视图:
49 |
50 | return view('greetings', ['name' => 'Victoria']);
51 | 当用这种方式传递数据时,作为第二个参数的数据必须是键值对数组。在视图文件中,你可以通过对应的键获取相应的值,例如 ``。作为将完整数据传递给辅助函数 `view` 的替代方法,你可以使用 `with` 方法将单个数据片段添加到视图:
52 |
53 | return view('greeting')->with('name', 'Victoria');
54 |
55 |
56 | #### 与所有视图共享数据
57 |
58 | 如果需要共享一段数据给应用程序的所有视图,你可以在服务提供器的 `boot` 方法中调用视图 Facade 的 `share` 方法。例如,可以将它们添加到 `AppServiceProvider` 或者为它们生成一个单独的服务提供器:
59 |
60 |
90 | ## 视图合成器
91 |
92 | 视图合成器是在渲染视图时调用的回调或者类方法。如果你每次渲染视图时都要绑定视图的数据,视图合成器可以帮你将这些逻辑整理到特定的位置。
93 |
94 | 在下面这个例子中,我们会在一个 [服务提供器](/docs/{{version}}/providers) 中注册视图合成器,使用 `View` Facade 来访问底层的 `Illuminate\Contracts\View\Factory` 契约实现。默认情况下,Laravel 没有存放视图合成器的目录,你需要根据喜好来重新建立目录,例如:`App\Http\ViewComposers`。
95 |
96 | {note} 注意,如果你创建了新的一个服务提供器来存放你注册视图合成器的代码,那么你需要将这个服务提供器添加到配置文件 `config/app.php` 的 `providers` 数组中。
135 |
136 | 到此我们已经注册了视图合成器,每次渲染 `profile` 视图时都会执行 `ProfileComposer@compose` 方法。那么下面我们来定义视图合成器的这个类吧:
137 |
138 | users = $users;
164 | }
165 |
166 | /**
167 | * 将数据绑定到视图。
168 | *
169 | * @param View $view
170 | * @return void
171 | */
172 | public function compose(View $view)
173 | {
174 | $view->with('count', $this->users->count());
175 | }
176 | }
177 |
178 | 视图合成器的 `compose` 方法会在视图渲染之前被调用,并传入一个 `Illuminate\View\View` 实例。你可以使用 `with` 方法将数据绑定到视图。
179 |
180 | > {tip} 所有的视图合成器都会通过 [服务容器](/docs/{{version}}/container) 进行解析,所以你可以在视图合成器的构造函数中类型提示需要注入的依赖项。
181 |
182 | #### 将视图构造器添加到多个视图
183 |
184 | 通过将一组视图作为第一个参数传入 `composer` 方法,将一个视图合成器添加到多个视图:
185 |
186 | View::composer(
187 | ['profile', 'dashboard'],
188 | 'App\Http\ViewComposers\MyViewComposer'
189 | );
190 |
191 | `composer` 方法同时也接受通配符 `*`,表示将一个视图合成器添加到所有视图:
192 |
193 | View::composer('*', function ($view) {
194 | //
195 | });
196 |
197 | #### 视图构造器
198 |
199 | 视图**构造器**和视图合成器非常相似。唯一不同之处在于:视图构造器在视图实例化之后立即执行,而视图合成器在视图即将渲染时执行。使用 `creator` 方法注册视图构造器:
200 |
201 | View::creator('profile', 'App\Http\ViewCreators\ProfileCreator');
202 |
203 | ## 译者署名
204 |
205 | | 用户名 | 头像 | 职能 | 签名 |
206 | |---|---|---|---|
207 | | [@JokerLinly](https://laravel-china.org/users/5350) |
| Review | Stay Hungry. Stay Foolish. |
208 | | [@shamiao](https://laravel-china.org/users/7034) |
| 修正 | Make developers great again. |
209 |
210 | ---
211 |
212 | > {note} 欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
213 | >
214 | > 转载请注明:本文档由 Laravel China 社区 [laravel-china.org](https://laravel-china.org) 组织翻译,详见 [翻译召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
215 | >
216 | > 文档永久地址: https://d.laravel-china.org
217 |
--------------------------------------------------------------------------------