面向 WEB 工匠的 PHP 框架。

注意:本文档只摘取 Laravel 官方文档 的部分常用功能。框架功能庞大,但我们通常只会用到其中很小的一部分。

入门

安装

通过 Composer 安装

  1. composer create-project laravel/laravel example-app
  2. cd example-app
  3. php artisan serve

一旦您启动了 Artisan 开发服务器,您就可以在 http://localhost:8000 进行访问。

目录结构

  1. ├── app // 应用程序
  2. | ├── Broadcasting // 广播
  3. | ├── Console // Artisan命令
  4. | ├── Events // 事件
  5. | ├── Exceptions // 异常
  6. | ├── Http // 请求
  7. | ├── Jobs // 队列
  8. | ├── Listeners // 事件监听
  9. | ├── Mail // 电子邮件
  10. | ├── Models // Eloquent模型
  11. | ├── Notifications // 消息通知
  12. | ├── Policies // 授权策略
  13. | ├── Providers // 服务提供者
  14. | └── Rules // 验证规则
  15. ├── bootstrap // 引导程序
  16. ├── config // 配置文件
  17. ├── database // 数据库
  18. ├── lang // 语言包
  19. ├── public // 公共目录
  20. ├── resources // 静态资源
  21. ├── routes // 路由
  22. ├── storage // 存储生成文件
  23. ├── tests // 自动化测试
  24. ├── vendor // Composer包

部署

服务器要求

  • PHP >= 8.0
  • BCMath PHP 扩展
  • Ctype PHP 扩展
  • cURL PHP 扩展
  • DOM PHP 扩展
  • Fileinfo PHP 扩展
  • JSON PHP 扩展
  • Mbstring PHP 扩展
  • OpenSSL PHP 扩展
  • PCRE PHP 扩展
  • PDO PHP 扩展
  • Tokenizer PHP 扩展
  • XML PHP 扩展

服务器配置
Nginx

  1. server {
  2. listen 80;
  3. listen [::]:80;
  4. server_name example.com;
  5. root /srv/example.com/public;
  6. add_header X-Frame-Options "SAMEORIGIN";
  7. add_header X-Content-Type-Options "nosniff";
  8. index index.php;
  9. charset utf-8;
  10. location / {
  11. try_files $uri $uri/ /index.php?$query_string;
  12. }
  13. location = /favicon.ico { access_log off; log_not_found off; }
  14. location = /robots.txt { access_log off; log_not_found off; }
  15. error_page 404 /index.php;
  16. location ~ \.php$ {
  17. fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
  18. fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
  19. include fastcgi_params;
  20. }
  21. location ~ /\.(?!well-known).* {
  22. deny all;
  23. }
  24. }

优化
优化自动加载
Composer 的类自动加载器映射,以便 Composer 可以快速找到要为给定类加载的正确文件。

  1. composer install --optimize-autoloader --no-dev

优化配置加载
所有配置文件合并到一个缓存文件中,减少框架在加载配置值时必须访问文件系统的次数。

  1. php artisan config:cache

优化路由加载
所有路由注册减少到缓存文件中的单个方法调用中,从而在注册数百条路由时提高路由注册的性能。

  1. php artisan route:cache

优化视图加载
预编译所有 Blade 视图,因此它们不会按需编译,从而提高每个返回视图的请求的性能。

  1. php artisan view:cache

关闭调试模式
在生产环境中,APP_DEBUG 应该始终为 false

核心架构

请求生命周期

