Call Modules Controller from Application Bootstrap - zend-framework

I've asked a question like this previously but I believe this is different (that one was just a general question).
I implemented Zend_Navigation.
For menu I used DB Table to store menu items and did recursion on Array-s to get the tree of menu items.
All of this action takes place in my module called Menu. Inside I have:
Menu --
Controllers --
IndexController.php
Models--
DbTable--
Menu.php
Bootstrap.php
inside index controller I have a function menuGenerator($menu_id)
So following tutorials on Zend_Navigation, the menu is initialized in the application bootstrap.
my function inside application's bootstrap looks like this:
public function _initMenus() {
$menuArray = new Menu_IndexController();
$outArray = $menuArray->menuGenerator(1);
$mainmenu = new Zend_Navigation($outArray);
$this->view->navigation($mainmenu);
}
and it gives me an error:
Fatal error: Class 'Menu_IndexController' not found in D:\Server\xampp\htdocs\project\application\Bootstrap.php on line 8
So, Any ideas how should I make it to work correctly?
P.S. is it possible to start 2 new menus at a time? for ex: I need 1. main menu 2. footer menu (any link to an article would be nice)

By default, Zend Framework's autoloader doesn't autoload controllers in the same way it loads other components (models, view helpers, forms, etc), so PHP throws the error saying it can't find the class. The quickest way to get around this is to explicitly include the controller in Bootstrap.php. The following should work:
public function _initMenus() {
require_once('./Controllers/IndexController.php');
$menuArray = new Menu_IndexController();
$outArray = $menuArray->menuGenerator(1);
$mainmenu = new Zend_Navigation($outArray);
$this->view->navigation($mainmenu);
}

It's pretty unusual to call a controller method during Bootstrap since there are many bootstrapping tasks upon which controller actions depend. In your case, the controller method menuGenerator() is not actually an action, so presumably it will not be a problem.
Nonetheless, it's still unusual enough that I would move the menuGenerator() method out into its own class. Then invoke that operation both at Bootstrap and in your controller.

Related

NDepend doesn't return all methods in ASP.NET MVC Controller class

Here is my code:
// <Name>test</Name>
warnif count > 0
let controllerType= ThirdParty.Types.WithFullName("System.Web.Mvc.Controller").Single()
from m in controllerType.Methods
select m
But I could only see these methods in Controller:
But clearly View is a method of Controller yet NDepend doesn't see it. Can any body point out what I am missing? Thanks.
[Update]
My original intent was to categorize actions according to the actual type of content they return (eg. html, fileresult, ajax result, etc) in my ASP.NET MVC code. To determine if an action returns html, I need to check if the action actually returns a ViewResult, including actions like the following which has a return type of ActionResult but actually returns ViewResult using the View method.
So I wanted to check if an action actually IsUsingMethod(mvcViewMethod) and as long as it calls any of the View method, I will consider this action as returning html. But now i couldn't get a reference to the mvcViewMethod.
[Update 2]
As suggested by Patrick, I checked out the class browser and only see this:
I don't see any View methods. This is much less than what I see in ILSpy of the same dll, where I can see the View method clearly defined:
And for an action like this:
In the class browser, if I right click this action and choose "Select methods that I use (Directly or Indirectly)", I will see this query result:
I still couldn't see it uses the View method.
[Final Update]
Following Patrick's suggestion, I added System.Web.Mvc dll into my application code dlls and it works perfectly now:

Typo3 Extension PHP View

