echo something after json serialize in cakePHP - php

How can I echo something at the end of the cakePHP json/xml response?
I need this in order to add JSONP support (Because i need to add the callback at the beginning and the ');' at the end
The controller uses this :
public function json() {
//...code to populate $jsonObjects
$this->set('objetos',$jsonObjects);
$this->set('_serialize', 'objetos');
}

Firstly, I'm assuming you have Routes set up to correctly handle JSON/XML responses
In your routes file:
Router::parseExtensions('json');
Secondly, you would need to make sure the call to your example uses the .json extension or the Accept header is application/json
You then check for the callback in your controller
public function json() {
//...code to populate $jsonObjects
// check for callback and set it
// note: you should do Sanitize::clean() or something like that to
// prevent code injection
if ($this->request->params['callback']) {
$this->set('callback', $this->request->params['callback']);
}
$this->set('objetos',$jsonObjects);
$this->set('_serialize', 'objetos');
}
in your view file (ex: View/Users/json/index.ctp) you should have something like this:
if (isset($callback)) {
echo $callback . '('.json_encode($objetos).')';
} else {
echo json_encode($objetos);
}
I use something similar but didn't test the exact example above so you may need to clean it up. Also make sure you clean up the callback var so you aren't leaving a security hole by outputting exactly what is in the query string parameter.

Related

How to pass a data with redirect in codeigniter

In my controller i used this way. i want to pass a variable data to my index function of the controller through redirect
$in=1;
redirect(base_url()."home/index/".$in);
and my index function is
function index($in)
{
if($in==1)
{
}
}
But I'm getting some errors like undefined variables.
How can i solve this?
Use session to pass data while redirecting. There are a special method in CodeIgniter to do it called "set_flashdata"
$this->session->set_flashdata('in',1);
redirect("home/index");
Now you may get in at index controller like
function index()
{
$in = $this->session->flashdata('in');
if($in==1)
{
}
}
Remember this data will available only for redirect and lost on next page request. If you need stable data then you can use URL with parameter & GET $this->input->get('param1')
So in the controller you can have in one function :
$in=1;
redirect(base_url()."home/index/".$in);
And in the target function you can access the $in value like this :
$in = $this->uri->segment(3);
if(!is_numeric($in))
{
redirect();
}else{
if($in == 1){
}
}
I put segment(3) because on your example $in is after 2 dashes. But if you have for example this link structure : www.mydomain.com/subdomain/home/index/$in you'll have to use segment(4).
Hope that helps.
Use session to pass data while redirecting.There are two steps
Step 1 (Post Function):
$id = $_POST['id'];
$this->session->set_flashdata('data_name', $id);
redirect('login/form', 'refresh');
Step2 (Redirect Function):
$id_value = $this->session->flashdata('data_name');
If you want to complicate things, here's how:
On your routes.php file under application/config/routes.php, insert the code:
$route['home/index/(:any)'] = 'My_Controller/index/$1';
Then on your controller [My_Controller], do:
function index($in){
if($in==1)
{
...
}
}
Finally, pass any value with redirect:
$in=1;
redirect(base_url()."home/index/".$in);
Keep up the good work!
I appreciate that this is Codeigniter 3 question, but now in 2021 we have Codeigniter 4 and so I hope this will help anyone wondering the same.
CI4 has a new redirect function (which works differently to CI3 and so is not a like for like re-use) but actually comes with the withInput() function which does exactly what is needed.
So to redirect to any URL (non named-routed) you would use:
return redirect()->to($to)->withInput();
In your controller - I emphasise because it cannot be called from libraries or other places.
In the function where you are expecting old data you can helpfully use the new old() function. So if you had a key in your original post of FooBar then you could call old('FooBar'). old() is useful because it also escapes data by default.
If however, like me, you want to see the whole post then old() isn't helpful as the key is required. In that instance (and a bit of a cheat) you can do this instead:
print'<pre>';print_r($_SESSION['_ci_old_input']['post']);print'</pre>';
CI4 uses the same flash data methods behind the scenes that were given in the above answers and so we can just pull out the relevant session data.
To then escape the data simply wrap it in the new esc() function.
More info would be very helpful, as this should be working.
Things you can check:
Is your controller named home.php? Going to redirect(base_url()."home"); shows your home page?
Make your index function public.
public function index($in) {
....
}

Capture all informations passed to a view in Laravel

I want to capture every information passed to view using the afterFilter. So I need to know:
all variables
session flash
the action executed (last action)
the view called
This is because I need to check if the request is json or not for change the response.
Currently I use afterFilter like this:
public function __construct()
{
// Here's something that happens after the request
$this->afterFilter(function() {
});
}
What I want is: use the afterFilter method in BaseController to capture all events/actions and then decide if the request is json or not.
If you need more information, comment please.
And sorry for my english
Do you need to know if JSON or if AJAX? If AJAX then just use:
if (Request::ajax())
{
//
}
You may use Request::wantsJson() to determine if the request is asking for json in return using:
// In app/filters.php
App::after(function($request, $response)
{
if($request->wantsJson()) {
//...
}
});
In this case, Laravel (through Base/Symfony class) checks if the Accept header is set and if that is application/json.

Can't get JSON input for Laravel4 POST

I am using Laravel routes to build a RESTful API. I am routing to a Controller. In it, my function "store()" (my post function) should be getting a JSON input and I'm testing it by simply returning it. I seem to be able to see the data being passed in by doing Input::get('data') but I can't do a json_decode on that. The value of the json_decode is simply null. Can anyone help me get a working example of POSTing to a route with JSON data and accessing the data?
Here's what I have:
Route
Route::post('_api/tools/itementry/items', 'ItemEntryController');
Controller
class ItemEntryController extends BaseController
{
//... other functions
public function store()
{
if(Input::has('data'))
{
$x = Input::get('data');
$data = json_decode($x);
var_dump($data);
}
}
}
I'm using a REST tester client to submit a post with the following Query string parameters:
Name: "data"
Value: { itemNumber:"test1", createdBy:"rsmith" }
This ended up being a really stupid problem. I was doing everything right, except my JSON that I was sending in the test client was formatted incorrectly. I forgot to add quotes around the key strings.
So, instead of doing { itemNumber:"test1", createdBy:"rsmith" }
I needed to do { "itemNumber":"test1", "createdBy":"rsmith" }
Now it works.

Change addActionContext() to be XML only

I've got Zend code which looks like this:
$contextSwitch->addActionContext('get', array('xml','json'))->initContext();
How can I change this so that it ONLY returns XML formatted data? SOrry, I'm new to Zend programming.!
Read the manual
public function init()
{
$this->_helper->contextSwitch()
->addActionContext('get', array('xml','json'))
->initContext();
}
public function getAction()
{
this->_helper->contextSwitch()->initContext('xml'); //will always use xml if action has xml context
//...
}
If you only ever use xml for a particular action, set the headers inside the action you want to return xml:
$this->getResponse()->setHeader('Content-type', 'text/xml');
And then process the rest of the action as you need it to. Without context switching enabled the view will be the default for the action (ie. actioname.phtml)
You will probably also want to disable your layout:
$this->_helper->layout->disableLayout();

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