737276-20181005182255861-926106710.png
下面对应的代码,解释上图。

  1. // 文件路径:public/index.php
  2. /**
  3. * 定义框架启动时间
  4. */
  5. define('LARAVEL_START', microtime(true));
  6. /**
  7. * 检查应用程序是否处于维护模式
  8. */
  9. if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
  10. require $maintenance;
  11. }
  12. /**
  13. * 注册自动加载
  14. */
  15. require __DIR__.'/../vendor/autoload.php';
  16. /**
  17. * 运行应用程序
  18. */
  19. $app = require_once __DIR__.'/../bootstrap/app.php';
  20. $kernel = $app->make(Kernel::class);
  21. $response = $kernel->handle(
  22. $request = Request::capture()
  23. )->send();
  24. $kernel->terminate($request, $response);
  1. // 文件路径:bootstrap/app.php
  2. /**
  3. * 创建应用程序
  4. */
  5. $app = new Illuminate\Foundation\Application(
  6. $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
  7. );
  8. /**
  9. * 绑定内核
  10. */
  11. $app->singleton(
  12. Illuminate\Contracts\Http\Kernel::class,
  13. App\Http\Kernel::class
  14. );
  15. $app->singleton(
  16. Illuminate\Contracts\Console\Kernel::class,
  17. App\Console\Kernel::class
  18. );
  19. $app->singleton(
  20. Illuminate\Contracts\Debug\ExceptionHandler::class,
  21. App\Exceptions\Handler::class
  22. );
  23. /**
  24. * 返回应用程序
  25. */
  26. return $app;
  1. // 文件路径:vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php
  2. class Kernel implements KernelContract
  3. {
  4. protected $bootstrappers = [
  5. \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, // 注册应用环境配置
  6. \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, // 注册应用配置
  7. \Illuminate\Foundation\Bootstrap\HandleExceptions::class, // 注册异常
  8. \Illuminate\Foundation\Bootstrap\RegisterFacades::class, // 注册门面模式
  9. \Illuminate\Foundation\Bootstrap\RegisterProviders::class, // 注册服务提供者
  10. \Illuminate\Foundation\Bootstrap\BootProviders::class, // 注册引导程序
  11. ];
  12. /**
  13. * 处理请求
  14. */
  15. public function handle($request)
  16. {
  17. try {
  18. $request->enableHttpMethodParameterOverride();
  19. $response = $this->sendRequestThroughRouter($request);
  20. } catch (Throwable $e) {
  21. $this->reportException($e);
  22. $response = $this->renderException($request, $e);
  23. }
  24. $this->app['events']->dispatch(
  25. new RequestHandled($request, $response)
  26. );
  27. return $response;
  28. }
  29. /**
  30. * 通过中间件/路由发送请求
  31. */
  32. protected function sendRequestThroughRouter($request)
  33. {
  34. $this->app->instance('request', $request);
  35. Facade::clearResolvedInstance('request');
  36. $this->bootstrap();
  37. return (new Pipeline($this->app))
  38. ->send($request)
  39. ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
  40. ->then($this->dispatchToRouter());
  41. }
  42. /**
  43. * 引导应用程序
  44. *
  45. * @return void
  46. */
  47. public function bootstrap()
  48. {
  49. if (! $this->app->hasBeenBootstrapped()) {
  50. $this->app->bootstrapWith($this->bootstrappers());
  51. }
  52. }
  53. /**
  54. * 路由分发
  55. */
  56. protected function dispatchToRouter()
  57. {
  58. return function ($request) {
  59. $this->app->instance('request', $request);
  60. return $this->router->dispatch($request);
  61. };
  62. }
  63. /**
  64. * 终止应用程序
  65. */
  66. public function terminate($request, $response)
  67. {
  68. $this->terminateMiddleware($request, $response);
  69. $this->app->terminate();
  70. }
  71. }

服务容器

服务容器是管理类依赖和执行依赖注入的强大工具。依赖注入是一个花哨的短语,本质上是这样的:类依赖通过构造函数或在某些情况下的“setter”方法“注入”到类中。
让我们看一个简单的例子:

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Controllers\Controller;
  4. use App\Repositories\UserRepository;
  5. use App\Models\User;
  6. class UserController extends Controller
  7. {
  8. /**
  9. * 用户存储库实现
  10. *
  11. * @var UserRepository
  12. */
  13. protected $users;
  14. /**
  15. * 创建一个新的控制器实例
  16. *
  17. * @param UserRepository $users
  18. * @return void
  19. */
  20. public function __construct(UserRepository $users)
  21. {
  22. $this->users = $users;
  23. }
  24. /**
  25. * 显示给定用户的信息
  26. *
  27. * @param int $id
  28. * @return Response
  29. */
  30. public function show($id)
  31. {
  32. $user = $this->users->find($id);
  33. return view('user.profile', ['user' => $user]);
  34. }
  35. }