Using the infos in this link:
https://docs.typo3.org/typo3cms/ExtbaseFluidBook/8-Fluid/9-using-php-based-views.html
I try to create an action to output a JSON.
I have a normal controller with the list action:
public function listAction()
{
$storelocators = $this->storelocatorRepository->findAll();
$this->view->assign('storelocators', $storelocators);
}
And in ext/my_storelocator/Classes/View/Storelocator I have a class List.php:
<?
class Tx_MyStorelocator_View_Storelocator_List extends Tx_Extbase_MVC_View_AbstractView {
public function render() {
return 'Hello World';
}
}
All I get is:
Sorry, the requested view was not found.
The technical reason is: No template was found. View could not be resolved for action "list" in class "My\MyStorelocator\Controller\StorelocatorController".
So I guess there is something wrong with the paths. Or where is the Problem?
Edit: Extensioninfos
Vendor: My
key: my_storelocator
controller: NOT SURE (I created it with the extension_builder so I guess my controllers name is Storelocator)
action: list
From my understanding a classname like Tx_MyStorelocator_View_Storelocator_List should be correct. But its not working
You will need to create an empty file for the HTML view for your controller, e.g. Resources/Private/Template/Storelocator/List.html, even if you do not plan to use the HTML view or if you just return the content yourself (which is perfectly fine).
The reason for this is simply technical limitation.
First of all, TYPO3 now has a built-in JSON view, described thoroughly here: https://usetypo3.com/json-view.html. It lets you easily define which properties you'd like to render.
The error message means that your Controller is still pointing to the TemplateView - because thats the error the TemplateView throws if it can't find the defined template file.
You can specify which view to use to render within your controller. You can either set a default view via the $defaultViewObjectName property, like so:
/**
* #var string
*/
protected $defaultViewObjectName = '\TYPO3\CMS\Fluid\View\TemplateView';
You can also set it from within the Controller inside initialization actions like so:
public function initializeExportPDFAction(){
$this->defaultViewObjectName = 'Vendor\Extension\View\FileTransferView';
}
(I have, however, not yet found a way to define the template from within actions, any tips in the comments would be appreciated)
Your path syntax is probably out of date. Instead of writing a render() function in Classes/View/Storelocator/List.php, try writing a listAction() function in a Classes/Controller/StorelocatorController.php file. Extension Builder should have created this file for you, if you made an aggregate model with the usual "list, create, edit ..." and such actions.
Review A journey through the Blog Example and the following chapter, Creating a first extension, for tips.
Keep in mind that there is a mismatch between the documentation and the Extension Builder generated PHP code files. Developing TYPO3 Extensions with Extbase and Fluid has some parts up to date, and other parts still using old syntax.

Nested View in Theme Views using Fuelphp

I have working with Fuelphp and done some tiny apps, Now i am moving to bigger one, now i am stuck with this.
I have enabled theme in fuelphp and it is working perfectly, In my App there is a Top Nav bar, In Nav bar there is 3 drop down notification system like facebook & also search option. So i have created top_nav partial. I want to make the search and notification system in partial inside partial, to making it more modular, so i created another partial of top_nav_search and top_nav_notif . Both partials need some variables to transfer from controller, How i do that. My variables are passing to top_nav only. Not top_nav_search or top_nav_notif.
How can i add partial inside the partial.
Answer Found:
using View Class will not work with theme. It will search for APP/View folder.
we have to use
echo Theme::instance()->view('partials/partial_file')->set_safe('var', $this->get('var'));
found working
You can use set_global on your view, and then the exposed variable will be available everywhere.
$view->set_global('some_data', $some_data);
// instead of
$view->some_data = $some_data;
Also, when using set_partial, you can specify a View instance instead of the path for the view. That way you can pass variables directly into the View instance specified to set_partial. Though I'm not sure it solves your problem. Still, here's an example:
$view = View::forge('nav/search');
$view->some_data = $some_data;
$theme->set_partial('top_nav_search', $view);
Edit: I wrote View::forge, but more appropriate would've been to write $theme->view in this example. Like this:
$view = $theme->view('nav/search');
$view->some_data = $some_data;
$theme->set_partial('top_nav_search', $view);

How do I avoid repetition when passing variables from the Controller/Action to the Layout

