이 주제에 대해 더 철저하고 업데이트 된 블로그 게시물을 작성했습니다 : http://elnur.pro/symfony-without-bundles/
아니요, 모든 것이 번들로 제공 될 필요는 없습니다. 다음과 같은 구조를 가질 수 있습니다.
src/Vendor/Model
— 모델의 경우
src/Vendor/Controller
— 컨트롤러 용
src/Vendor/Service
— 서비스,
src/Vendor/Bundle
—와 같은 번들의 src/Vendor/Bundle/AppBundle
경우
- 기타
이런 식으로, 당신 AppBundle
은 실제로 Symfony2에만 해당되는 것들을 넣을 것입니다. 나중에 다른 프레임 워크로 전환하기로 결정한 경우 Bundle
네임 스페이스를 제거 하고 선택한 프레임 워크로 바꿉니다.
여기서 제안하는 것은 앱 특정 코드를 위한 것 입니다. 재사용 가능한 번들의 경우 여전히 모범 사례를 사용 하는 것이 좋습니다 .
엔티티를 번들에서 제외
엔티티를 src/Vendor/Model
번들 외부에 유지하기 위해 doctrine
섹션 config.yml
을
doctrine:
# ...
orm:
# ...
auto_mapping: true
에
doctrine:
# ...
orm:
# ...
mappings:
model:
type: annotation
dir: %kernel.root_dir%/../src/Vendor/Model
prefix: Vendor\Model
alias: Model
is_bundle: false
Doctrine 저장소에서 액세스 할 수있는 엔티티 이름 Model
은이 경우로 시작 합니다 (예 :) Model:User
.
하위 네임 스페이스를 사용하여 관련 엔터티를 함께 그룹화 할 수 있습니다 (예 :) src/Vendor/User/Group.php
. 이 경우 엔터티 이름은 Model:User\Group
입니다.
컨트롤러를 번들에서 제외
먼저 다음을 추가하여 JMSDiExtraBundlesrc
에 서비스 의 폴더 를 스캔하도록 지시 해야 합니다 config.yml
.
jms_di_extra:
locations:
directories: %kernel.root_dir%/../src
그런 다음 컨트롤러를 서비스로 정의 하고 Controller
네임 스페이스 아래에 배치하십시오 .
<?php
namespace Vendor\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Elnur\AbstractControllerBundle\AbstractController;
use Vendor\Service\UserService;
use Vendor\Model\User;
/**
* @Service("user_controller", parent="elnur.controller.abstract")
* @Route(service="user_controller")
*/
class UserController extends AbstractController
{
/**
* @var UserService
*/
private $userService;
/**
* @InjectParams
*
* @param UserService $userService
*/
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
/**
* @Route("/user/add", name="user.add")
* @Template
* @Secure("ROLE_ADMIN")
*
* @param Request $request
* @return array
*/
public function addAction(Request $request)
{
$user = new User;
$form = $this->formFactory->create('user', $user);
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$this->userService->save($user);
$request->getSession()->getFlashBag()->add('success', 'user.add.success');
return new RedirectResponse($this->router->generate('user.list'));
}
}
return ['form' => $form->createView()];
}
/**
* @Route("/user/profile", name="user.profile")
* @Template
* @Secure("ROLE_USER")
*
* @param Request $request
* @return array
*/
public function profileAction(Request $request)
{
$user = $this->getCurrentUser();
$form = $this->formFactory->create('user_profile', $user);
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$this->userService->save($user);
$request->getSession()->getFlashBag()->add('success', 'user.profile.edit.success');
return new RedirectResponse($this->router->generate('user.view', [
'username' => $user->getUsername()
]));
}
}
return [
'form' => $form->createView(),
'user' => $user
];
}
}
컨트롤러를 서비스로 정의하는 것을 단순화하기 위해 ElnurAbstractControllerBundle 을 사용 하고 있습니다.
마지막으로 남은 것은 번들없이 템플릿을 찾도록 Symfony에 알리는 것입니다. 템플릿 추측 서비스를 재정 의하여이 작업을 수행하지만 Symfony 2.0과 2.1의 접근 방식이 다르기 때문에 두 가지 버전을 모두 제공하고 있습니다.
Symfony 2.1 이상 템플릿 추측 자 재정의
나는 당신을 위해 번들 을 만들었습니다 .
Symfony 2.0 템플리트 리스너 대체
먼저 클래스를 정의하십시오.
<?php
namespace Vendor\Listener;
use InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener as FrameworkExtraTemplateListener;
use JMS\DiExtraBundle\Annotation\Service;
class TemplateListener extends FrameworkExtraTemplateListener
{
/**
* @param array $controller
* @param Request $request
* @param string $engine
* @throws InvalidArgumentException
* @return TemplateReference
*/
public function guessTemplateName($controller, Request $request, $engine = 'twig')
{
if (!preg_match('/Controller\\\(.+)Controller$/', get_class($controller[0]), $matchController)) {
throw new InvalidArgumentException(sprintf('The "%s" class does not look like a controller class (it must be in a "Controller" sub-namespace and the class name must end with "Controller")', get_class($controller[0])));
}
if (!preg_match('/^(.+)Action$/', $controller[1], $matchAction)) {
throw new InvalidArgumentException(sprintf('The "%s" method does not look like an action method (it does not end with Action)', $controller[1]));
}
$bundle = $this->getBundleForClass(get_class($controller[0]));
return new TemplateReference(
$bundle ? $bundle->getName() : null,
$matchController[1],
$matchAction[1],
$request->getRequestFormat(),
$engine
);
}
/**
* @param string $class
* @return Bundle
*/
protected function getBundleForClass($class)
{
try {
return parent::getBundleForClass($class);
} catch (InvalidArgumentException $e) {
return null;
}
}
}
그리고 Symfony에게 다음을 추가하여 사용하도록 지시하십시오 config.yml
.
parameters:
jms_di_extra.template_listener.class: Vendor\Listener\TemplateListener
번들없이 템플릿 사용
이제 번들에서 템플릿을 사용할 수 있습니다. app/Resources/views
폴더 아래에 보관하십시오 . 예를 들어 위의 예제 컨트롤러에서이 두 작업에 대한 템플릿은 다음 위치에 있습니다.
app/Resources/views/User/add.html.twig
app/Resources/views/User/profile.html.twig
템플릿을 참조 할 때는 번들 부분을 생략하십시오.
{% include ':Controller:view.html.twig' %}