绑定
几乎所有服务容器绑定都会在 服务提供者 中注册。在服务提供者中,您始终可以通过 $this->app 属性访问容器。我们可以使用 bind 方法注册绑定,bind 方法的第一个参数为要绑定的类或接口名称,第二个参数是一个返回类实例的闭包:

  1. // 简单绑定
  2. $this->app->bind(Transistor::class, function ($app) {
  3. return new Transistor($app->make(PodcastParser::class));
  4. });
  5. // 绑定单例
  6. $this->app->singleton(Transistor::class, function ($app) {
  7. return new Transistor($app->make(PodcastParser::class));
  8. });
  9. // 绑定作用域单例
  10. $this->app->scoped(Transistor::class, function ($app) {
  11. return new Transistor($app->make(PodcastParser::class));
  12. });
  13. // 绑定实例
  14. $service = new Transistor(new PodcastParser);
  15. $this->app->instance(Transistor::class, $service);
  16. // 绑定接口到实现
  17. $this->app->bind(EventPusher::class, RedisEventPusher::class);
  18. // 绑定上下文
  19. $this->app->when(PhotoController::class)
  20. ->needs(Filesystem::class)
  21. ->give(function () {
  22. return Storage::disk('local');
  23. });
  24. // 绑定原语
  25. $this->app->when('App\Http\Controllers\UserController')
  26. ->needs('$variableName')
  27. ->give($value);
  28. // 绑定扩展
  29. $this->app->extend(Service::class, function ($service, $app) {
  30. return new DecoratedService($service);
  31. });

解析
您可以使用 make 方法从容器中解析类实例。make 方法接受您希望解析的类或接口的名称:

  1. $transistor = $this->app->make(Transistor::class);

容器事件
服务容器每次解析对象时都会触发一个事件。您可以使用 resolving 方法侦听此事件:

  1. $this->app->resolving(Transistor::class, function ($transistor, $app) {
  2. // 当容器解析 "Transistor" 类型的对象时调用...
  3. });
  4. $this->app->resolving(function ($object, $app) {
  5. // 当容器解析任何类型的对象时调用...
  6. });

服务提供者

服务提供者是所有 Laravel 应用程序的引导中心。您自己的应用程序,以及 Laravel 的所有核心服务,都是通过服务提供者引导的。
“引导”可以理解为注册,包括注册服务容器绑定、事件监听器、中间件,甚至路由。
如果您打开 Laravel 的 config/app.php 文件时,您会看到一个 providers 数组。这些是应用程序加载的所有服务提供者类。默认情况下,数组中列出了一组 Laravel 核心服务提供者。这些提供者引导 Laravel 核心组件,例如邮件、队列、缓存等。其中许多是“延迟”提供者,这意味着它们不会在每个请求上加载,而只会在实际需要它们提供服务时加载。
编写服务提供者
所有服务提供者都会继承 Illuminate\Support\ServiceProvider 类。大多数服务提供者都包含一个 register 和一个 boot 方法。在 register 方法中,您应该只将服务绑定到 服务容器 中。您永远不应该尝试在 register 方法中注册任何事件侦听器、路由或任何其他功能。
Artisan CLI 可以通过 make:provider 命令生成新的提供者:

  1. php artisan make:provider RiakServiceProvider

注册方法

  1. <?php
  2. namespace App\Providers;
  3. use App\Services\Riak\Connection;
  4. use Illuminate\Support\ServiceProvider;
  5. class RiakServiceProvider extends ServiceProvider
  6. {
  7. /**
  8. * 注册任何应用程序服务
  9. *
  10. * @return void
  11. */
  12. public function register()
  13. {
  14. $this->app->singleton(Connection::class, function ($app) {
  15. return new Connection(config('riak'));
  16. });
  17. }
  18. }

引导方法

  1. <?php
  2. namespace App\Providers;
  3. use Illuminate\Support\Facades\View;
  4. use Illuminate\Support\ServiceProvider;
  5. class ComposerServiceProvider extends ServiceProvider
  6. {
  7. /**
  8. * 引导任何应用程序服务
  9. *
  10. * @return void
  11. */
  12. public function boot()
  13. {
  14. View::composer('view', function () {
  15. //
  16. });
  17. }
  18. }

注册服务提供者
所有服务提供者都在 config/app.php 配置文件中注册。

  1. 'providers' => [
  2. // 其他服务提供者
  3. App\Providers\ComposerServiceProvider::class,
  4. ],

