I'm making an AJAX call in my symfony project, so it has an sf_format of 'js'. In the actionSuccess.js.php view, I call get_partial to update the content on the page. By default it looks for the partial in 'js' format since the sf_format is still set as 'js'. Is it possible to override the sf_format so that it uses the regular 'html' partial that I already have (so that I don't have to have two identical partials)?
I have had a similar issue.
I looked through the code, and get_partial doesn't give you any scope to change the format looked for ... guess you could modify the code to make that possible if you needed to.
I instead went for switching the request format - also not ideal in my opinion. But better than editing the symfony files.
To do this in the controller:
$request->setRequestFormat('html');
or in the view
$sf_context->getRequest()->setRequestFormat('html');
In both cases, if you want to set this back afterwards, you can retrieve the existing value using getRequestFormat().
if your looking for a more sustainable solution, you could listen to the view.configure_format and set the sfPHPView extension in your appflication configuration.
// in apps/api/config/apiConfiguration.class.php
public function configure() {
$this->dispatcher->connect('view.configure_format', array($this, 'configure_formats'));
}
public function configure_formats(sfEvent $event) {
// change extension, so our module templates and partials
// for xml do not need the .xml.php extension
$event->getSubject()->setExtension('.php');
}
Related
I am trying to give a shot to HMVC in Codeigniter. Here is my folder structure.
-ROOT
--APPLICATION
---MODULES
----Module_Email
-----Controllers
-----Models
-----Views
-----Assets
------JS
------CSS
------IMG
To render the Module i have to use
Module::run('Module_Email');
This method will output the rendered output, an example is given below
<script type="text/javascript" src="PATH/TO/EMAIL_MODULE/JS/JS_FILE.JS"></script>
<div data-module-name="Module_Email" class="Email_wrapper">
//RENDERED HTML CONTENT
</div>
Now here my problem start. Normally i would like to put all my resources to header. So when i call any module, its dependence need to be added in header instead of from where its get called.
I searched a lot but i couldn't find any good methods.
Please help.
Update
Currently i have a function on my header called get_assets() which will output predefined resources to header. But i cant say which modules is going to use in pages, so the system need to check which modules are used in this page, and if its used then its dependencies need to be added on header.
Seems like your main problem then is trying to figure out what modules were used.
Unfortunately as far as I can tell with the default Wiredesignz modular extension there is no way to access the module name unless you write some sort of hack to get at that data. The module being used is stored in the protected variable $module in the MX_Router class, however, there is no public method to allow you to get access to it. So your only choice would be to extend the class and create a public function.
Alternatively you could use a forked version of Wiredesignz implementation which I did which provides numerous other features including a public function to get at the $module variable. Using the forked version I wrote you could then use code such as this:
<?php $module_name = $this->router->fetch_module(); ?>
However, that will only record the last module you loaded, so you would still need to do work to store all the modules, and then have your function use this information to determine what assets to load. If I were doing something like you I would probably fork my version and then create an additional data structure to store every module that was loaded that you could then later get access to.
I don't think this is exactly what you were hoping for, but might be something to get you on the right track to finding a solution.
I added an array to the Module class to store the assets and two functions to store/retrieve the items. Here is the source (updated Modules.php)
# Register your assets
public static function register_asset( $asset )
{
if( in_array($asset,self::$assets) === FALSE )
{
self::$assets[] = $asset;
}
}
public static function assets()
{
return self::$assets;
}
and now you can register your assets like this inside your module
Modules::register_asset('myslider.js');
You can retrieve all your assets using
Modules:assets();
Which will return an array of assets that can be processed depending up on the situation.
I am using codeigniter for a project that is used by a variety of companies.
The default version of our software is up and running and works fine - however some of our customers want slightly different view files for their instance of the system.
Ideally what I would like to do is set a variable (for example VIEW_SUFFIX) and whenever a view file is loaded it would first check if there was a suffix version available if there was use that instead.
For example if the system had a standard view file called 'my_view.php' but one client had a VIEW_SUFFIX of 'client_1' - whenever I called $this->load->view('my_view') if the VIEW_SUFFIX was set it would first check if my_view_client_1 existed (and if it did use that) or if not use the default my_view.php.
I hope that my question is clear enough... If anyone has done this before or can think of a way to do it I would really appreciate it.
EDIT:
Ideally I would like a solution that works without me changing every place that I am calling the view files. Firstly because there are a few files that may want different client versions and also because the view files are called from a lot of controllers
I had a similar requirement for which I created a helper function. Among other things, this function can check for a suffix before loading the specified view file. This function can check for the suffix and check if the file exists before loading it.
Unfortunately, the file checking logic would be a bit brittle. As an alternative, you can implement a MY_Loader class that will override the basic CI_Loader class.
Something like this in your application/core/MY_Loader.php:
class MY_Loader extends CI_Loader {
protected function _ci_load($_ci_data)
{
// Copy paste code from CI with your modifications to check prefix.
}
}
Could you not do this
// some method of creating $client
// probably created at login
$_SESSION['client'] = 'client_1';
$client = (isset($_SESSION['client'])) ? $_SESSION['client'] : '';
$this->load->view("your_view{$client}", $data);
Situation: only main page is accessible by default, all other pages needs a logged in user. When a module is loaded without user, a login template should be displayed, and no module. In other words, the $sf_content must be emptied in layout.php which is not 100% ok since there is logic in the layout. Is there elegant way for that? I dont think a helper is OK either....
Check out security filters, this is one standard way security is designed in symfony.
You even can implement your own SecurityFilter class with the functionality you want.
http://symfony.com/legacy/doc/reference/1_4/en/12-Filters#chapter_12_security
It is done by default for you by the sfBasicSecurityFilter filter. You just need a good configuration. Read this part of the Jobeet tutorial. You should use sfDoctrineGuardPlugin (or sfGuardPlugin if you using propell) for user authentication.
To complete my comments above: There are different ways to override the layout. You could use the methods:
setLayout($name)
//or using foward, which forwards current action to a new one (without browser redirection)
forward($module, $action);
inside your action class. In case you wand to modify the layout inside a filter, you can use something simular to this:
class yourFilter extends sfFilter {
public function execute($filterChain) {
if($yourConditionForOverrideTheDefaultLayout) {
//here the syntax to change the layout from the filer
$actionStack = $this->getContext()->getActionStack();
$actionStack->getFirstEntry()->getActionInstance()->setLayout('yourLayout');
}
$filterChain->execute();
}
}
To avoid unnecessary duplication in the layout file you can work with Fragments and Partials.
Hey guys, I've used the Symfony admin generator for a module.
Everything is working, but when the form for my model is instantiated, I need to pass in my own option.
I could do this myself by overriding the executeNew, executeCreate functions in myModuleActions.class.php (which extends myModuleAutoActions).
But I was hoping for a neater solution?
Perhaps overriding one of the configuration classes is the way to go. I basically need to add the current sf_user object ($this->getUser) as an "sf_user" option for the form, to avoid using sfContext in the myModuleForm.
Any ideas?
Welcome to Stack Overflow, jolly18.
I would just use sfContext. For example, in my app, I have a subform that creates a new Note object and assigns the user to it. In my form's configure() I have:
$new_note->setAuthor(sfContext::getInstance()->getUser()->getUsername());
I see the book calls this "The fastest but ugly way" because it makes "a big coupling between the form and the context, making the testing and reusability more difficult." But in practice... this works well and I can move on.
if module was generated using admin-generator :
in apps/backend/modules/books/actions/actions.class.php
modify: in
executeEdit(){
//leave rest unchanged
$values=array('activity_id'=>$activity_id, 'book_id'=>$book_id, 'todo_id'=>$todo_id, 'user_id'=>$this->getUser()->getGuardUser()->getId());
$this->form = new TabelBooksForm($TabelBooks, $values);
}
modify: in
executeNew(){
//leave rest unchanged
$values=array('activity_id'=>$activity_id, 'book_id'=>$book_id, 'todo_id'=>$todo_id, 'user_id'=>$this->getUser()->getGuardUser()->getId());
$this->form = new TabelBooksForm(array(), $values);
}
in TabelBooksForm.class.php
public function configure()
{
if ($this->isNew()) {
$this->setWidget('book_id', new sfWidgetFormInputHidden());
$this->setDefault('book_id', $this->getOption('book_id'));
$this->setWidget('activity_id', new sfWidgetFormInputHidden());
$this->setDefault('activity_id', $this->getOption('activity_id'));
$this->setWidget('todo_id', new sfWidgetFormInputHidden());
$this->setDefault('todo_id', $this->getOption('todo_id'));
}
}
i've been facing this problem for a while but symfony always surprises me with some neat code that i was not aware of.
I assume you'r using sfPropelPlugin, quite standar, if you checkout the code generated in cache (note: this code will be available once you tried to open the module from the browser, so firts try to look at it so we dont get in trouble :P) you may see something like:
cache/{application_name}(generally frontend or backend)/dev(enviromnemt)/autoModule_name( look here for the module)/:
lib
action
The action folder contains an action.class.php file that defines all actions generated by the generator (executeNew, Edit, Create, Update, etc). If you look a the implementation of executeNew and executeEdit, you can see that they ask a configuration instace the actual form to display, here is an example:
public function executeNew(sfWebRequest $request)
{
$this->form = $this->configuration->getForm();
$this->PaymentOrder = $this->form->getObject();
}
The configuration var containt an instance of a configuration class defined in the lib folder i mentioned earlier. That class tweaks the form to fit the object needs (generally by setting a fresh object instance).
So here comes the magic, the classes you see in your module extend from those in cache, so by pure logic, if you modifi the getForm() method in the main module/lib folder to fit your needs, you wont have to hack forms by getting user valuer where you shouldn't.
Hope this helps!
I just started my adventure with zend framework 1.9.1 but I encountered few issues. I would like to remove default routes to avoid displaying the same content on different URLs - to achive it I wrote custom function in bootstraper
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initMyRouter()
{
$this->bootstrap('router')
->getContainer()
->frontcontroller
->getRouter()
->removeDefaultRoutes();
}
}
but after that, one problem arise - every invalid URL reaches to default controller instead of error controller. To solve this issue I put
resources.frontController.defaultcontrollername = "error"
resources.frontController.defaultaction = "throw"
in application.ini and
public function throwAction()
{
throw new Zend_Controller_Dispatcher_Exception;
}
in ErrorController to workaround this but my question is... am I doing something wrong?
The second issue is that I need to generate only absolute URLs so I added resources.frontController.baseurl = "http://mydomain.com/" in application.ini but after that every URL points to default controller. How to fix it?
The third (and last) is... how to call Zend_Controller_Action_Helper_Url::url in my actions? I tried something like $this->_helper->url(array(), 'frontpage') but it calls Zend_Controller_Action_Helper_Url::direct
I'll answer number three first as I can tell you off the top of my head.
I generally use $this->view->url(array(...), 'routeName', true); the last argument resets the parameters. I find that the view helper is a little easier/quicker to type than the Action Helper. Although I think $this->_helper->url->url(...) is the proper way to get to the action helper.
I've never removed the default route - but if there aren't any other answers later in the day - I'll do my best to do some testing for you after work hours.