Normally, for a Silex project, I would have top-level directories like:
- app/
- views/
- src/
- vendor/
- web/
Now, some of my classes may call $app['twig']->render(...) and it will pull out a view from the app/views folder.
If I extract a library to be more reusable, across multiple projects, where should I keep its view files, and how do I instruct Twig to look there?
The same question applies to graphics/stylesheets, etc which I would normally put in web/.
Surely they have to be within vendor/my-lib somewhere to allow Composer to cleanly install the files? Is there a common/best-practice way to do this?
Update
For reference, here's what I ended up doing:
<?php
// in my \Silex\ServiceProviderInterface ...
/**
* #var \Twig_Environment $twig
*/
$twig = $app['twig'];
// Add the paths to our twig templates here
$fsLoader = new \Twig_Loader_Filesystem(array(
__DIR__.'/views/'
));
$twig->setLoader(new \Twig_Loader_Chain(array($twig->getLoader(), $fsLoader)));
Thanks.
I store the views under src/{Library}/{Class}/View/
I set the base path of Twig to the src
$app->register(new TwigServiceProvider(), array(
'twig.path' => array(
__DIR__ . '/../src/{Library}/'
),
'twig.options' => array('cache' => false, 'strict_variables' => true)
));
and when calling render I pass in the path from that point
$app['twig']->render('{Class}/View/{twigfile}.html.twig',$data);
Related
I'd like to structure a Symfony3 Bundle into submodules.
For this I would like to move the Bundle/Resources folder (with views, config and public) along with the controller classes into a subfolder.
Example with a DemoBundle and the Messages module. The directory should be like this:
+ DemoBundle
+ Directory
+ Posts
+ Messages
+ Controller
+ MessageController.php
+ Resources
+ config
+ public
+ views
+ listing.html.twig
I could move the Controller by making an entry to the routing.yml file like this:
demo-messages:
resource: "#DemoBundle/Messages/Controller/"
type: annotation
prefix: /
The Controller now looks like this:
class MessageController extends Controller {
/**
* #Route("/messsages", name="Message")
*/
public function listingAction(Request $request) {
return $this->render('listing.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
]);
}
}
When I now navigate to this route, I get an error: "Unable to find template". The error says it is still looking in /demo/Resources/views instead of /demo/messages/Resources/views.
Question: Can I somehow tell symfony to look in the folder /demo/messages/Resources/views? Is that possible at all? Or is my template addressing in $this->render(...) wrong?
So far tried the following versions for the template reference:
return $this->render('messages/listing.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
]);
Effect: Error: Template not found
~~~
return $this->render('#DemoBundle/Messages/Resources/views/listing.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
]);
Works!
The reason I chose this structure over a Bundle for each submodule is that i would like to encapsulate the user interface in this Bundle while i'd like to organize the admin interface in the AdminBundle.
Cerads solution with namespaced template references helped. The following code worked:
return $this->render('#DemoBundle/Messages/Resources/views/listing.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
]);
Drawbacks with this workaround are that the short hand template reference is not possible any more and that the copying of the assets (CSS, JS, etc.) doesn't work with php bin/console assets:install
I have a quite big project that I need to program. I used to code with CodeIgniter but since they stopped maintaining the framework, I decided to switch to another. I chose Phalcon framework. The folder structure of the application that I want to implement is next:
app/
controllers/
admin/
users/
UsersController.php
UserGroupsController.php
dashboard/
system/
another_subfolder/
AnotherSubFolderController.php
production/
settings/
SettingsController.php
dashboard/
flow/
another_subfolder/
AnotherSubFolderController.php
website1/
customers/
CustomersController.php
CompaniesController.php
another_subfolder .... /
models/
sub_folder_structure/ // The same as controllers
This is just example of the folder structure of the application. There will be quite a lot of folders and sub-folders in this project to make it manageable.
From my understanding I need to register all namespaces at the loader for each sub-folder, so that Phalcon knows where to search and load the class.
//Register an autoloader
$loader = new \Phalcon\Loader();
$loader->registerNamespaces(array(
// Main
'Controllers' =>'app/controllers/',
'Models' =>'app/models/',
// Admin Routing
'Controllers\Admin'=>'app/controllers/admin',
'Models\Admin'=>'app/models/admin',
'Controllers\Admin'=>'app/controllers/admin',
'Models\Admin'=>'app/models/admin',
'Controllers\Admin\Users'=>'app/controllers/admin/users',
'Models\Admin\Users'=>'app/models/admin/users'
))->register();
The loader will look quite big.
Then I have to set-up the router so that requests redirected to the right controller. Right now I have next:
// Setup Router
$di->set('router', function(){
$router = new \Phalcon\Mvc\Router(false);
$router->removeExtraSlashes(true);
$router->add('/', array(
'namespace' => 'Controllers',
'controller' => "login"
));
$router->add('/:controller/:action/', array(
'namespace' => 'Controllers',
'controller' => 1,
'action' =>2
));
$router->add('/admin/:controller/:action/', array(
'namespace' => 'Controllers\Admin',
'controller' => 1,
'action' =>2
));
$router->add('/admin/users/:controller/:action/', array(
'namespace' => 'Controllers\Admin\Users',
'controller' => 1,
'action' =>2
));
return $router;
});
That will be also very big if I need to manually setup router for each sub-folder and namespace.
So the questions that I have are this:
Is there any way to make a loader prettier and smaller? As it will grow bigger.
How can I setup router so that I don't need to enter all of the namespaces and combinations of subfolders? Is there any way to make it smaller? May be modify dispatcher or any other class? Or is there a way I can set a path variable in the router to the location of the controller?
I have researched Phalcon documentation but could not find the way to do that.
Any help and suggestions are very much appreciated.
Thanks
Ad. 1. You can change your namespaces to be more PSR-0 (in my opinion), so I would make:
app
controllers
Admin
Users
UsersController.php
The you can register one namespace Admin or any other. Then you need to register only the top most namespace to work (keep in mind that your UsersController must have namespace Admin\Users\UsersController; to work). Thena autoloader should have only:
$loader
->registerDirs(
array(
// It's taken from my config so path may be different
__DIR__ . '/../../app/controllers/'
// other namespaces here (like for models)
)
);
I'm using registerDirs so I only point loader to the folder in which some namespace exists.
Ad. 2.
For this you can use groups of routes so you can pass a namespace as a parameter for config array of constructor and then do the repeative task in one place. Then just create new instances with different parameters;
$router->addGroup(new MahGroup(array('namespace' => 'Mah\\Controller'));
So inside MahGroup class could be:
class MahGroup extends Phalcon\Mvc\Router\Group {
public function _construct($config = array()) {
$this->setPrefix('/' . $config['perfix']);
$router->add('/:controller/:action/', array(
'namespace' => $config['namespace'],
'controller' => 1,
'action' => 2
));
// etc...
}
}
And then configuring routes:
$router->addGroup( new MahGroup(array('prefix' => 'mah-namespace', 'namespace' => 'Mah\\Namespace' )) );
$router->addGroup( new MahGroup(array('prefix' => 'mah-other-namespace', 'namespace' => 'Mah\\Other\\Namespace' )) );
But given examples for second question are just what could be done. I usually create Group class for each namespace and then declare some routes that my app uses since I'm not using english names for routes and I need rewriting polish urls to controllers which have also some namespaces.
So I've been reading a ton of stackoverflow and phalcon forum threads.. (I'm starting to hate this framework), but nothing seem to work and it doesn't explain why like Laravel does, for example.
I'm just trying to be able to operate with this application structure:
As you can see, all I want is to use namespaced controllers in subfolders to make more order for my code.
According to all explanations, here's my loader.php:
<?php
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerDirs(
array(
$config->application->controllersDir,
$config->application->modelsDir,
$config->application->pluginsDir
)
)->register();
AFAIK, Phalcon should traverse all subfolders for not found classes when used via registerDirs.
Then I define my routes to specific controller after the main route to index controllers in base directory:
<?php
$router = new Phalcon\Mvc\Router(false);
$router->add('/:controller/:action/:params', array(
'namespace' => 'App\Controllers',
'controller' => 1,
'action' => 2,
'params' => 3,
));
$router->add('/:controller', array(
'namespace' => 'App\Controllers',
'controller' => 1
));
$router->add('/soccer/soccer/:controller', array(
'namespace' => 'App\Controllers\Soccer',
'controller' => 1
));
$router->add('/soccer/:controller/:action/:params', array(
'namespace' => 'App\Controllers\Soccer',
'controller' => 1,
'action' => 2,
'params' => 3
));
return $router;
And one of my controllers look like:
<?php namespace App\Controllers\Soccer;
use App\Controllers\ControllerBase as ControllerBase;
class IndexController extends ControllerBase
{
public function indexAction()
{
}
}
What's wrong here? Default top namespace is not registered? Am I missing something?
This just doesn't work. When I try to open myserver.com/soccer which I expect to go to app/controllers/soccer/IndexController.php, but instead it tells me:
SoccerController handler class cannot be loaded
Which basically means it's looking for SoccerController.php in /controllers directory and totally ignores my subfolder definition and routes.
Phalcon 1.3.0
Stuck on this for a week. Any help - Much appreciated.
I was having a problem with loading the ControllerBase and the rest of the controllers in the controllers folder using namespaces. I was having a hard time since other example projects worked fine and I realized that I was missing a small detail in the despatcher declaration where I was supposed to setDefaultNamespace
(ref: https://github.com/phalcon/vokuro/blob/master/app/config/services.php)
$di->set('dispatcher', function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('App\Controllers');
return $dispatcher;
});
or you can specify it directly on the routing declaration file like this
$router->add("/some-controler", array(
'namespace' => 'App\Controllers'
'controller' => 'some',
'action' => 'index'
));
that should work as well, it might be a bit confusing at first with namespaces but once you get a hang of it you will love this extremely fast framework
It looks like your namespaces have capitals
App\Controllers\Soccer
and your folder structure does not
app\controllers\soccer
In my app I have controllers with a namespace and I have just tried changing the case of the folders so they don't match and I get the missing class error.
Of course it does raise a question, how many controllers are you planning on having that namespacing them is worthwhile? Are you grouping controllers and action by function or content? I used to have loads of controllers in Zend, but now I have grouped them by function I only have 16 and I am much happier. e.g. I suspect soccer, rugby, hockey etc will probably be able to share a sport controller, articles, league positions etc will have a lot of data in common.
ps Don't give up on Phalcon! In my experience it is sooo much faster than any other PHP framework I have used it is worth putting up with a lot :)
Are you sure Phalcon traverses subfolders when registering directories to the autoloader? Have you tried adding a line to your autoloader which explicitly loads the controllers\soccer directory?
Alternatively, if your soccer controller is namespaced, you can also register the namespace: "App\Controllers\Soccer" => "controllers/soccer/" with the autoloader.
I have following structure in my Zend-Project :
-application
- PDF
- configs
- controllers
- models
- views
- Bootstrap.php
-library
-public
-tests
I have created a new folder PDF inside application folder. And I have write some classes inside it[PDF].
What I want is to access this classes inside the indexAction() of the IndexController, but it showing an error like :
"Class 'Application_PDF_FormDocument' not found in D:\xampp\htdocs\zendapp\application\controllers\IndexController.php on line 13"
What may be the possible reason?
Please provide some help.....
Thanks In Advance......
I agree with ChanibaL regarding the naming of your classes. you should be naming it PDF_FormDocumnet.
Next, in application.ini, regerster the namespace:
autoloaderNamespaces[] = "PDF_"
Lastly, in your index.php make sure you are adding it to the include path:
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
realpath(APPLICATION_PATH),
get_include_path(),
)));
That should do the trick
If you have a standard autoloader in your application, the class name should be PDF_FormDocument (no Application_ part!) in the file application/PDF/FormDocument.php
If this doesn't help by itself try adding
protected function _initAutoload() {
$autoloader=new Zend_Application_Module_Autoloader(array(
'namespace' => 'PDF',
'basePath' => dirname(__FILE__).DIRECTORY_SEPARATOR.'PDF'
));
to application/Bootstrap.php
I am trying to figure out how do you generate models for modules in ZF? My logic could be flawed, but here is the setup:
I have a ZF Structure setup for modules. I have a Blog Module and a Game Module. I wish for both of these systems to be independent of each other, but share the same common modules, such as user accounts, they would be hosted under separate databases IE a Blog Database and a Game Database and a Core database. So my structure would look like:
ZF /
- applications /
- configs
- controllers
- models
User.php
- modules
- blog
- controllers
- models
Blog.php
- views
- games
- controllers
- models
Games.php
- views
- views
I am just a bit confused on how you can get doctrine to generate the models for individual modules. I could be looking at this completely wrong, if anyone can shed some insight I would totally appreciate it, short of manually doing it. Back to trying to do some more research for it see if I can find the solution.
Thanks.
AFAIK you can't generate them in your way :( , sorry for that .
i ran into same problem once before and i think the best solution is to generate the Models out of the application folder and put them into the Library folder so the structure would be
ZF /
- applications /
- configs
- controllers
- models
- modules
- blog
- controllers
- models
- views
- games
- controllers
- models
- views
- views
-library/
-your_custom_namespace
-Model
User.php
Blog.php
Games.php
so all of your model would have the same prefix + save the time and pain of manually editing each generated model to fit to its namespace .
down below my doctrine cli
<?php
echo "Hello Tawfek ! , Howdy ?? \n";
/**
* Doctrine CLI
*/
error_reporting(E_ALL);
define('ROOT_PATH', realpath(dirname(__FILE__)));
define('APPLICATION_PATH', realpath(dirname(__FILE__) . "/../"));
define('APPLICATION_ENV', 'development');
//Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
'../library',get_include_path(), "/home/Sites/site/library/" )));
/** Zend_Application */
require_once 'Zend/Application.php';
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
// Read in the application.ini bootstrap for Doctrine
$application->getBootstrap()->bootstrap('doctrine');
// Create the configuration array
$config = $application->getOption('doctrine');
// (Note you can have all of these in application.ini aswell)
$config['generate_models_options'] = array(
// Define the PHPDoc Block in the generated classes
'phpDocPackage' =>'site',
'phpDocSubpackage' =>'Models',
'phpDocName' =>'Your Name Goes here',
'phpDocEmail' =>'Your Email',
'phpDocVersion' =>'1.0',
// Define whats what and named how, where.
'suffix' => '.php',
'pearStyle' => true,
'baseClassPrefix' => 'Base_',
// Unless you have created a custom class or want Default_Model_Base_Abstract
'baseClassName' => 'Doctrine_Record',
// Leave this empty as specifying 'Base' will create Base/Base
'baseClassesDirectory' => NULL,
// Should make it Zend Framework friendly AFAIK
'classPrefix' => 'Dagho_Model_',
'classPrefixFiles' => false,
'generateBaseClasses' => true,
'generateTableClasses' => false,
'packagesPath' => APPLICATION_PATH "/../library/Dagho/Model" ,
'packagesFolderName' => 'packages',
);
$cli = new Doctrine_Cli($config);
$cli->run($_SERVER['argv']);
?>