延迟服务提供者
延迟加载服务提供者将提高应用程序的性能,因为它不是在每次请求时都从文件系统加载的。
要延迟加载提供者,需要实现 \Illuminate\Contracts\Support\DeferrableProvider 接口并定义 provides 方法。provides 方法应返回提供者注册的服务容器绑定:

  1. <?php
  2. namespace App\Providers;
  3. use App\Services\Riak\Connection;
  4. use Illuminate\Contracts\Support\DeferrableProvider;
  5. use Illuminate\Support\ServiceProvider;
  6. class RiakServiceProvider extends ServiceProvider implements DeferrableProvider
  7. {
  8. /**
  9. * 注册任何应用程序服务
  10. *
  11. * @return void
  12. */
  13. public function register()
  14. {
  15. $this->app->singleton(Connection::class, function ($app) {
  16. return new Connection($app['config']['riak']);
  17. });
  18. }
  19. /**
  20. * 获取提供者提供的服务
  21. *
  22. * @return array
  23. */
  24. public function provides()
  25. {
  26. return [Connection::class];
  27. }
  28. }

Facades

Laravel Facades 充当服务容器中底层类的“静态代理”,提供简洁、富有表现力的语法,同时保持比传统静态方法更多的可测试性和灵活性。
Facades Vs. 依赖注入
依赖注入的主要好处之一是能够交换注入类的实现。这在测试期间很有用,因为您可以注入 mockstub 并断言在 stub 上调用了各种方法。

  1. use Illuminate\Support\Facades\Cache;
  2. Route::get('/cache', function () {
  3. return Cache::get('key');
  4. });

使用 Laravel Facades 测试方法,我们可以编写以下测试来验证 Cache::get 方法是否使用我们期望的参数调用:

  1. use Illuminate\Support\Facades\Cache;
  2. /**
  3. * 一个基本的功能测试示例
  4. *
  5. * @return void
  6. */
  7. public function testBasicExample()
  8. {
  9. Cache::shouldReceive('get')
  10. ->with('key')
  11. ->andReturn('value');
  12. $response = $this->get('/cache');
  13. $response->assertSee('value');
  14. }

Facades Vs. 辅助函数
除了 Facades 之外,Laravel 还包括各种辅助函数,它们可以执行常见任务,例如生成视图、触发事件、调度作业或发送 HTTP 响应。许多辅助函数执行与对应 Facades 具有相同的作用。
Facades 工作原理
Facades 是一个提供从容器访问对象的类。Facade 基类 Illuminate\Support\Facades\Facade 使用 __callStatic() 魔术方法将来自 Facade 的调用推迟到从容器解析出对象后。
下面的示例中,调用了 Laravel 缓存系统。看一眼这段代码,人们可能会认为 get 正在 Cache 类上调用静态方法:

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Controllers\Controller;
  4. use Illuminate\Support\Facades\Cache;
  5. class UserController extends Controller
  6. {
  7. /**
  8. * 显示给定用户的信息
  9. *
  10. * @param int $id
  11. * @return Response
  12. */
  13. public function showProfile($id)
  14. {
  15. $user = Cache::get('user:'.$id);
  16. return view('profile', ['user' => $user]);
  17. }
  18. }

请注意,在文件顶部附近,我们正在导入了 Cache Facade 。这个 Facade 充当访问Illuminate\Contracts\Cache\Factory 接口底层实现的代理。我们使用 Facade 进行的任何调用都将传递给 Laravel 缓存服务的底层实例。
如果我们查看 Illuminate\Support\Facades\Cache 类,您会发现没有静态方法 get

  1. class Cache extends Facade
  2. {
  3. /**
  4. * 获取组件的注册名称
  5. *
  6. * @return string
  7. */
  8. protected static function getFacadeAccessor() { return 'cache'; }
  9. }

相反,Cache Facade 继承了 Facade 基类并定义了 getFacadeAccessor() 方法。此方法的工作是返回服务容器绑定的名称。当用户引用 Cache Facade 上的任何静态方法时,Laravel 会从 服务容器 解析绑定 cache 并针对该对象运行请求的方法(在本例中为 get 方法)。
实时 Facades
使用实时 Facade,您可以将应用程序中的任何类视为 Facade。
要生成实时 Facade,请在导入类的命名空间前加上 Facades

  1. <?php
  2. namespace App\Models;
  3. use Facades\App\Contracts\Publisher;
  4. use Illuminate\Database\Eloquent\Model;
  5. class Podcast extends Model
  6. {
  7. /**
  8. * 发布 podcast
  9. *
  10. * @return void
  11. */
  12. public function publish()
  13. {
  14. $this->update(['publishing' => now()]);
  15. Publisher::publish($this);
  16. }
  17. }

当使用实时 Facade 时,publisher 实现将使用出现在 Facades 前缀之后的接口或类名部分从服务容器中解析出来。
Facade 类参考
您将在下面找到每个 Facade 类及其底层类。这是一个有用的工具,可以快速查找 Facade 类的 API 文档。而且还包括 服务容器绑定

