symfony 소스 코드 분석의 프레임 워 크 메 인 프로 세 스
프레임 메 인 프로 세 스
용기 생 성 및 사용
경로 생 성
소스 코드 를 분석 할 때 phopstrom 을 사용 하여 xdebug 확장 에 맞 춰 정지점 디 버 깅 을 하여 코드 분석 과 정리 에 큰 도움 이 되 었 습 니 다.
1 호출 과정
web/app.php
$kernel = new AppKernel('prod', false);
$response = $kernel->handle($request);
Symfony\Component\HttpKernel\Kernel
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
if (false === $this->booted) {
// Bundle
$this->boot();
}
// Symfony\Component\HttpKernel\HttpKernel handle
return $this->getHttpKernel()->handle($request, $type, $catch);
}
Symfony\Component\HttpKernel\HttpKernel
private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
{
$this->requestStack->push($request);
//
$event = new GetResponseEvent($this, $request, $type);
$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
//
if (false === $controller = $this->resolver->getController($request)) {
throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo()));
}
//
$event = new FilterControllerEvent($this, $controller, $request, $type);
$this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event);
$controller = $event->getController();
//
$arguments = $this->argumentResolver->getArguments($request, $controller);
//
$event = new FilterControllerArgumentsEvent($this, $controller, $arguments, $request, $type);
$this->dispatcher->dispatch(KernelEvents::CONTROLLER_ARGUMENTS, $event);
$controller = $event->getController();
$arguments = $event->getArguments();
// call controller
//
$response = call_user_func_array($controller, $arguments);
if (!$response instanceof Response) {
// Response view
}
return $this->filterResponse($response, $request, $type);
}
2 주류 프로 세 스 분석
주류 프로 세 스 코드 를 간소화 하고 사건 위임 코드 를 무시 하 며 절 차 는 다음 과 같다.
// 1.
$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
// 2.
$controller = $this->resolver->getController($request)
// 3.
$arguments = $this->argumentResolver->getArguments($request, $controller);
// 4.
$response = call_user_func_array($controller, $arguments);
2.1 일치 경로 조회 에 필요 한 컨트롤 러
여 기 는 이벤트 KernelEvents::REQUEST 를 촉발 합 니 다.이 이벤트 의 handler:Symfony\Component\\HttpKernel\\EventListener\RouterListener 는 경로,컨트롤 러 에 대한 분석 조 회 를 실 시 했 습 니 다.경로 가 생 성 되 지 않 으 면 경로 코드 를 생 성 할 수 있 습 니 다.
# Symfony\Component\HttpKernel\EventListener\RouterListener
public function onKernelRequest(GetResponseEvent $event)
{
//
if ($request->attributes->has('_controller')) {
return;
}
try {
if ($this->matcher instanceof RequestMatcherInterface) {
//
$parameters = $this->matcher->matchRequest($request);
} else {
$parameters = $this->matcher->match($request->getPathInfo());
}
// request attributes
// $parameters = [
// '_controller' => " :: ",
// '_route' =''
// ]
$request->attributes->add($parameters);
unset($parameters['_route'], $parameters['_controller']);
$request->attributes->set('_route_params', $parameters);
} catch (ResourceNotFoundException $e) {
// ......
} catch (MethodNotAllowedException $e) {
// ......
}
}
경로 가 일치 하 는 코드 분석,프레임 워 크 는 경로 정 보 를 분석 하여 캐 시 파일 var/prod/apProd Project Container UrlMatcher.php 에 저장 합 니 다.구체 적 인 경로 생 성 코드 는 루트 코드 생 성 분석 구체 적 으로 살펴보다
# Symfony\Bundle\FrameworkBundle\Routing\Router
public function getRouteCollection()
{
if (null === $this->collection) {
// routing.loader load
// Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader::load
//
// $this->resource -> app/config/routing.yml
// $this->options['resource_type'] -> null
$this->collection = $this->container->get('routing.loader')->load($this->resource, $this->options['resource_type']);
$this->resolveParameters($this->collection);
$this->collection->addResource(new ContainerParametersResource($this->collectedParameters));
}
return $this->collection;
}
# Syfmony\Component\Routing\Router\Router
public function matchRequest(Request $request)
{
$matcher = $this->getMatcher();
if (!$matcher instanceof RequestMatcherInterface) {
// fallback to the default UrlMatcherInterface
return $matcher->match($request->getPathInfo());
}
return $matcher->matchRequest($request);
}
public function getMatcher()
{
// $this->getConfigCacheFactory() -> Symfony\Component\Config\ResourceCheckerConfigCacheFactory
// var/prod/appProdProjectContainerUrlMatcher.php
$cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['matcher_cache_class'].'.php',
// ,
function (ConfigCacheInterface $cache) {
// ......
}
);
// var/cache/dev/app[ENV]DebugProjectContainerUrlMatcher.php
require_once $cache->getPath();
return $this->matcher = new $this->options['matcher_cache_class']($this->context);
}
2.2 컨트롤 러 의 인 스 턴 스 와 실행 할 방법 가 져 오기
이 코드 의 호출 은 다음 과 같 습 니 다.
Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver extends
Symfony\Component\HttpKernel\Controller\ContainerControllerResolver extends
Symfony\Component\HttpKernel\Controller\ControllerResolver
최종 실 행 된 핵심 코드 는 다음 과 같 습 니 다.
# Symfony\Component\HttpKernel\Controller\ControllerResolver
public function getController(Request $request)
{
// $controller $request attributes , KernelEvents::CONTROLLER handler RouterListener
//
if (!$controller = $request->attributes->get('_controller')) {
if (null !== $this->logger) {
$this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
}
return false;
}
if (is_array($controller)) {
return $controller;
}
if (is_object($controller)) {
if (method_exists($controller, '__invoke')) {
return $controller;
}
throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo()));
}
if (false === strpos($controller, ':')) {
if (method_exists($controller, '__invoke')) {
return $this->instantiateController($controller);
} elseif (function_exists($controller)) {
return $controller;
}
}
$callable = $this->createController($controller);
if (!is_callable($callable)) {
throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable)));
}
return $callable;
}
이상 코드 의 핵심 세 션 은$controller=$request->attributes->get('controller')
2.3 컨트롤 러 가 실행 할 방법 에 대해 반사 적 으로 방법 에 필요 한 인 자 를 얻 고 용 기 를 통 해 실례 화 된 대상 을 되 돌려 줍 니 다.
컨트롤 러 방법 중의 매개 변수 처리 핵심 코드 는 다음 과 같다.
# Symfony\Component\HttpKernel\Controller\ArgumentResolver
public function getArguments(Request $request, $controller)
{
$arguments = array();
// , Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata
foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) {
// argument resolver
foreach ($this->argumentValueResolvers as $resolver) {
if (!$resolver->supports($request, $metadata)) {
continue;
}
$resolved = $resolver->resolve($request, $metadata);
if (!$resolved instanceof \Generator) {
throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', get_class($resolver)));
}
//$resolver Generator yield
foreach ($resolved as $append) {
$arguments[] = $append;
}
// continue to the next controller argument
continue 2; //
}
$representative = $controller;
if (is_array($representative)) {
$representative = sprintf('%s::%s()', get_class($representative[0]), $representative[1]);
} elseif (is_object($representative)) {
$representative = get_class($representative);
}
throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName()));
}
return $arguments;
}
public static function getDefaultArgumentValueResolvers()
{
return array(
new RequestAttributeValueResolver(),
new RequestValueResolver(),
new SessionValueResolver(),
new DefaultValueResolver(),
new VariadicValueResolver(),
);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Symfony - API-플랫폼 설치 후 웹 페이지 드롭 오류설치하고 버전 4.4로 만든 후 웹 페이지를 열면 오류가 발생합니다. 그리고 디버깅 모드를 활성화 시켜도 제대로 된 에러메세지가 안나와서 짜증나네요.... Passt에서 다음을 실행할 때 더 자세한 오류 메시지가 표...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.