入门laravel
初始化流程
http 的初始化
引入composer的autoload
实例化Applocation(初始化ioc容器,application本身就是ioc容器。并且注册本身到自己的ioc容器中。注册基础的服务提供者【并且执行服务提供者的register和boot方法】。注册一些类别名到ioc容器)
注册Http的Kernel到ioc容器
从make中去除kernel(实例化了kernel,kernel调用了一些bootstrap的类来初始化一些系统功能【门面注册,内容提供者注册--app.php中配置的那些】,调用application的boot方法等)
捕获Request
发送response(Symfony\Component\HttpFoundation\Response)
console 的初始化
几个重要的系统定义初始化的值
Illuminate\Foundation\Http\Kernel $bootstrappers 初始化一些系统的必须类 包括下面的几个类 (都有bootstrap()方法 初始化了系统绝大多数东西)
protected $bootstrappers = [
'Illuminate\Foundation\Bootstrap\DetectEnvironment',
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
'Illuminate\Foundation\Bootstrap\ConfigureLogging',
'Illuminate\Foundation\Bootstrap\HandleExceptions',
//初始化门面
'Illuminate\Foundation\Bootstrap\RegisterFacades',
//初始化内容提供者
'Illuminate\Foundation\Bootstrap\RegisterProviders',
//调用Applocation实例到ioc容器中
'Illuminate\Foundation\Bootstrap\BootProviders',
];
application 注册核心的别名到ioc容器中 契约以及契约的实现类
public function registerCoreContainerAliases()
{
$aliases = [
'app' => ['Illuminate\Foundation\Application', 'Illuminate\Contracts\Container\Container', 'Illuminate\Contracts\Foundation\Application'],
'auth' => ['Illuminate\Auth\AuthManager', 'Illuminate\Contracts\Auth\Factory'],
'auth.driver' => ['Illuminate\Contracts\Auth\Guard'],
'blade.compiler' => ['Illuminate\View\Compilers\BladeCompiler'],
'cache' => ['Illuminate\Cache\CacheManager', 'Illuminate\Contracts\Cache\Factory'],
'cache.store' => ['Illuminate\Cache\Repository', 'Illuminate\Contracts\Cache\Repository'],
'config' => ['Illuminate\Config\Repository', 'Illuminate\Contracts\Config\Repository'],
'cookie' => ['Illuminate\Cookie\CookieJar', 'Illuminate\Contracts\Cookie\Factory', 'Illuminate\Contracts\Cookie\QueueingFactory'],
'encrypter' => ['Illuminate\Encryption\Encrypter', 'Illuminate\Contracts\Encryption\Encrypter'],
'db' => ['Illuminate\Database\DatabaseManager'],
'db.connection' => ['Illuminate\Database\Connection', 'Illuminate\Database\ConnectionInterface'],
'events' => ['Illuminate\Events\Dispatcher', 'Illuminate\Contracts\Events\Dispatcher'],
'files' => ['Illuminate\Filesystem\Filesystem'],
'filesystem' => ['Illuminate\Filesystem\FilesystemManager', 'Illuminate\Contracts\Filesystem\Factory'],
'filesystem.disk' => ['Illuminate\Contracts\Filesystem\Filesystem'],
'filesystem.cloud' => ['Illuminate\Contracts\Filesystem\Cloud'],
'hash' => ['Illuminate\Contracts\Hashing\Hasher'],
'translator' => ['Illuminate\Translation\Translator', 'Symfony\Component\Translation\TranslatorInterface'],
'log' => ['Illuminate\Log\Writer', 'Illuminate\Contracts\Logging\Log', 'Psr\Log\LoggerInterface'],
'mailer' => ['Illuminate\Mail\Mailer', 'Illuminate\Contracts\Mail\Mailer', 'Illuminate\Contracts\Mail\MailQueue'],
'auth.password' => ['Illuminate\Auth\Passwords\PasswordBrokerManager', 'Illuminate\Contracts\Auth\PasswordBrokerFactory'],
'auth.password.broker' => ['Illuminate\Auth\Passwords\PasswordBroker', 'Illuminate\Contracts\Auth\PasswordBroker'],
'queue' => ['Illuminate\Queue\QueueManager', 'Illuminate\Contracts\Queue\Factory', 'Illuminate\Contracts\Queue\Monitor'],
'queue.connection' => ['Illuminate\Contracts\Queue\Queue'],
'queue.failer' => ['Illuminate\Queue\Failed\FailedJobProviderInterface'],
'redirect' => ['Illuminate\Routing\Redirector'],
'redis' => ['Illuminate\Redis\Database', 'Illuminate\Contracts\Redis\Database'],
'request' => ['Illuminate\Http\Request', 'Symfony\Component\HttpFoundation\Request'],
'router' => ['Illuminate\Routing\Router', 'Illuminate\Contracts\Routing\Registrar'],
'session' => ['Illuminate\Session\SessionManager'],
'session.store' => ['Illuminate\Session\Store', 'Symfony\Component\HttpFoundation\Session\SessionInterface'],
'url' => ['Illuminate\Routing\UrlGenerator', 'Illuminate\Contracts\Routing\UrlGenerator'],
'validator' => ['Illuminate\Validation\Factory', 'Illuminate\Contracts\Validation\Factory'],
'view' => ['Illuminate\View\Factory', 'Illuminate\Contracts\View\Factory'],
];
foreach ($aliases as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}
app.php 配置文件中的aliases 就是吧对应的类设置别名(通过AliasLoad 去找到类【prependToLoaderStack】注册了门面的autoload)
需要知道的知识
类:Closure
这个是一个回调函数的具体类
方法 bind(Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
bindto(object $newthis [, mixed $newscope = 'static' ])
bind:将回调函数绑定到一个具体的类 $newthis(这个绑定之后才有上下文)
$newscope 代表的是这个类的作用域(即回调函数能访问这个作用域【类】中的成员变量 也可以是一个命名空间加类名的字符串)
即 $newthis是绑定上下文 $newscope取得上下文的变量
bindTo 参数如上
static::class --> 返回的是php这个类的域名以及类名的全部string
callable 标示一个可以调用的类型
接口:ArrayAccess:让类可以像数组一样的进行使用
//laravel的基础类
Macroable:实现了一个注册callable类型就可以添加到类中的trait
applocatin 分析
Applocation 类继承了接口:
IApplication, HttpKernelInterface
,继承了类Container
- Application 接口
interface Application extends Container
{
/**
* 获取laravel的版本
* @return string
*/
public function version();
/**
* 获取laravel框架的基本路径(项目根目录)
* @return string
*/
public function basePath();
/**
* 取得环境
* @return string
*/
public function environment();
/**
* 判断框架是否是在维护
* @return bool
*/
public function isDownForMaintenance();
/**
* 注册所有的配置提供者
* @return void
*/
public function registerConfiguredProviders();
/**
* 注册服务提供者到applocation中 并且调用服务的register方法
* @param \Illuminate\Support\ServiceProvider|string $provider
* @param array $options
* @param bool $force
* @return \Illuminate\Support\ServiceProvider
*/
public function register($provider, $options = [], $force = false);
/**
*注册一个延迟的服务提供者(如果已经有注册服务的话就从deferredServices中unset服务 然后在调用register方法注册服务)
* @param string $provider
* @param string $service
* @return void
*/
public function registerDeferredProvider($provider, $service = null);
/**
* 调用所有的boot的callback并且吧所有注册的服务提供者都调用boot方法
* @return void
*/
public function boot();
/**
* 注册一个boot(框架启动的回调函数)
*
* @param mixed $callback
* @return void
*/
public function booting($callback);
/**
* 注册一个框架启动完成之后的回调函数
*
* @param mixed $callback
* @return void
*/
public function booted($callback);
/**
* Get the path to the cached "compiled.php" file.
*
* @return string
*/
public function getCachedCompilePath();
/**
* Get the path to the cached services.php file.
*
* @return string
*/
public function getCachedServicesPath();
}
//http接口
interface HttpKernelInterface
{
const MASTER_REQUEST = 1;
const SUB_REQUEST = 2;
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
}
//依赖注入容器
interface Container
{
/**
* Determine if the given abstract type has been bound.
*
* @param string $abstract
* @return bool
*/
public function bound($abstract);
/**
* Alias a type to a different name.
*
* @param string $abstract
* @param string $alias
* @return void
*/
public function alias($abstract, $alias);
/**
* Assign a set of tags to a given binding.
*
* @param array|string $abstracts
* @param array|mixed ...$tags
* @return void
*/
public function tag($abstracts, $tags);
/**
* Resolve all of the bindings for a given tag.
*
* @param array $tag
* @return array
*/
public function tagged($tag);
/**
* Register a binding with the container.
*
* @param string|array $abstract
* @param \Closure|string|null $concrete
* @param bool $shared
* @return void
*/
public function bind($abstract, $concrete = null, $shared = false);
/**
* Register a binding if it hasn't already been registered.
*
* @param string $abstract
* @param \Closure|string|null $concrete
* @param bool $shared
* @return void
*/
public function bindIf($abstract, $concrete = null, $shared = false);
/**
* Register a shared binding in the container.
*
* @param string|array $abstract
* @param \Closure|string|null $concrete
* @return void
*/
public function singleton($abstract, $concrete = null);
/**
* "Extend" an abstract type in the container.
*
* @param string $abstract
* @param \Closure $closure
* @return void
*
* @throws \InvalidArgumentException
*/
public function extend($abstract, Closure $closure);
/**
* Register an existing instance as shared in the container.
*
* @param string $abstract
* @param mixed $instance
* @return void
*/
public function instance($abstract, $instance);
/**
* Define a contextual binding.
*
* @param string $concrete
* @return \Illuminate\Contracts\Container\ContextualBindingBuilder
*/
public function when($concrete);
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
public function make($abstract, array $parameters = []);
/**
* Call the given Closure / class@method and inject its dependencies.
*
* @param callable|string $callback
* @param array $parameters
* @param string|null $defaultMethod
* @return mixed
*/
public function call($callback, array $parameters = [], $defaultMethod = null);
/**
* Determine if the given abstract type has been resolved.
*
* @param string $abstract
* @return bool
*/
public function resolved($abstract);
/**
* Register a new resolving callback.
*
* @param string $abstract
* @param \Closure|null $callback
* @return void
*/
public function resolving($abstract, Closure $callback = null);
/**
* Register a new after resolving callback.
*
* @param string $abstract
* @param \Closure|null $callback
* @return void
*/
public function afterResolving($abstract, Closure $callback = null);
}
- 通过
Illuminate\Config\Repository
读取配置文件的数据
apploction 初始化注册的的基础服务和基础容器
- 基础服务
//事件服务
class EventServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->singleton('events', function ($app) {
return (new Dispatcher($app))->setQueueResolver(function () use ($app) {
return $app->make('Illuminate\Contracts\Queue\Factory');
});
});
}
}
//路由服务
class RoutingServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerRouter();
$this->registerUrlGenerator();
$this->registerRedirector();
$this->registerPsrRequest();
$this->registerPsrResponse();
$this->registerResponseFactory();
}
}
主要关注 EventServiceProvider
核心概念
依赖注入
依赖注入接口
//Application 是这个接口的子类
<?php
namespace Illuminate\Contracts\Container;
use Closure;
interface Container
{
//判断是不是存在这个ioc
public function bound($abstract);
public function alias($abstract, $alias);
public function tag($abstracts, $tags);
public function tagged($tag);
public function bind($abstract, $concrete = null, $shared = false);
public function bindIf($abstract, $concrete = null, $shared = false);
public function singleton($abstract, $concrete = null);
public function extend($abstract, Closure $closure);
public function instance($abstract, $instance);
public function when($concrete);
public function make($abstract, array $parameters = []);
public function call($callback, array $parameters = [], $defaultMethod = null);
public function resolved($abstract);
public function resolving($abstract, Closure $callback = null);
public function afterResolving($abstract, Closure $callback = null);
}
依赖注入的一些类型
- 注册单例
- 注册别名
服务提供者
服务提供者是一个在框架运行流程中可以注册到框架的applocation中 然后有两个主要的方法
1. register
2. boot
执行顺序 register->boot
app.php配置文件中有许多初始化的服务提供者
系统的启动也是这些提供者提供的
门面
门面抽象类中的getFacadeAccessor()方法(重载) 就是用来获取ioc容器中alias别名容器中对应的【契约=》类】;
//门面就是一个注册函数或者对象到类中 之后可以通过__callStatic 来访问这些方法
// 使得很多注册的门面可以直接通过static的方式进行访问
//门面类
namespace Illuminate\Support\Facades;
abstract class Facade
//门面注册类 (在application中进行了执行)
namespace Illuminate\Foundation\Bootstrap;
class RegisterFacades
主要使用(http)
路由
控制器
abstract class Controller
{
/**
* The middleware registered on the controller.
*
* @var array
*/
protected $middleware = [];
/**
* Register middleware on the controller. 注册一个中间件
*
* @param array|string|\Closure $middleware
* @param array $options
* @return \Illuminate\Routing\ControllerMiddlewareOptions
*/
public function middleware($middleware, array $options = [])
{
foreach ((array) $middleware as $m) {
$this->middleware[] = [
'middleware' => $m,
'options' => &$options,
];
}
return new ControllerMiddlewareOptions($options);
}
/**
* Get the middleware assigned to the controller. 获取注册到控制器的中间件
*
* @return array
*/
public function getMiddleware()
{
return $this->middleware;
}
/**
* Execute an action on the controller. 调用控制器的方法
*
* @param string $method
* @param array $parameters
* @return \Symfony\Component\HttpFoundation\Response
*/
public function callAction($method, $parameters)
{
return call_user_func_array([$this, $method], $parameters);
}
/**
* Handle calls to missing methods on the controller. 调用控制器没有的方法抛出异常
*
* @param array $parameters
* @return mixed
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
*/
public function missingMethod($parameters = [])
{
throw new NotFoundHttpException('Controller method not found.');
}
/**
* Handle calls to missing methods on the controller. 调用未知方法直接抛出异常
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
throw new BadMethodCallException("Method [{$method}] does not exist.");
}
}
中间件
用来过滤请求 然后可以对请求进行处理
比如 验证 跳转 过滤
php artisan make:middleware CheckAge 可以直接生成中间件
- 普通中间件(中间件前)
class CheckAge
{
public function handle($request, Closure $next)
{
return $next($request);
}
}
- 后置中间件
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// 执行动作
return $response;
}
}