Facade 服务容器绑定
App Illuminate\Foundation\Application app
Artisan Illuminate\Contracts\Console\Kernel artisan
Auth Illuminate\Auth\AuthManager auth
Auth (Instance) Illuminate\Contracts\Auth\Guard auth.driver
Blade Illuminate\View\Compilers\BladeCompiler blade.compiler
Broadcast Illuminate\Contracts\Broadcasting\Factory
Broadcast (Instance) Illuminate\Contracts\Broadcasting\Broadcaster
Bus Illuminate\Contracts\Bus\Dispatcher
Cache Illuminate\Cache\CacheManager cache
Cache (Instance) Illuminate\Cache\Repository cache.store
Config Illuminate\Config\Repository config
Cookie Illuminate\Cookie\CookieJar cookie
Crypt Illuminate\Encryption\Encrypter encrypter
Date Illuminate\Support\DateFactory date
DB Illuminate\Database\DatabaseManager db
DB (Instance) Illuminate\Database\Connection db.connection
Event Illuminate\Events\Dispatcher events
File Illuminate\Filesystem\Filesystem files
Gate Illuminate\Contracts\Auth\Access\Gate
Hash Illuminate\Contracts\Hashing\Hasher hash
Http Illuminate\Http\Client\Factory
Lang Illuminate\Translation\Translator translator
Log Illuminate\Log\LogManager log
Mail Illuminate\Mail\Mailer mailer
Notification Illuminate\Notifications\ChannelManager
Password Illuminate\Auth\Passwords\PasswordBrokerManager auth.password
Password (Instance) Illuminate\Auth\Passwords\PasswordBroker auth.password.broker
Queue Illuminate\Queue\QueueManager queue
Queue (Instance) Illuminate\Contracts\Queue\Queue queue.connection
Queue (Base Class) Illuminate\Queue\Queue
Redirect Illuminate\Routing\Redirector redirect
Redis Illuminate\Redis\RedisManager redis
Redis (Instance) Illuminate\Redis\Connections\Connection redis.connection
Request Illuminate\Http\Request request
Response Illuminate\Contracts\Routing\ResponseFactory
Response (Instance) Illuminate\Http\Response
Route Illuminate\Routing\Router router
Schema Illuminate\Database\Schema\Builder
Session Illuminate\Session\SessionManager session
Session (Instance) Illuminate\Session\Store session.store
Storage Illuminate\Filesystem\FilesystemManager filesystem
Storage (Instance) Illuminate\Contracts\Filesystem\Filesystem filesystem.disk
URL Illuminate\Routing\UrlGenerator url
Validator Illuminate\Validation\Factory validator
Validator (Instance) Illuminate\Validation\Validator
View Illuminate\View\Factory view
View (Instance) Illuminate\View\View

基础功能

路由

基本路由

  1. Route::get('/users', [UserController::class, 'index']);

可用的路由方法:

  1. Route::get($uri, $callback);
  2. Route::post($uri, $callback);
  3. Route::put($uri, $callback);
  4. Route::patch($uri, $callback);
  5. Route::delete($uri, $callback);
  6. Route::options($uri, $callback);

路由参数

  1. Route::get('/users/{id}', [UserController::class, 'show']);

全局约束:

  1. // 文件路径:app\Providers\RouteServiceProvider.php
  2. public function boot()
  3. {
  4. Route::pattern('id', '[0-9]+');
  5. }

路由命名

  1. Route::get('/users/{id}', [UserController::class, 'show'])->name('users.show');

路由分组

  1. Route::middleware('auth')->group(function () {
  2. Route::get('/users', [UserController::class, 'index']);
  3. Route::get('/users/{id}', [UserController::class, 'show']);
  4. });

路由前缀:

  1. Route::prefix('admin')->group(function () {
  2. Route::get('/users', [UserController::class, 'index']);
  3. });

中间件

中间件提供了一种方便的机制来检查和过滤进入应用程序的 HTTP 请求。所有中间件都位于 app/Http/Middleware 目录中。
定义中间件
要创建新的中间件,请使用 make:middleware Artisan 命令:

  1. php artisan make:middleware EnsureTokenIsValid

