I need to render a partial view inside a custom component file in Yii2 and according to the Yii docs you can access the view instance via something like this:
\Yii::$app->view->renderFile('#app/views/site/license.php');
I went ahead and tried:
Yii::$app->view->renderPartial('//my/view/');
...but then got an error that I was trying to access a non-existent method.
I then checked out the view class and noticed it doesn't have a renderPartial and this is a method of the controller class instead.
I see it has a renderFile method and a render method; which of these should I use?
The docs don't state the render method includes the layout like the method of the same name from the controller class, so I'm not sure; as for renderFile I'm not 100% sure if that is suitable either?
Could someone explain which method would produce the same results that renderPartial produces?
You can call renderPartial from Yii::$app->controller->renderPartial('myview'); Also as you can see from source code of yii\base\Controller renderPartial calls View's render method so you can use Yii::$app->view->render. Basically there is no difference between render and renderFile, because render internally calls renderFile. But when you use render you can pass $view in several formats like path alias, absolute path whithin application or whithin module and relative path. And to renderFile you can pass only absolute file path or path alias.
Related
i would ask You about proper way to change dynamicly the $twig->render path called from controller.
I want to create custom loader or event subscriber, which works like:
when i set parameter/param and call from controller
return $this->render('system/create.html.twig');
twig will check, if template in path
system/custom/variable_name/create.html.twig
exists, load it, if not, load normal path
system/create.html.twig
I can't find proper way to realize it, have not idea, what i should use, EventSubscriber(and how to Subscribe on render method), or just realize it with some custom Twig loader?
#EDIT
Problem solved! There is no way to do it "on the fly", so i extend AbstractController in custom Class, override render method and check in this method all conditions.
I've created a video about one of the major problem that I have. I need to understand the file loading architecture, how it's done when writing a class in WP plugin development (how one class knows about the existence of another class), and how this compares with WP MVC file loading architecture. It's one big question, and I went through the various smaller questions that helped me arrived at the question summary in the video in the drive link below. I'm putting the plugin code in the Google Drive folder also: https://drive.google.com/open?id=1JVSSlkSJ5pCfNojRh6jen3ax2w-HZr5d
WP side:
plugin.php has this line: $wp_filter[ $tag ]->do_action( $args );
$tag = 'init'
This calls WP_Hook->do_action, then WP_Hook->apply_filters
WP MVC side:
This then calls MvcLoader->init, which then calls the needed load_controllers/libs/models/settings/functions (only the files under the bolded folder names will be loaded)
load_controllers will use the file_includer and make all files under the [plugin app path]/controllers be required
This means that any class under the specified folders above will be auto-required for the plugin that depends on WP MVC [tested]
This also explains why if one create a helper function, following the documentation, one would put the class under helper folder, but that doesn't get auto-loaded and one will get class not found error (because helpers doesn't get loaded/not in the list above)
Upon a closer inspection, it looks like only classes extending MvcController can load any helper files (base class MvcController is the only class that has load_helper() function). The helper files need to be named xyzHelper, under helpers folder, and needs to extend MvcHelper. In the child controller class, call $this->load_helper('xyz') and the base class will automatically try to load the helper class from the helpers folder. The controller class will now have a helper object named xyz (the class name, including underscores, without the _helper suffix). One can now have access to the helper class through the controller class (in the view classes also, etc. Used like $controller->xyz->function()) [tested]
How to get the above info:
Activate an example plugin from WP MVC and navigate to a public view
Put the breakpoint in mvc_file_includer.php require_file() [I actually just run the debugger without any breakpoint and there was a deprecated function warning at the above function. I didn't think to put a breakpoint at that function previous to seeing this, and I didn't know where to put the breakpoints previous to this realization]
Look at the stack trace and try to understand
Also, in WP MVC, there are other calls that will automatically include files
An example is render_view() - This will either call the controller's, or the helper's, render_view(), which will use the file_includer to find the desired file path, and call require on that file path. Therefore, it's more like this is a dynamic-loading of files that is being used.
Now, how did MvcLoader->init() get triggered?
In the main plugin's file: wp_mvc.php, depending on if it's in the admin/public functionality view, wp_mvc_load_global_functionality is called with the needed parameter. One of the actions in that function is add_action('init', array($loader, 'init')), which triggers the init hook for the MvcAdminLoader, which is a child of MvcLoader [tested by commenting out the add_action and it no longer works]
I would like to write a few action helper but it seems that I am not doing it well.
First of all, in my Bootstrap file, I am doing the following:
Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH.'/controllers/helpers/My/Helper/', 'My_Helper');
In this directory, I have the following tree:
My/Helper/
- Fileupload/
- Abstract.php
- Xhr.php
- Fileupload.php
In my Controller, I successfully call the fileupload helper (in the class My_Helper_Fileupload):
$res = $this->_helper->fileupload($directory);
But in the constructor of this helper, I am trying get another helper (in the class My_Helper_Fileupload_Xhr) iwth:
Zend_Controller_Action_HelperBroker::getStaticHelper('Fileupload_Xhr');
which lead me to the error
Action Helper by name FileuploadXhr not found
What am I doing wrong? I tried a lot of stuff but I can't figure out what's wrong...
Moreover, after a few test, it seems that in my constructor of the fileupload helper, I am getting NULL when I call the getActionController method. Isn't it supposed to be set automatically?
The helper broker will remove underscores as part of its process of "normalizing" the helper name you give it. It only deals with CamelCased helper names, so your Fileupload_Xhr gets converted to FileuploadXhr.
The Zend_Loader that ends up being responsible for finding and loading the right PHP file uses underscores to determine when it should add a directory separator.
If you combine these two things, the practical upshot is that you can't have a nested folder structure under any path for the action helper broker. All the helper classes you want to be able to load for any path added with addPath must reside directly under the given path, with no intervening subfolders.
The simple solution is to move your helper from My/Helper/Fileupload/Xhr.php to My/Helper/FileuploadXhr.php.
Assuming you are using My as your appnamespace - which is what I usually do; Application is too long to type - then this is one way to do it.
In Bootstrap:
Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH .'/controllers/helpers', 'My_Controller_Helper');
Name your helper class as My_Controller_Helper_SomeHelper and store it in the file application/controllers/helpers/SomeHelper.php.
Invoke in a controller using:
$this->_helper->someHelper()
If your appnamespace is different, the just replace My_ with your appnamespace.
How do I eliminate the need for the "Controller" suffix in the filename of a Zend Framework controller? It just gets tiresome to keep typing that suffix in when creating controllers, and meanwhile the file is already in a controllers folder so it's superfluous.
For instance, by default the homepage on a site goes to "controllers/IndexController.php". What if I want it to go to "controllers/Index.php"?
The latter portion of the class name is hardcoded to "Controller" in Zend_Controller_Dispatcher_Abstract::formatControllerName().
To change it, you'd have to create a custom Dispatcher class that implements Zend_Controller_Dispatcher_Interface and override the formatControllerName() function. Then assign an instance of your new Dispatcher to the front controller in your bootstrap script with $frontController->setDispatcher() before you call dispatch().
Why would you need to change the format of a controller class name anyway? It's not like that PHP file appears in a request URL anywhere.
Sounds like you're bikeshedding.
I have several view Partials (like paginator partial) which I want them to be available
To all view scripts in my application.
Is there a directory I can put partial vies in, and they will be available to all?
Or, how do I define such a directory?
You can create a folder in the views folder with any name and from your views you would call a partial using the following code and as the second argument pass an array of values which would be used within the partial.
$this->partial('your-partial-dir/your-partial.phtml', array('var'=>$myVar));
Note that you can include and render any partial view from any view referring to the views folder as the root. And you would access variables within the partial using the $this identifier to refer to each variable as though it was a member of the partial object:
//your-partial.phtml file
$this->var;
Alternatively you can also create a view helper - a view helper is a class that is declared and extended from the Zend_View_helper class and can be called from a view as though it was a member function.
For more on view helpers you can refer to this write up on Zend http://devzone.zend.com/article/3412-View-Helpers-in-Zend-Framework