I am currently working on a project developed using Zend Framework, based on the structure of my web page design I have reached a point where I have to pass a small number of variables to my layout from each Controller/Action. These variables are:
<?php Zend_Layout::getMvcInstance()->assign('pageId', 'page1'); ?>
<?php Zend_Layout::getMvcInstance()->assign('headerType', '<header id="index">'); ?>
The reason for passing this information is firstly, I pass the page id as the multi column layout may change depending on the content being displayed, thus the page id within the body tag links the appropriate CSS to how the page should be displayed. Secondly I display a promotional jQuery slider only on the index page, but I need the flexibility to have it displayed on potentially multiple pages in case the wind changes and the client changes their mind.
My actual question: Is there a more appropriate method of passing this information to the Layout that I am overlooking?
I am not really questioning whether the information has to be sent, rather is there some Zend Framework feature that I have, in my haste, overlooked which would reduce the amount of repetitive redundant code which may very well be repeated in multiple Actions within the same controller?
You could turn that logic into an action helper than you can call from your controllers in a more direct way. You could also make a view helper to accomplish the same thing but view helpers usually generate data for the view rather than set properties.
// library/PageId.php
class Lib_PageId extends Zend_Controller_Action_Helper_Abstract
{
public function direct($title, $pageId, $headerType)
{
$view = $this->getActionController()->view;
$view->headTitle()->append($title);
$view->pageId = $pageId;
$view->headerType = $headerType;
}
}
In your controller actions you can now do this:
$this->_helper->PageId('Homepage', 'page1', 'index');
// now pageId and headerType are available in the view and
// Homepage has been appended to the title
You will also need to register the helper path in your Bootstrap like this:
protected function _initActionHelpers()
{
Zend_Controller_Action_HelperBroker::addPrefix('Lib');
}
Doing it like that can reduce the amount of repetitive code and remove needing to assign the values from the view. You can do it in the controller very quickly. You can also have default values in the case that the helper hasn't been called.
You shoudn't really be passing anything from the view to the layout, for a start the view should be included IN the layout, not the other way around.
So, setting your page title should be done using similar code to what you have, but inside the controller action being called:
$this->view->headTitle()->append('Homepage');
And the other two issues - you need to rethink as I stated to begin with. Maybe you're misunderstanding the layout/view principle? If you include the different views per action, then you simply change the div id when needed, and include the header for your banner only in the index.phtml file.

Zend Framework - Extending Controllers

I'd like to have my controller - i.e. Page_IndexController - extend a base controller.
For example;
class Page_IndexController extends Content_IndexController {
}
However, it seems the autoloader doesn't pick up the fact it's a controller class at any point - I get the error Fatal error: Class 'Content_IndexController' not found
First question: How do I fix this?
I can temporarily fix this by require_once'ing the generic 'content' controller, but this is hardly ideal.
The next issue is that if my Page controller has it's own view script for an action, it works no problem.
But if I'm extending a controller, and I call for example 'listAction' on the Page controller, but this action is implemented in Content_IndexController, it still looks for the list view script in the page controllers "scripts" directory.
Second question: How do I configure my controller to use its parents view script if it doesn't have its own?
If your application can find Page_IndexController you probably have a Page module. If you are not using modules in your application you have to name your controllers PageController and ContentController, not Page_IndexController, ... So the solution is to register "Content_" namespace with the autoloader.
As for the second question. You can extend the provided ViewRenderer controller action helper and override methods for finding the view script so they can look in other places if needed. You just have to pass your viewrenderer to the front controller. For passing your own ViewRenderer to the controller take a look at Advanced Usage Examples.
The auto loader can't find your controller because you haven't told it where to search. The Content_IndexController isn't in your "library" folder (I assume its inside of the Content module)
What I would suggest is creating a My_Controller_IndexBase class in your library folder that both Content_IndexController and Page_IndexController inherit.
Did a little more research on the topic of the view script. You could change up the view's script paths during init() somewhere. I'm pretty sure this would probably need to be done in a ViewRenderer - but might also work inside the controller's init/action code.
$this->view->setScriptPath(
array(
realpath(APPLICATION_PATH+'/../path/to/other/module/views'),
) + $this->view->getScriptPath());
Script paths are processed Last In First Out according to the Zend_View_Abstract
For the second question:
If you don't want to write your own ViewRenderer, you can use $this->renderScript('parent/index.phtml') to render a specific view script. You could call that in your child controllers instead of letting the views be rendered for you automatically, or if your child controllers rely on the parent controller to do the rendering of the script you can just place that in your parent controllers.
I do that mode.
Frist I register a new name who a plugin in my index.php into the public folder:
/public/index.php
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('modelo_');
Secound I create a new folder to put my controller
/library/modelo/
Third I create my controller model and put it into the folder created and rename it.
class Modelo_ModeloController extends Zend_Controller_Action
{
protected $_db = null;
protected $_menu = null;
protected $_util = null;
protected $_path = null;
... actions to my model
public function inicial(){}
}
and I extend this class im my application
class Sispromo_PedidoController extends Modelo_ModeloController
{
public function init(){}
....
}