Laravel4 get section array in Controller/Router layer from a Blade template - php

I need your help.
I've just found out that the class \Illuminate\View\Environment has a protected array $sections and a method to get it getSections() but it returns an empty array.
Here's how I tried to get it:
$view = View::make('pages');
$env = $view->getEnvironment();
$env->make('pages');
print($env->getSections());
And the result is Array( )
Where did I go wrong? Any suggestion will be appreciated.

That's because when you call $env->make('pages'), the view isn't immediately processed. It's only processed when the render method on the $view object is called, which is done automatically when you return it as a response, via the __toString() method. The problem, though is that just after the page is rendered, still inside the render method, the $sections variable is cleared, using the flushSections method. So you actually never have access to it.
You could try to fool it if you call the incrementRender method before making the view, then make and render the view, get the sections and then finally decrementRender() and flushSections(), but this could bring unexpected results. Something like this:
// Fool it
$env->incrementRender();
$env->make('pages')->render();
$sections = $env->getSections();
// Clear it
$env->decrementRender();
$env->flushSections();

Related

Get data from model to every view using OOP and DRY

I have a piece of data I want passed to every view. I am using CodeIgniter 3 and have PHP 7 available to me. The current way I do it is using something like this in every function.
$data['foobar'] = $this->general_model->foobar();
// More code
$this->load->view('homepage', $data);
I'd prefer not to have to call $data['foobar'] = $this->general_model->foobar(); on every single function.
I've tried many approaches to fix this without resorting to anything that makes the code too goofy. I've tried constructors, autoload, and hooks. The problem in each case boils down to the fact that $data is local to each function. The best I've gotten is usually something like this.
$data['foobar'] = $this->foobar;
// More code
$this->load->view('homepage', $data);
This is slightly nicer, but it still results in me placing this line in every function.
I'd like my functions to in someway inherit $data with the index foobar already set. I'd prefer to avoid a solution that requires every function receiving $data as a parameter. How can I accomplish this?
Option 1:
Not sure if you have tried this but you could set $data as a property of your class
protected $data = [];
Then in your constructor set it.
$this->data['foobar'] = $this->general_model->foobar();
This would mean your $data becomes accessible to all your methods in your controller and you would need to refer to them as $this->data['data_name'] and use it in a view like
$this->load->view('homepage', $this->data);
Option 2:
A second way is to create a method like render() which is common to all your methods that load views and replaces your existing view calls.
So you would have something like...
public function one_of_my_methods(){
$data['content'] = 'This is content 1';
$this->render('test_view',$data); // Call the new view handler
}
// All methods using views now call this to load the final view
public function render($view,$data){
$data['foobar'] = 'I am common'; // DRY
$this->load->view($view, $data);
}

Silverstripe customize controller data/variables

I'm trying to return search results to a new controller than where the search action was performed from. Problem is Results is never accessible from CustomSearchResultPage.ss. I've added inline comments for what I think is happening, am I right in my thinking here?
// Customise content with results
$response = $this->customise(array(
'Results' => $results ? $results->getResults() : '',
));
if ($results) {
$response = $response->customise($results);
}
// Use CustomSearchResultPage.ss template
$templates = array('CustomSearchResultPage', 'Page');
// Create a new CustomSearchResultPage page
$page = CustomSearchResultPage::get_one('CustomSearchResultPage');
// Build a controller using the CustomSearchResultPage
$controller = CustomSearchResultPage_Controller::create($page);
// Add the custom data to the newly minted controller
$result = $controller->customise($response);
// Return the controller and tell it how to render
return $result->renderWith($templates);
The page seems to render as expected just the variable is always empty...
Your explanation is a little hard to follow I'm afraid. So I'm answering for what I can ascertain as below:
Performing a search. This requires loading a controller to do as such.
Customising the current controller with the results
RE-customising the current controller with itself.
Setting the template for the current (double customised) controller.
Disregarding all of the above.
Fetching a random page (or an empty record).
Creating a controller for the empty page.
Customising the new controller with the customised controller of the current controller customised with itself.
Returning that page, which shows no results.
You need only stop at step 4 (skip step 3), and return the customisation ($response).
If there is some reason you think you need another controller however (which seems superflous, but who knows), creating and then customising that one (only) before returning it would be better.
Being that you have only used this second controller for rendering a result, the URL will not have changed or anything. The whole thing seems beyond requirements.
A much more simple way to render a result from this action would probably be:
return $this
->customise(['Results' => $results ? $results->getResults() : null])
->renderWith(['CustomSearchResultPage', 'Page']);
(from the top of my head, may need a little refining).

CodeIgniter, Accessing class property after page reloads, is it possible?