注册中间件

  1. // 文件路径:app/Http/Kernel.php
  2. /**
  3. * 全局中间件
  4. */
  5. protected $middleware = [
  6. // \App\Http\Middleware\TrustHosts::class,
  7. \App\Http\Middleware\TrustProxies::class,
  8. \Illuminate\Http\Middleware\HandleCors::class,
  9. \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
  10. \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
  11. \App\Http\Middleware\TrimStrings::class,
  12. \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
  13. ];
  14. /**
  15. * 中间件组
  16. */
  17. protected $middlewareGroups = [
  18. 'web' => [
  19. \App\Http\Middleware\EncryptCookies::class,
  20. \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
  21. \Illuminate\Session\Middleware\StartSession::class,
  22. \Illuminate\View\Middleware\ShareErrorsFromSession::class,
  23. \App\Http\Middleware\VerifyCsrfToken::class,
  24. \Illuminate\Routing\Middleware\SubstituteBindings::class,
  25. ],
  26. 'api' => [
  27. // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
  28. 'throttle:api',
  29. \Illuminate\Routing\Middleware\SubstituteBindings::class,
  30. ],
  31. ];
  32. /**
  33. * 路由中间件
  34. */
  35. protected $routeMiddleware = [
  36. 'auth' => \App\Http\Middleware\Authenticate::class,
  37. 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
  38. 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
  39. 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
  40. 'can' => \Illuminate\Auth\Middleware\Authorize::class,
  41. 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
  42. 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
  43. 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
  44. 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
  45. 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
  46. ];

控制器

控制器可以将相关的请求处理逻辑分组到一个类中。例如,一个 UserController 类可能会处理所有与用户相关的传入请求,包括显示、创建、更新和删除用户。默认情况下,控制器存储在 app/Http/Controllers 目录中。
编写控制器

  1. php artisan make:controller UserController
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Controllers\Controller;
  4. class UserController extends Controller
  5. {
  6. }

资源控制器

  1. php artisan make:controller UserController --resource

资源控制器处理的动作:

Verb URI Action Route Name
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy

请求

Laravel 的 Illuminate\Http\Request 类提供了一种面向对象的方式来与您的应用程序正在处理的当前 HTTP 请求进行交互,并检索与请求一起提交的输入、cookie 和文件。
请求交互
通过依赖注入获取当前 HTTP 请求的实例。

  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. class UserController extends Controller
  5. {
  6. /**
  7. * 存储一个新用户
  8. *
  9. * @param \Illuminate\Http\Request $request
  10. * @return \Illuminate\Http\Response
  11. */
  12. public function store(Request $request)
  13. {
  14. $name = $request->input('name');
  15. //
  16. }
  17. }

输入

  1. // 检索所有输入数据
  2. $input = $request->all();
  3. // 检索输入值
  4. $name = $request->input('name', 'Sally');
  5. // 检索Json输入值
  6. $name = $request->input('user.name');

文件

  1. $file = $request->file('photo');
  2. $file = $request->photo;
  3. $path = $request->photo->store('images');
  4. $path = $request->photo->store('images', 's3');

响应

  1. return response()->json([
  2. 'name' => 'Abigail',
  3. 'state' => 'CA',
  4. ]);

重定向:

  1. return redirect()->route('login');

文件:

  1. // 文件下载
  2. return response()->download($pathToFile);
  3. // 文件显示
  4. return response()->file($pathToFile);

验证

Laravel 提供了几种不同的方法来验证应用程序的传入数据。最常见的方法是对所有传入的 HTTP 请求使用 validate 方法。

  1. php artisan make:request StorePostRequest
  1. /**
  2. * 获取应用请求的验证规则
  3. *
  4. * @return array
  5. */
  6. public function rules()
  7. {
  8. return [
  9. 'title' => 'required|unique:posts|max:255',
  10. 'body' => 'required',
  11. ];
  12. }
  13. /**
  14. * 获取验证规则的错误消息
  15. *
  16. * @return array
  17. */
  18. public function messages()
  19. {
  20. return [
  21. 'title.required' => 'A title is required',
  22. 'body.required' => 'A message is required',
  23. ];
  24. }
  1. /**
  2. * 存储一篇新的博客文章
  3. *
  4. * @param \App\Http\Requests\StorePostRequest $request
  5. * @return Illuminate\Http\Response
  6. */
  7. public function store(StorePostRequest $request)
  8. {
  9. $validated = $request->validated();
  10. }

错误处理

app\Exceptions\Handler 类是记录应用程序抛出的所有异常然后呈现给用户。

