Currently I'm trying to implement this behavior:
I make several routers
Inside a router, I change an environment variable
That environment variable is accessible on before.dispatch
Basically, I want to be able to do this:
$app->get('(/)', function() use ($app, $env) {
$env['title'] = 'My page title';
$app->render('index.tpl', array(
'test' => 'Test!!!',
));
});
While I also have this:
$app->hook('slim.before.dispatch', function () use ($app, $env) {
$app->view()->appendData(array(
'env' => $env
));
if (!isset($env['partial']) || $env['partial'] != true)
$app->render('header.tpl');
});
Problem is, the $env['title'] is only available in index.tpl, and not header.tpl, I'm assuming because in before.dispatch, I don't apply the route yet.
How can I achieve this behavior without having to applyHook() at every route I need to change header template variables for?
Thank you!
You've got a scope issue, and the way you're attempting to get a variable from your route into the variable in your hook simply isn't going to work.
Instead, you should be adding $env to view via the $app->render() call in your route, like so:
$app->render('index.tpl', array(
'test' => 'Test!!!',
'env' => $env,
));
When you do that, the data in $env will be available in any of the slim.after hooks.
IMPORTANT: Since you're appending 'env' to the view data in your hook, I highly recommend naming your page title array key title, or else the env data you've appended in the render method will be overwritten. The new render arguments would look like:
$app->render('index.tpl', array(
'test' => 'Test!!!',
'title' => 'My page title',
));
Your template engine should now be able to access the title in both header.tpl and index.tpl.
Related
I am using Laravel. I have referenced my project name in several different places in my views.
I then decided to change the name of my application! So is there a global variable I can use instead and then I only have to change the name in one place next time?
I looked through the docs but couldn't see this feature..
Of course global variables exist in Laravel as well. However just because the exist it doesn't mean you should use them.
A much more suitable approach would be to store the name in a config file.
You can use app/config/app.php and just add a row:
return array(
'name' => 'FooBar',
// existing values ...
'debug' => false,
'url' => 'http://localhost',
// etc ...
);
Or create your very own config file. For example app/config/site.php
return array(
'name' => 'FooBar'
);
And you use it like this:
Config::get('app.name');
Or
Config::get('site.name');
See the documentation for more information
You can make use of View Composers
http://laravel.com/docs/4.2/responses#view-composers
Regarding the use of named routes, these 2 lines allow me to access the same page so which is correct?
// Named route
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// Much simpler
Route::get('apples', 'TestController#getApples');
Is there any reason I should be using named routes if the latter is shorter and less prone to errors?
Named routes are better, Why ?
It's always better to use a named route because insstsead of using the url you may use the name to refer the route, for example:
return Redirect::to('an/url');
Now above code will work but if you would use this:
return Redirect::route('routename');
Then it'll generate the url on the fly so, if you even change the url your code won't be broken. For example, check your route:
Route::get('apples', 'TestController#getApples');
Route::get('apples', array('as' => 'apples.show', 'uses' => 'TestController#getApples'));
Both routes are same but one without name so to use the route without name you have to depend on the url, for example:
return Redirect::to('apples');
But same thing you may do using the route name if your route contains a name, for example:
return Redirect::route('apples.show');
In this case, you may change the url from apples to somethingelse but still your Redirect will work without changing the code.
The only advantage is it is easier to link to, and you can change the URL without going through and changing all of its references. For example, with named routes you can do stuff like this:
URL::route('apples');
Redirect::route('apples');
Form::open(array('route' => 'apples'));
Then, if you update your route, all of your URLs will be updated:
// from
Route::get('test/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
// to
Route::get('new/apples', array('as'=>'apples', 'uses'=>'TestController#getApples'));
Another benefit is logically creating a URL with a lot parameters. This allows you to be a lot more dynamic with your URL generation, so something like:
Route::get('search/{category}/{query}', array(
'as' => 'search',
'uses' => 'SearchController#find',
));
$parameters = array(
'category' => 'articles',
'query' => 'apples',
);
echo URL::route('search', $parameters);
// http://domain.com/search/articles/apples
The only reason to name the route is if you need to reference it later. IE: from your page in a view or something, check whether you are in that route.
I'm creating an app in CakePHP which requires me to run 'multiple' apps within one CakePHP installation. Something like I have n controllers that behave the same for all applications, but they only differ when I call the database - anyway, I need to create a route which behaves something like this:
/app1/controller/action/a/b/c
/app2/controller/action/a/b/c
(where app1 and app2 are alphanumeric strings that can change to anything)
That would be routed to something like:
/controller/action/app1/a/b/c (or the same for app2, and so on)
The routed route could be just /controller/action/a/b/c too, but I need to have a way to access the app1 / app2 parts of the URL within the controller (for further processing within the controller). Is there a way to do this in CakePHP? Thanks.
Slightly related question: When the above is accomplished, is there a way to set a 'default' app-name (like when I attempt to access /controller/action/a/b/c it will automatically be routed to the equivalent of typing /global/controller/action/a/b/c?)
Thanks!
Effectively: What I want is just to use Routing (or any other CakePHP 'method' that can do this) to handle URLs like /foobar/controller/action/the/rest to /controller/action/the/rest and pass "foobar" to the controller, somehow. "Foobar" is any alphanumeric string.
In app/Config/routes.php add:
Router::connect(
'/:app/:controller/:action/*',
array(),
array( 'pass' => array( 'app' ))
);
This will pass the value of app as the first argument to the action in your controller. So in your controller you would do something like:
class FoosController Extends AppController {
public function view_something($app, $a, $b, $c) {
// ...
}
}
When you request /myApp1/foos/view_something/1/2/3 the value of $app would be 'myApp1', the value of $a would be 1, etc.
To connect other routes, before the above, you can add something like:
Router::connect(
'/pages/:action/*',
array( 'app' => 'global', 'controller' => 'pages' ),
array( 'pass' => array( 'app' )) // to make app 1st arg in controller
);
Instead of routing, you should use Model attribute -> dbconfig to change the databases dynamically. Also you should also have to send some arguments to the method by which you can identify which database needs to be connected with your application.
Below i have an ajax tab example:
$this->widget('zii.widgets.jui.CJuiTabs', array(
'tabs' => array(
'StaticTab 1' => 'Content for tab 1',
'StaticTab 2' => array('content' => 'Content for tab 2', 'id' => 'tab2'),
// panel 3 contains the content rendered by a partial view
'AjaxTab' => array('ajax' => $this->createUrl('/AjaxModule/ajax/reqTest01')),
),
// additional javascript options for the tabs plugin
'options' => array(
'collapsible' => true,
),
));
but i don't know what happens in /AjaxModule/ajax/reqTest01.
There is a missing part in this example, the rendering view, and i don't know how to design it so that the ajax call to work. Thanks.
According to the code you have put up, specifically this line:
'AjaxTab' => array('ajax' => $this->createUrl('/AjaxModule/ajax/reqTest01')),
We know that we need ajaxmodule, ajax controller, reqtest01 action, so do the following steps:
First
Create a module, it'll have to be named AjaxModule.
Second
Create a controller in this AjaxModule named Ajax.
Third
Create an action within this Ajax controller, named ReqTest01.
Within this action you can either directly echo html, or use renderPartial(), to render a view file partially for ajax.
So your controller Ajax and the action within looks somewhat like this
<?php
class AjaxController extends Controller
{
public function actionIndex()
{
$this->render('index');
}
public function actionReqTest01(){
// directly echoing output is hardly of any use, like echo "Directly echoing this";
$this->renderPartial('rendpar_ajax'); // renderPartial is way better as we have a view file rendpar_ajax.php that we can manipulate easily
}
}
Fourth
Now we can code the rendpar_ajax.php view file, create this file in the views folder of the ajaxController controller in the AjaxModule module.
<?php
// rendpar_ajax.php file for ajax tab
// have any code here, use widgets, form, html helper etc
echo "<h1>AjaxModule--AjaxController--actionReqTest01</h1>";
echo "<p>This view is partially rendered</p>";
Read more about creating modules, controllers, actions, and how they are used, and how the yii directory hierarchy works.
Good luck!
Edit: Note that to a view we can also pass dataproviders for getting complex dynamic views.
Im using "Zend form". What should I do to get correct "action" parameter in my FORM tag?
For example, the form Form_Search used in SearchController in indexAction. Where and how should I set the action parameter to form to make it "/my/app/directory/search/index"?
Update: "action" parameter should be the same as the form will assume if not set. I just need the param in FORM to simplify JS coding.
You can use setAction method of Zend_Form, e.g.:
$yourForm->setAction('/my/app/directory/search/index');
Hope this is what you are looking for.
EDIT:
You can retrieve many info about the request, in an action, using $this->getRequest() method that returns an instance of Zend_Controller_Request_Http. For example, if to get basePath and everything between the BaseUrl and QueryString you can do:
$infoPath = $this->getRequest()->getPathInfo();
$basePath = $this->getRequest()->getBaseUrl();
$yourForm->setAction($basePath . $infoPath);
Zend_Controller_Request_Http has other methods that might be useful to you.
You can use the url() view helper to create your action urls.
$view->url(array(
'module' => 'mymodule',
'controller' => 'mycontroller',
'action' => 'myaction',
'param1' -> 'myvalue1',
// etc
), 'default');
// 'default' here refers to the default route.
// If you specify a custom route, then that route will be used to
// assemble() the url.
Depending where you call $form->setAction(), you can access to the $view in different ways.
In the controller: $this->view
In the form itself: $this->getView()
In a view script: $this
In view helper extending Zend_View_Helper_Abstract: $this->view
Hope it helps!
Just an addition to previous answers. Kind of "industry standard approach" is to render/validate/process the form all on the same page. Then there is no need to set the action as it's filled with current URL.
Exception is for example serch field in layout. Then use $form->setAction($url). But always remember to echo the form in the search action. If the form value is invalid, ZF would expect you to render it in page with the errors. Or you can use $form->getErrors().
`$this->setAttribs(array(
'accept-charset' => 'utf-8',
'enctype' => Zend_Form::ENCTYPE_URLENCODED,
'method' => 'get',
'action' => '/controller/action/param/attr'
))`