I have a product controller and a header controller. When loading the product controller, I use Route::forward() to load my header controller.
return View::make('frontend.catalogue.product.view')
->with('head', Route::forward("GET", "frontend/page/head"));
I can then echo out the header on the page by doing:
<?php echo $head; ?>
Simple. However, I want to pass information to the header controller which will be defined in the product controller, such as the page title or meta description.
Ideally I would either be able to pass an array to the header, or have an instantiated class somewhere which both route requests have access to.
I've tried instantiating a library in my base controller constructor, however this gets re-instantiated on each Route::forward() request so any properties I set can't be read in the next forward.
The only way I can think of doing this is using session data, but that doesn't seem like it would be the best way to do it.
The header does need to be a controller and not just a view composer, as it deals with it's own models etc.
I know Laravel doesn't do HMVC, which would be the ideal solution, and I know there are bundles for HMVC, but I'm curious how you would approach this the Laravel way.
(Using Laravel 3.2 btw)
Managed to get this working how I want. For others interested:
Instead of using
return View::make('frontend.catalogue.product.view')
->with('head', Route::forward("GET", "frontend/page/head"));
I now do the following in the main request controller:
$document = array(
'meta_title' => 'My Title',
'meta_description' => 'My Description',
);
// Output the view
return View::make('frontend.catalogue.category.view')
->with('head', Controller::call('frontend.page.head#index', array($document)));
and in my frontend/page/head controller, I have the following:
public function action_index($document = array()) {
$meta_title = isset($document['meta_title']) ? $document['meta_title'] : 'Default Title';
return View::make('frontend.page.head')
->with('meta_title', $meta_title);
}
Props to the friendly guys on the Laravel IRC for helping with this
Related
I want to use templating in a Codeigniter-4 project.
If my controller looked like this
class Blog extends \CodeIgniter\Controller
{
public function index()
{
$data = [
'todo_list' => ['Clean House', 'Call Mom', 'Run Errands'],
'title' => "My Real Title",
'heading' => "My Real Heading"
];
echo view('blogview', $data);
}
}
I want to use a templating system which works as below:
// Create new Plates instance
$templates = League\Plates\Engine::create('/path/to/templates');
// Render a template with the given data
echo $templates->render('profile', ['name' => 'Jonathan']);
My question is - what is the best place to instantiate that $templates object?
I can repeat it in every method which I know for sure is bad practice.
.... OR ...
I could do it in the __contstructor() and assign to $this->templates and I do so for every controller where I want to use that templating. I feel like there is still a better way.
I have little experience of Laravel where I don't specifically set this $templates variable to use Blade templates instead it simply calls View(). I want to achieve something like that, if possible. I tagged laravel so that anyone with more experience in Laravel may have better understanding on how to achieve it?
What would you suggest?
PS: I am using composer autoload to load all the files.
I'm afraid I am really only a CI3 user but have read a little about CI4 and there is still a base controller you can use. You should take a look at https://codeigniter4.github.io/userguide/extending/basecontroller.html?highlight=basecontroller. You would then make your $this->templates available through all extended controllers.
To build a sidebar that has a lot of dynamic data on it I learned about View composers in Laravel. The problem was that View Composers trigger when the view loads, overriding any data from the controller for variables with the same name. According to the Laravel 5.4 documentation though, I achieve what I want with view creators :
View creators are very similar to view composers; however, they are
executed immediately after the view is instantiated instead of waiting
until the view is about to render. To register a view creator, use the
creator method:
From what I understand, this means if I load variables with the same name in the controller and the creator, controller should override it. However this isn't happening with my code. The view composer:
public function boot()
{
view()->creator('*', function ($view) {
$userCompanies = auth()->user()->company()->get();
$currentCompany = auth()->user()->getCurrentCompany();
$view->with(compact('userCompanies', 'currentCompany'));
});
}
And here is one of the controllers, for example:
public function name()
{
$currentCompany = (object) ['name' => 'creating', 'id' => '0', 'account_balance' => 'N/A'];
return view('companies.name', compact('currentCompany'));
}
the $currentCompany variable in question, for example, always retains the value from the creator rather than being overridden by the one from the controller. Any idea what is wrong here?
After some research, I realized my initial assumption that the data from the view creator can be overwritten by the data from the controller was wrong. The creator still loads after the controller somehow. But I found a simple solution.
For those who want to use View composers/creators for default data that can get overwritten, do an array merge between the controller and composer/creator data at the end of the boot() method of the composer/creator, like so:
$with = array_merge(compact('userCompanies', 'currentCompany', 'currentUser'), $view->getData());
$view->with($with);
I'm developing a web application with Zend Framework 1.12, which is something new to me, and I'm not sure about the way to do something I want to.
EDIT: When I talk about Module, I mean Controller, sorry for that, I still mistake the terms ...
On my home page, the module Index, I made what I wanted to do with it, created several actions and all the stuff, but I'd like to add a search engine I'll make myself.
The problem is that I'd like to create the search engine as a separate module named Search, for example, but put the SearchForm in the home page. Hitting submit would send the datas from the form to the Search module.
I don't quite understand how to do that without having to go to /search to access my form and every associated actions.
Do I have to use a View Helper ?
Also, the searchForm in the front page would be some sort of QuicKSearch and accessing /search would show a more elaborated form for the research.
Can someone explain me how to access the searchForm from the Index module or redirect me to the part of the documentation talking about that ? My research are unsuccessful and Google doesn't help me either.
EDIT: When I talk about Module, I mean Controller, sorry for that, I still mistake the terms ...
First of all, build the searchform as viewHelper, then you can reuse it in several views.
The action attribute in form snippet set to searchModule/controller/action.
Additionaly make research about viewHelpers and Forms in Zend Documentation.
I actually prefer to do this as a an action helper and then just use a standard placeholder view helper to present the search form.
let me demonstrate:
the actual action helper just initiates a form and prepares it for display. I'll leave the form structure to you.
//the action helper
//Just fill in the args for the form to be displayed
class NameSpace_Controller_Action_Helper_Search extends Zend_Controller_Action_Helper_Abstract
{
public function direct($action, $label = null, $placeHolder = null)
{
$form = new Application_Form_Search();
//set the action
$form->setAction($action);
//set the submit button text
$form->search->setLabel($label);
//set the hint text displayed in the form window
$form->query->setAttribs(array('placeholder' => $placeHolder,
'size' => 27,
));
return $form;
}
}
I put the helper in the predispatch method of the controller so that each action in the controller can use the search form with having to build it in every page.
//to use the helper in your controller
class IndexController extends Zend_Controller_Action
{
public function preDispatch()
{
//setup action helper and assign it to a placeholder
$this->_helper->layout()->search = $this->_helper->search(
'/index/display', 'Search Collection!', 'Title');
}
//in your view script
<?php echo $this->layout()->search ?>
I like to put the placeholder in my master layout.phtml so that any time I populate the placeholder it will display. Now all you have to do is style it however you want.
Remember: As with any html form the action parameter is just a url so any valid url can be assigned to the form action. In this example I used the /controller/action parameters, but there are many other ways to pass a url to the form. The url helper comes to mind as good way to do it.
url($urlOptions, $name, $reset, $encode): Creates a URL string based
on a named route. $urlOptions should be an associative array of
key/value pairs used by the particular route.
I have pages in my application that make up the navigation tree. I would like to dynamically insert pages into my navigation using the values of the request. I already have the logic to find the page and then call the addPage() method on it. What I'm looking for is how to easily pass the Zend_Controller_Request values to Zend_Navigation_Page::factory() so I can add that page. Maybe even written as a plugin?
Solution
AngelP got the closest, so I'm giving him credit, but here's my solution:
$request = $this->getRequest();
if ($page = $this->view->siteNav->findBy('id', $page_id)) {
$page->addPage(Zend_Navigation_Page::factory($request->getParams())
->setParams($request->getParams())
->setLabel($this->view->title)
->setVisible(false));
}
This code is executed from a controller action. $this->view->siteNav is an instance of Zend_Navigation that I have in the view. getParams() from the Zend_Controller_Request instance is easily passed to Zend_Navigation_Page::factory() and then to the setParams() method of the Zend_Navigation_Page_Mvc instance.
I have limited resources at the moment so I cannot really check my suggestion, but if you're in you controller, why don't you..
$controller = $this->_request->getControllerName();
$action = $this->_request->getActionName();
$page = new Zend_Navigation_Page( array(
'label' => "Sonny's Page",
'controller' => $controller,
'action' => $action
));
Maybe you could use this as a plugin so that you overload your view? And then add to your Navigation Container?
Cheers,
Angel
Since we don't know the code you have written already, I'm only guessing…
You need to:
retrieve the actual Zend_Navigation container used in navigation() view helper
create new Zend_Navigation_Page instance from array of data retrieved from the request
add the page to the container
assign the new container to the navigation helper
This should be easy. The rest you need to know:
how to write controller plugin with preDispatch method, and put the above there,
how to access current view instance in this plugin (from the view renderer or from application resource/bootstrap)
Then in the plugin you operate on navigation view helper as usual in the view.
Hope this clarified some things.
Why not store the instance in Zend_Registry and then in a postDispatch from either a plugin, module bootstrap or action controller add the pages to the original nav?
is there an easy way to access the url helpers from the models like the ones available in the controllers
i mean in the controllers there is an easy way to generate urls like this :
$this->_helper->url(controller,action,null,params);
now what i need is an easy way to pass urls direclty from the model to the views , for now what i am doing is to pass the CONTROLLER,ACTION AND PARAM as an array to controller then replace the text in the controller with with the helper url in the controller but i want a better way is there one?
You can access the url helper by calling it directly:
$urlHelper = new Zend_View_Helper_Url();
$urlHelper->url(array(),'',true);
The Model should not access the View, nor having to know about it.
If you have to do work that is related to the presentation layer, either use an Action Helper or a View Helper. The data you are processing is fully available in the Controller, so there should be no need to pass it from model.
actually it's a bit specific to my problem but i made work it this way
$check['msg'] == will contain the error or success message
from the models i pass the link that causes the problem
$messages['link'] = array('action'=>'index','controller'=>'trip','params'=>$tripid );
an on the controllers
$check['msg'] = str_replace('%link%',$this->_helper->url($check['link']['action'],$check['link']['controller'],null,array('id' => $check['link']['params'])),
$check['msg']);
$this->_flashMessenger->addMessage($check['msg']);
I found the following code snippet in a book, it maybe of help to someone:
$urlHelper = $this->_helper->getHelper('url');
$urlHelper->url(array(
'controller' => 'customer' ,
'action' => 'save'
),
'default'
);