日志记录

Laravel 日志记录基于“通道”。每个通道代表一种写入日志信息的特定方式。例如,single 通道将日志文件写入单个日志文件,而 slack 通道将日志消息发送到 Slack。日志消息可以根据其严重性写入多个通道。
配置

  1. 'stack' => [
  2. 'driver' => 'stack',
  3. 'name' => 'channel-name',
  4. 'channels' => ['single', 'slack'],
  5. ],

日志级别
提供 RFC 5424 规范 中定义的所有日志级别:emergencyalertcriticalerrorwarningnoticeinfodebug

  1. Log::emergency($message);
  2. Log::alert($message);
  3. Log::critical($message);
  4. Log::error($message);
  5. Log::warning($message);
  6. Log::notice($message);
  7. Log::info($message);
  8. Log::debug($message);

继续深入

Artisan 命令行

Artisan 作为脚本存在于应用程序的根目录中,并提供了许多有用的 artisan 命令,可以在您构建应用程序时为您提供帮助。
编写命令

  1. php artisan make:command SendEmails
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Models\User;
  4. use App\Support\DripEmailer;
  5. use Illuminate\Console\Command;
  6. class SendEmails extends Command
  7. {
  8. /**
  9. * 命令的名称和签名
  10. *
  11. * @var string
  12. */
  13. protected $signature = 'mail:send {user}';
  14. /**
  15. * 命令描述
  16. *
  17. * @var string
  18. */
  19. protected $description = 'Send a marketing email to a user';
  20. /**
  21. * 执行命令
  22. *
  23. * @param \App\Support\DripEmailer $drip
  24. * @return mixed
  25. */
  26. public function handle(DripEmailer $drip)
  27. {
  28. $drip->send(User::find($this->argument('user')));
  29. }
  30. }

缓存

Laravel 为各种缓存后端提供了一个富有表现力的统一 API,允许您利用它们超快的数据检索并加速您的 Web 应用程序。
配置
缓存配置文件位于 config/cache.php。在此文件中,您可以指定您希望在整个应用程序中默认使用的缓存驱动程序。
使用

  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Support\Facades\Cache;
  4. class UserController extends Controller
  5. {
  6. /**
  7. * 显示所有用户列表
  8. *
  9. * @return Response
  10. */
  11. public function index()
  12. {
  13. $value = Cache::get('key');
  14. }
  15. }
  1. // 检索
  2. Cache::get('key');
  3. Cache::get('key', 'default');
  4. // 存储
  5. Cache::put('key');
  6. Cache::put('key', 'value');
  7. // 删除
  8. Cache::forget('key');
  9. // 助手
  10. cache('key');

集合

Illuminate\Support\Collection 类为处理数据数组提供了一个流畅、方便的包装器。

  1. $collection = collect([1, 2, 3]);

事件

Laravel 的事件提供了一个简单的观察者模式实现,允许你订阅和监听应用程序中发生的各种事件。事件类通常存储在 app/Events 目录中,而它们的侦听器存储在 app/Listeners

文件存储

Laravel 提供了强大的文件系统抽象,得益于 Frank de Jonge 的 Flysystem 扩展包。

辅助函数

Laravel 包含各种全局 PHP“辅助”函数。

HTTP 客户端

Laravel 围绕 Guzzle HTTP 客户端 提供了一个富有表现力的最小 API ,允许您快速发出 HTTP 请求与其他 Web 应用程序通信。

扩展包开发

包是向 Laravel 添加功能的主要方式。
包发现
在 Laravel 应用程序的 config/app.php 配置文件中,providers 选项定义了 Laravel 应该加载的服务提供者列表。

  1. "extra": {
  2. "laravel": {
  3. "providers": [
  4. "Barryvdh\\Debugbar\\ServiceProvider"
  5. ],
  6. "aliases": {
  7. "Debugbar": "Barryvdh\\Debugbar\\Facade"
  8. }
  9. }
  10. },

队列

通过将时间密集型任务移到队列中,您的应用程序可以以极快的速度响应 Web 请求,并为您的客户提供更好的用户体验。

  1. use App\Jobs\ProcessPodcast;
  2. // This job is sent to the default connection's default queue...
  3. ProcessPodcast::dispatch();
  4. // This job is sent to the default connection's "emails" queue...
  5. ProcessPodcast::dispatch()->onQueue('emails');
  1. php artisan queue:work

创建任务

  1. php artisan make:job ProcessPodcast

