Saya telah menulis posting blog yang lebih menyeluruh dan diperbarui tentang topik ini: http://elnur.pro/symfony-without-bundles/
Tidak, tidak semuanya harus dalam satu bundel. Anda dapat memiliki struktur seperti ini:
src/Vendor/Model
- untuk model,
src/Vendor/Controller
- untuk pengontrol,
src/Vendor/Service
- untuk layanan,
src/Vendor/Bundle
- untuk bundel, seperti src/Vendor/Bundle/AppBundle
,
- dll.
Dengan cara ini, Anda hanya akan memasukkan AppBundle
hal-hal yang benar-benar spesifik untuk Symfony2. Jika Anda memutuskan untuk beralih ke kerangka kerja lain nanti, Anda akan menyingkirkan Bundle
namespace dan menggantinya dengan hal-hal kerangka kerja yang dipilih.
Harap perhatikan bahwa yang saya sarankan di sini adalah untuk kode khusus aplikasi . Untuk bundel yang dapat digunakan kembali, saya masih menyarankan menggunakan praktik terbaik .
Menjaga entitas dari bundel
Untuk menjaga entitas di src/Vendor/Model
luar bundel apa pun, saya telah mengubah doctrine
bagian config.yml
dari
doctrine:
# ...
orm:
# ...
auto_mapping: true
untuk
doctrine:
# ...
orm:
# ...
mappings:
model:
type: annotation
dir: %kernel.root_dir%/../src/Vendor/Model
prefix: Vendor\Model
alias: Model
is_bundle: false
Nama-nama entitas - untuk diakses dari repositori Doktrin - mulai dengan Model
dalam kasus ini, misalnya Model:User
,.
Anda dapat menggunakan subnamespaces untuk mengelompokkan entitas terkait bersama, misalnya src/Vendor/User/Group.php
,. Dalam hal ini, nama entitas adalah Model:User\Group
.
Menghindari pengontrol dari bundel
Pertama, Anda perlu memberi tahu JMSDiExtraBundle untuk memindai src
folder untuk layanan dengan menambahkan ini ke config.yml
:
jms_di_extra:
locations:
directories: %kernel.root_dir%/../src
Kemudian Anda mendefinisikan pengontrol sebagai layanan dan menempatkannya di bawah Controller
namespace:
<?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
];
}
}
Perhatikan bahwa saya menggunakan ElnurAbstractControllerBundle saya untuk menyederhanakan mendefinisikan pengontrol sebagai layanan.
Hal terakhir yang tersisa adalah memberi tahu Symfony untuk mencari templat tanpa bundel. Saya melakukan ini dengan mengesampingkan layanan penebak template, tetapi karena pendekatannya berbeda antara Symfony 2.0 dan 2.1, saya menyediakan versi untuk keduanya.
Mengganti penebak templat Symfony 2.1+
Saya telah membuat bundel yang melakukan itu untuk Anda.
Mengganti pendengar template Symfony 2.0
Pertama, tentukan kelasnya:
<?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;
}
}
}
Dan kemudian beri tahu Symfony untuk menggunakannya dengan menambahkan ini ke config.yml
:
parameters:
jms_di_extra.template_listener.class: Vendor\Listener\TemplateListener
Menggunakan templat tanpa bundel
Sekarang, Anda dapat menggunakan templat dari bundel. Simpan di bawah app/Resources/views
folder. Misalnya, templat untuk dua tindakan dari contoh controller di atas berada di:
app/Resources/views/User/add.html.twig
app/Resources/views/User/profile.html.twig
Saat merujuk ke templat, cukup abaikan bagian bundel:
{% include ':Controller:view.html.twig' %}