I have a CI page that will load to a div in view file, using jQuery. Using switch(page_parameter), I control what is showing from the page.
When I call the page for 3rd time, I set a value to the class array.
But when I call the 4th time, the array become empty.
I was wondering, is it actually possible to use the class property to store value that can be used after page re-access? Or something missing in my head?
I know that using session is not a good idea, since the real array is a big chunk of serialized xml.
Here's my code:
class MyClass extends MY_Controller
{
public static $pitems = array();
function Hotel(){
parent::MY_Controller();
}
function new_campaign(){
$params = $this->uri->uri_to_assoc();
switch($params['step']){
case '3' : self::$pitems = array("test","another"); //here the class array was set successfully
$this->load->view('viewer');
break;
case '4' : print_r(self::$pitems); //here the array is empty
break;
}
}
In the viewer page, there's a call to the page:
Next page
Same issue also with $this->
What am i missing here?
Thanks in advance~
edit:
I saw a script that has similar scenario. it successfully reused the variable set in the constructor, instead of treating it as a class variable. i'll look thorough to confirm this, but for now, i'll close this thread. Thanks Chris for sharing.
Im not really sure what your trying to do but I have users jQuery post()/get()/ajax() many of times in CI and have had no problems. So despite not knowing or understanding what your trying to do. I thought I'd at least say I know loading data without refresh in CI through something like jQuery isn't an issue. Example on system I built on CI had a twitter like feed of tweets where jQuery on a timer was polling for new data and coming back with it each time accordingly if something new was to be shown.

Using only layout from a controller

how do I make available some data for a layout/layout.phtml script without having to create a view script from a controller?
I've tried the following in indexAction function, but it does not work. When I do not create the view script I get an error. I could created empty one, but I don't like this solution much. Any better ideas?
$this->layout->content = "foo"
$this->_helper->viewRenderer->setNoRender(true);
Thanks in advance
You don't actually render some data you make the data available and then choose which script to render. Don't confuse the terminology.
What you have done there is stopped any script from being rendered by using the :
$this->_helper->viewRenderer->setNoRender(true);
When you do
$this->layout->content = "foo";
You are setting the property content, which you then neeed to make use in your layout script.
So then in your layout.phtml script (which I hope you have already configured to render by efault) you then just do this
echo $this->content
Notice that I don't actually use $this->layout because when you are inside the layout, $this equal $this->layout. The same goes for $this->view->foo is $this->foo inside your view.
I hope this helps.
Any questions just ask.

Zend Framework - Passing a variable within a controller for an ajax call

Hi out there in Stackland! Here's my problem:
I want to use my Zend controller to load an array from a database, and then pass it to javascript. I've decided the best way to do this is to use ajax to ask the controller for it's array, encode it in json, and then pass it down. However, I don't know how to pass the variable I loaded in my first action to the action that will pass it down when it gets called via ajax.
The original action which produces the view
public function indexAction()
{
$storeid = $this->getStoreId();
if(!$storeid)
{
$this->_forward('notfound');
return;
}
$store = $this->_helper->loadModel('stores');
$store->getByPrimary($storeid);
}
The action that will be called via ajax
public function getdataAction()
{
$this->_helper->Layout->disableLayout(); // Will not load the layout
$this->_helper->viewRenderer->setNoRender(); //Will not render view
$jsonResponse = json_encode($store);
$this->getResponse()->setHeader('Content-Type', 'application/json')
->setBody($jsonResponse);
}
What I want is to pass $store in indexAction to getdataAction so it can send store as the jsonResponse. Note, these are called at two different times.
Things I have tried that haven't worked:
setting $this->getRequest()->setParam('store', $store) in indexAction, and then using $this->getRequest()->getParam('store'), in getdataAction. I presume this hasn't worked because they're different http requests, so attaching a new param is useless.
using protected $_store in the controller itself, and then saving to it with indexAction, and using it in getdataAction. I'm not really sure why this isn't working.
Is there a good way to pass a variable in this manner? Is there a way to pass a variable between different controllers?(I assume the answer to one is the answer to the other). Could I store it in a controller helper? Do I have to use a session, which I know would work but seems unnecessary? Is there a better way to pass variables to javascript? Am I asking too many questions? Any help would be outstanding. Thanks.
Maybe I'm reading the question wrong, but you should be able to just move $store into the constructor:
public function __construct() {
$store = $this->_helper->loadModel('stores');
$store->getByPrimary($storeid);
}
and have it accessible in all *Action methods. Using sessions seems out of whack for this.
(disclaimer: I'm pretty new to ZF, so I'm interested in other answers found here, and have not tested the below!)
In your view, where you put the ajax call, you will probably address it like:
(See ZF Documentation)
<?= $this->ajaxLink("Example 2",
"/YourController/getdata",
array('update' => '#content',
'class' => 'someLink'),
array('store' => $this->store)); ?>
Notice that in your indexAction, you store the store via:
$this->view->store = $storeid;
Of course, you should note that a web-user could modify the store parameter as it is passed through via an URL.
It would be better architecture to simply add a method to your IndexController, a helper, or somewhere, that returns an instance of Store. Use that method within your indexAction, and your getdataAction (would be more meaningful to call it ajaxAction). Also, you're forgetting to call sendResponse() (remember, you disabled autoRender):
private function indexAction()
{
$this->getStore();
//blah blah
}
private function getStore()
{
$storeid = $this->getStoreId();
if(!$storeid)
{
$this->_forward('notfound');
return;
}
$store = $this->_helper->loadModel('stores');
$store->getByPrimary($storeid);
return $store;
}
public function ajaxAction()
{
$this->_helper->Layout->disableLayout(); // Will not load the layout
$this->_helper->viewRenderer->setNoRender(); //Will not render view
$jsonResponse = json_encode($this->getStore());
$this->getResponse()->setHeader('Content-Type', 'application/json')
->setBody($jsonResponse)
->sendResponse();
}
The manual says:
To send the response output, including
headers, use sendResponse().
http://framework.zend.com/manual/en/zend.controller.response.html
All right, for those of you who want the answer to this too, I just sucked it up and used session. I put a Zend_Session->start() in the bootstrap. I then created a plugin to add a private variable $session to each controller. Then I set $this->session to Zend_Session_Namespace. To pass something, I pass it through session, so I use $this->session->store = $store. I can then pick it up elsewhere with $this->session->store. Thanks to those who tried to help!
Just a quick addition to the comments. To output an array as JSON from within a controller, use:
$array = array('hi' => array('Hello' => 'World');
$this->_helper->json($array);
This sends the response and sets the specific headers for a JSON response

Categories