分发任务

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Controllers\Controller;
  4. use App\Jobs\ProcessPodcast;
  5. use App\Models\Podcast;
  6. use Illuminate\Http\Request;
  7. class PodcastController extends Controller
  8. {
  9. /**
  10. * Store a new podcast.
  11. *
  12. * @param \Illuminate\Http\Request $request
  13. * @return \Illuminate\Http\Response
  14. */
  15. public function store(Request $request)
  16. {
  17. $podcast = Podcast::create(/* ... */);
  18. // ...
  19. ProcessPodcast::dispatch($podcast);
  20. }
  21. }

任务批处理

  1. use App\Jobs\OptimizePodcast;
  2. use App\Jobs\ProcessPodcast;
  3. use App\Jobs\ReleasePodcast;
  4. use Illuminate\Support\Facades\Bus;
  5. Bus::chain([
  6. new ProcessPodcast,
  7. new OptimizePodcast,
  8. new ReleasePodcast,
  9. ])->dispatch();

任务调度

Laravel 的命令调度器提供了一种全新的方法来管理服务器上的计划任务。
定义计划任务
您可以在 app\Console\Kernel 类的 schedule 方法中定义所有计划任务。

  1. <?php
  2. namespace App\Console;
  3. use Illuminate\Console\Scheduling\Schedule;
  4. use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
  5. use Illuminate\Support\Facades\DB;
  6. class Kernel extends ConsoleKernel
  7. {
  8. /**
  9. * Define the application's command schedule.
  10. *
  11. * @param \Illuminate\Console\Scheduling\Schedule $schedule
  12. * @return void
  13. */
  14. protected function schedule(Schedule $schedule)
  15. {
  16. $schedule->call(function () {
  17. DB::table('recent_users')->delete();
  18. })->daily();
  19. }
  20. }

安全

验证

一种使用应用程序进行身份验证和“登录”的方式。

授权

一种简单的方法来授权用户对给定资源的操作。

加密

通过 OpenSSL 使用 AES-256 和 AES-128 来加密和解密文本。

哈希

提供了安全的 Bcrypt 和 Argon2 哈希来存储用户密码。

重置密码

提供了一种重置忘记密码的方法。

数据库

入门

读写分离

  1. 'mysql' => [
  2. 'read' => [
  3. 'host' => [
  4. '192.168.1.1',
  5. '196.168.1.2',
  6. ],
  7. ],
  8. 'write' => [
  9. 'host' => [
  10. '196.168.1.3',
  11. ],
  12. ],
  13. 'sticky' => true,
  14. 'driver' => 'mysql',
  15. 'database' => 'database',
  16. 'username' => 'root',
  17. 'password' => '',
  18. 'charset' => 'utf8mb4',
  19. 'collation' => 'utf8mb4_unicode_ci',
  20. 'prefix' => '',
  21. ],

分页

迁移

数据库的版本控制。
生成迁移

  1. php artisan make:migration create_flights_table

迁移结构
一个迁移类包含两个方法:updownup 方法用于向数据库添加新表、列或索引,而 down 方法用于撤销 up 方法执行的操作。

  1. <?php
  2. use Illuminate\Database\Migrations\Migration;
  3. use Illuminate\Database\Schema\Blueprint;
  4. use Illuminate\Support\Facades\Schema;
  5. return new class extends Migration
  6. {
  7. /**
  8. * Run the migrations.
  9. *
  10. * @return void
  11. */
  12. public function up()
  13. {
  14. Schema::create('flights', function (Blueprint $table) {
  15. $table->id();
  16. $table->string('name');
  17. $table->string('airline');
  18. $table->timestamps();
  19. });
  20. }
  21. /**
  22. * Reverse the migrations.
  23. *
  24. * @return void
  25. */
  26. public function down()
  27. {
  28. Schema::drop('flights');
  29. }
  30. };

运行迁移

  1. php artisan migrate

回滚迁移

  1. php artisan migrate:rollback

数据填充

使用seed类为数据库填充数据的能力。

Redis

Eloquent ORM

入门

这是一个对象关系映射器 (ORM),使用 Eloquent 时,每个数据库表都有一个对应的“模型”,用于与该表进行交互。
生成模型类

  1. php artisan make:model Flight

关系

集合

属性修改器

API 资源

序列化

测试

入门

HTTP 测试

命令行测试

浏览器测试

数据库测试

模拟测试

官方扩展包