controller action with different render view base on contest page - yii2

I have a controller action that get called in different places in my app.
Is it possible to render different view based on caller page?
public function actionMyaction($id){
// blar, blar
if (/* if I'm calling this action from index */) {
return $this->redirect(['index']);
}
else{
return $this->redirect(['update']);
}
}

Try something like,
if($model->isNewRecord)
return $this->render('create', ['model' => $model]);
else
return $this->render('update', ['model' => $model]);

Yes, by "caller page" I assume you mean the referrer.
class ExampleController extends Controller {
private function handleRedirect() {
$referrer = $_SERVER["HTTP_REFERER"];
if (!empty($referrer)) {
switch ($referrer) {
case "blar": return $this->redirect("blar");
}
}
$this->redirect("foo");
}
public function actionMyaction() {
// ... blar
return $this->handleRedirect();
}
}
If not, then maybe you mean the action is the differentiator:
class ExampleController extends Controller {
private function handleRedirect() {
switch (\Yii::$app->controller->action->id) {
case "myaction": return $this->redirect("blar");
}
$this->redirect("foo");
}
public function actionMyaction() {
// ... blar
return $this->handleRedirect();
}
}
If not again then please clarify your question!

You can use:
$this->redirect(Yii::$app->request->referrer);
or:
$this->goBack(Yii::$app->request->referrer);
As per the PHP documentation, $_SERVER["HTTP_REFERER"] is not always to be trusted:
PHP $_SERVER
Edit: of course, you get the added benefit that the Yii team can actually spell "referrer", and your brain doesn't have to scream about the mis-spelt HTTP version.

Maybe you need something like this:
public function actionMyaction($id){
// blar, blar
$referrer = Yii::$app->request->referrer;
$action = explode('/', $referrer);
switch (end($action)) {
case 'index':
return $this->redirect(['index']);
break;
case 'update':
return $this->redirect(['update']);
break;
default:
break;
}
}

Related

Laravel user model not being process in JSON response

I have a Laravel 5.8 API where the JSON response for a user collection works as expected but fails for a model.
namespace App\Traits;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
trait ApiResponder
{
private function successResponse($data, $code)
{
return response()->json($data, $code);
}
protected function errorResponse($message, $code)
{
return response()->json(['error' => $message, 'code' => $code], $code);
}
protected function showAll(Collection $collection, $code = 200)
{
return $this->successResponse(['data' => $collection], $code);
}
protected function showOne(Model $model, $code = 200)
{
return $this->successResponse(['data' => $model], $code);
}
}
Below are the controller methods calling for the response.
public function index()
{
$users = User::all();
return $this->showAll($users);
}
public function update(Request $request, $id)
{
$user = User::findOrFail($id);
$rules = [
'email' => 'email|unique:users,email,' . $user->id,
'password' => 'min:6|confirmed'
];
if ($request->has('name')) {
$user->name = $request->name;
}
if ($request->has('email') && $user->email != $request->email) {
$user->verififed = User::UNVERIFIED_USER;
$user->verififcation_token = User::generateVerificationCode();
$user->email = $request->email;
}
if ($request->has('password')) {
$user->password = bcrypt($request->password);
}
if (!$user->isDirty()) {
return $this->errorResponse('You need to specify a change to update', 422);
}
$user->save();
$this->showOne($user);
}
The index method handle as a collection works perfectly, but the update method using the model returns empty (no content at all). I have confirmed that the $data variable does contain the model information as expected as I can print a JSON encode that displays the result I want. It's just not working in response()->json() for some reason.
Very complex code for what it actually does.
Here you have the problem, needless to say to render the response, you need a return.
$user->save();
$this->showOne($user);
}
should be:
$user->save();
return $this->showOne($user);
}
Bonus: I would look into response transformation for future references see Eloquent Resources or Fractal. Instead of doing to much if logic, you can use FormRequest to validate the input.

ZF2AuthAcl Module doesnt work out of the box

I picked up this ZF2AuthAcl module to make my life easier. For some reason it does not work out of the box. As soon as i activate it in Zend2 Application.config it takes over the whole site. Meaning it goes straight to login on any page i have. There is a "white list" and i tried to add pages to this in an array and it does not seem to work. I will show the Acl page that it has with the "white list" maybe i did not add them correctly or there is a better way. It is data driven also. Has anyone used this with success or know about it?
The author is the one who told me it probably has to do with the white list.
The area that i added to looked like this:
public function initAcl()
{
$this->roles = $this->_getAllRoles();
$this->resources = $this->_getAllResources();
$this->rolePermission = $this->_getRolePermissions();
// we are not putting these resource & permission in table bcz it is
// common to all user
$this->commonPermission = array(
'ZF2AuthAcl\Controller\Index' => array(
'logout',
'index'
),
);
$this->_addRoles()
->_addResources()
->_addRoleResources();
}
This is the whole thing with parts i added.
namespace ZF2AuthAcl\Utility;
use Zend\Permissions\Acl\Acl as ZendAcl;
use Zend\Permissions\Acl\Role\GenericRole as Role;
use Zend\Permissions\Acl\Resource\GenericResource as Resource;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class Acl extends ZendAcl implements ServiceLocatorAwareInterface
{
const DEFAULT_ROLE = 'guest';
protected $_roleTableObject;
protected $serviceLocator;
protected $roles;
protected $permissions;
protected $resources;
protected $rolePermission;
protected $commonPermission;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
return $this;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function initAcl()
{
$this->roles = $this->_getAllRoles();
$this->resources = $this->_getAllResources();
$this->rolePermission = $this->_getRolePermissions();
// we are not putting these resource & permission in table bcz it is
// common to all user
$this->commonPermission = array(
'ZF2AuthAcl\Controller\Index' => array(
'logout',
'index'
),
'Frontend\Controller\Index' => array(
'index'
),
'Blog\Controller\Blog' => array(
'blog',
'list',
'view',
'UsMap',
'maps'
)
);
$this->_addRoles()
->_addResources()
->_addRoleResources();
}
public function isAccessAllowed($role, $resource, $permission)
{
if (! $this->hasResource($resource)) {
return false;
}
if ($this->isAllowed($role, $resource, $permission)) {
return true;
}
return false;
}
protected function _addRoles()
{
$this->addRole(new Role(self::DEFAULT_ROLE));
if (! empty($this->roles)) {
foreach ($this->roles as $role) {
$roleName = $role['role_name'];
if (! $this->hasRole($roleName)) {
$this->addRole(new Role($roleName), self::DEFAULT_ROLE);
}
}
}
return $this;
}
protected function _addResources()
{
if (! empty($this->resources)) {
foreach ($this->resources as $resource) {
if (! $this->hasResource($resource['resource_name'])) {
$this->addResource(new Resource($resource['resource_name']));
}
}
}
// add common resources
if (! empty($this->commonPermission)) {
foreach ($this->commonPermission as $resource => $permissions) {
if (! $this->hasResource($resource)) {
$this->addResource(new Resource($resource));
}
}
}
return $this;
}
protected function _addRoleResources()
{
// allow common resource/permission to guest user
if (! empty($this->commonPermission)) {
foreach ($this->commonPermission as $resource => $permissions) {
foreach ($permissions as $permission) {
$this->allow(self::DEFAULT_ROLE, $resource, $permission);
}
}
}
if (! empty($this->rolePermission)) {
foreach ($this->rolePermission as $rolePermissions) {
$this->allow($rolePermissions['role_name'], $rolePermissions['resource_name'], $rolePermissions['permission_name']);
}
}
return $this;
}
protected function _getAllRoles()
{
$roleTable = $this->getServiceLocator()->get("RoleTable");
return $roleTable->getUserRoles();
}
protected function _getAllResources()
{
$resourceTable = $this->getServiceLocator()->get("ResourceTable");
return $resourceTable->getAllResources();
}
protected function _getRolePermissions()
{
$rolePermissionTable = $this->getServiceLocator()->get("RolePermissionTable");
return $rolePermissionTable->getRolePermissions();
}
private function debugAcl($role, $resource, $permission)
{
echo 'Role:-' . $role . '==>' . $resource . '\\' . $permission . '<br/>';
}
}
06/10/2016 Additional information
I have also found that this ACL page is not in any of the pages in the module. The functions are not called out anywhere in any page nor is it "use" on any page. So how is it supposed to work?
Update 06/10/2017 - Area that has been fixed.
I have found where this is used in the module.php there is a whitelist that the pages have to be added too. Below is where you add them.
$whiteList = array(
'Frontend\Controller\Index-index',
*Add whatever modules/controller/action you do not want included*
'ZF2AuthAcl\Controller\Index-index',
'ZF2AuthAcl\Controller\Index-logout'
);
Above is the conclusion of my issue. I stumbled upon it. I did not look in the module.php file. That is where the answer was.
Here is a general implementation of Zend ACL. I followed this one. If you wish you can follow this one too.
Create a file named module.acl.php in the config/ folder of your module. This file contains configuration for roles and permissions. Modify this script as you need.
ModuleName/config/module.acl.php
return array(
'roles' => array(
'guest',
'member'
),
'permissions' => array(
'guest' => array(
// Names of routes for guest role
'users-signup',
'users-login'
),
'member' => array(
// Names of routes for member role
// Add more here if you need
'users-logout'
)
)
);
You need to import the following three classes and define and initialize some methods in the Module.php.
ModuleName/Module.php
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\GenericRole;
use Zend\Permissions\Acl\Resource\GenericResource;
// Optional; use this for authentication
use Zend\Authentication\AuthenticationService;
Now lets create methods that will deploy ACL and check roles and permissions.
Module::initAcl()
public function initAcl(MvcEvent $e)
{
// Set the ACL
if ($e->getViewModel()->acl == null) {
$acl = new Acl();
} else {
$acl = $e->getViewModel()->acl;
}
// Get the roles and permissions configuration
// You may fetch configuration from database instead.
$aclConfig = include __DIR__ . '/config/module.acl.php';
// Set roles
foreach ($aclConfig['roles'] as $role) {
if (!$acl->hasRole($role)) {
$role = new GenericRole($role);
$acl->addRole($role);
} else {
$role = $acl->getRole($role);
}
// Set resources
if (array_key_exists($role->getRoleId(), $aclConfig['permissions'])) {
foreach ($aclConfig['permissions'][$role->getRoleId()] as $resource) {
if (!$acl->hasResource($resource)) {
$acl->addResource(new GenericResource($resource));
}
// Add role to a specific resource
$acl->allow($role, $resource);
}
}
}
// Assign the fully prepared ACL object
$e->getViewModel()->acl = $acl;
}
Module::checkAcl()
public function checkAcl(MvcEvent $e) {
// Get the route
$route = $e->getRouteMatch()->getMatchedRouteName();
// Use this if you have authentication set
// Otherwise, take this off
$auth = new AuthenticationService();
// Set role as you need
$userRole = 'guest';
// Use this if you have authentication set
// Otherwise, take this off
if ($auth->hasIdentity()) {
$userRole = 'member';
$loggedInUser = $auth->getIdentity();
$e->getViewModel()->loggedInUser = $loggedInUser;
}
// Check if the resource has right permission
if (!$e->getViewModel()->acl->isAllowed($userRole, $route)) {
$response = $e->getResponse();
// Redirect to specific route
$response->getHeaders()->addHeaderLine('Location', $e->getRequest()->getBaseUrl() . '/404');
$response->setStatusCode(404);
return;
}
}
Now call those above methods on the onBootstrap() method in your Module.php. Initialize Module::initAcl() and check resource permission by adding Module::checkAcl() to the route event.
Module::onBootstrap()
public function onBootstrap(MvcEvent $e)
{
$this->initAcl($e);
$e->getApplication()->getEventManager()->attach('route', array($this, 'checkAcl'));
}
Let us know it helps you or not!

Cakephp3: How can I return json data?

I am having a ajax post call to a cakePhp Controller:
$.ajax({
type: "POST",
url: 'locations/add',
data: {
abbreviation: $(jqInputs[0]).val(),
description: $(jqInputs[1]).val()
},
success: function (response) {
if(response.status === "success") {
// do something with response.message or whatever other data on success
console.log('success');
} else if(response.status === "error") {
// do something with response.message or whatever other data on error
console.log('error');
}
}
});
When I try this I get the following error message:
Controller actions can only return Cake\Network\Response or null.
Within the AppController I have this
$this->loadComponent('RequestHandler');
enabled.
the Controller function looks like this:
public function add()
{
$this->autoRender = false; // avoid to render view
$location = $this->Locations->newEntity();
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
return json_encode(array('result' => 'success'));
} else {
//$this->Flash->error(__('The location could not be saved. Please, try again.'));
return json_encode(array('result' => 'error'));
}
}
$this->set(compact('location'));
$this->set('_serialize', ['location']);
}
What do I miss here? Is there any additional settings needed?
Instead of returning the json_encode result, set the response body with that result and return it back.
public function add()
{
$this->autoRender = false; // avoid to render view
$location = $this->Locations->newEntity();
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
$resultJ = json_encode(array('result' => 'success'));
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
} else {
//$this->Flash->error(__('The location could not be saved. Please, try again.'));
$resultJ = json_encode(array('result' => 'error', 'errors' => $location->errors()));
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
}
}
$this->set(compact('location'));
$this->set('_serialize', ['location']);
}
Edit (credit to #Warren Sergent)
Since CakePHP 3.4, we should use
return $this->response->withType("application/json")->withStringBody(json_encode($result));
Instead of :
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
CakePHP Documentation
Most answers I've seen here are either outdated, overloaded with unnecessary information, or rely on withBody(), which feels workaround-ish and not a CakePHP way.
Here's what worked for me instead:
$my_results = ['foo'=>'bar'];
$this->set([
'my_response' => $my_results,
'_serialize' => 'my_response',
]);
$this->RequestHandler->renderAs($this, 'json');
More info on RequestHandler. Seemingly it's not getting deprecated anytime soon.
UPDATE: CakePHP 4
$this->set(['my_response' => $my_results]);
$this->viewBuilder()->setOption('serialize', true);
$this->RequestHandler->renderAs($this, 'json');
More info
there are few things to return JSON response:
load RequestHandler component
set rendering mode as json
set content type
set required data
define _serialize value
for example you can move first 3 steps to some method in parent controller class:
protected function setJsonResponse(){
$this->loadComponent('RequestHandler');
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
}
later in your controller you should call that method, and set required data;
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
$success = $this->Locations->save($location);
$result = [ 'result' => $success ? 'success' : 'error' ];
$this->setJsonResponse();
$this->set(['result' => $result, '_serialize' => 'result']);
}
also it looks like you should also check for request->is('ajax); I'm not sure about returning json in case of GET request, so setJsonResponse method is called within if-post block;
in your ajax-call success handler you should check result field value:
success: function (response) {
if(response.result == "success") {
console.log('success');
}
else if(response.result === "error") {
console.log('error');
}
}
In the latest version of CakePHP $this->response->type() and $this->response->body() are deprecated.
Instead you should use $this->response->withType() and $this->response->withStringBody()
E.g:
(this was pinched from the accepted answer)
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
$resultJ = json_encode(array('result' => 'success'));
$this->response = $this->response
->withType('application/json') // Here
->withStringBody($resultJ) // and here
return $this->response;
}
}
Relevant Documentation
When you return JSON data you need to define the data type and response body information like below:
$cardInformation = json_encode($cardData);
$this->response->type('json');
$this->response->body($cardInformation);
return $this->response;
In you case just change this return json_encode(array('result' => 'success')); line with below code:
$responseResult = json_encode(array('result' => 'success'));
$this->response->type('json');
$this->response->body($responseResult);
return $this->response;
RequestHandler is not required to send json.
In controller's action:
$this->viewBuilder()->setClassName('Json');
$result = ['result' => $success ? 'success' : 'error'];
$this->set($result);
$this->set('_serialize', array_keys($result));
As of cakePHP 4.x.x the following should work assuming that your controller and routes are set as shown below:
controller: <your_project_name>/src/Controller/StudentsController.php
public function index()
{
$students = $this->Students->find('all');
$this->set(compact('students'));
$this->viewBuilder()->setOption('serialize',['students']);
}
Routes: <your_project_name>/config/routes.php
<?php
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;
/** #var \Cake\Routing\RouteBuilder $routes */
$routes->setRouteClass(DashedRoute::class);
$routes->scope('/', function (RouteBuilder $builder) {
$builder->setExtensions(['json']);
$builder->resources('Students');
$builder->fallbacks();
});
Run bin/cake server and visit http://localhost:8765/students.json using postman/insomnia or just the normal browser.
See further documentation for setting up Restful controllers and Restful Routing
Don't forget to set the method to GET on postman and insomnia.
Though I'm not a CakePHP Guru, in my case i'm using cake > 4 and I need some results by ajax call. For this, from my controller i wrote,
echo json_encode(Dashboard::recentDealers()); die;
and in my JS file i just need to parse the data using
JSON.parse(data)
The ajax call like
$.get('/recent-dealers', function (data, status) {
console.log (JSON.parse(data)); });
});

Yii2 Dynamic Form update Action is not working

I like to explain my problem clearly,
Am using wbraganca/yii2-dynamicform
Here create action is working perfectly, but in update action
In the code which i marked, i don't know what i need to do, i dont have such field (addresses) in customer table. am stuck on that.
suppose if i create a variable in model like public $addressess, it makes me the reload the table again, and that cause while update the same form, data's getting reload and form viewing as empty without empty,
if create a function on that name, i don't know what to write on that..
Am simply using code like this
public function getaddressess()
{
}
Create Action Code
public function actionCreate()
{
$modelCustomer = new Customer;
$modelsAddress = [new Address];
if ($modelCustomer->load(Yii::$app->request->post())) {
$modelsAddress = Model::createMultiple(Address::classname());
Model::loadMultiple($modelsAddress, Yii::$app->request->post());
// ajax validation
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ArrayHelper::merge(
ActiveForm::validateMultiple($modelsAddress),
ActiveForm::validate($modelCustomer)
);
}
// validate all models
$valid = $modelCustomer->validate();
$valid = Model::validateMultiple($modelsAddress) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $modelCustomer->save(false)) {
foreach ($modelsAddress as $modelAddress) {
$modelAddress->customer_id = $modelCustomer->id;
if (! ($flag = $modelAddress->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $modelCustomer->id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}
return $this->render('create', [
'modelCustomer' => $modelCustomer,
'modelsAddress' => (empty($modelsAddress)) ? [new Address] : $modelsAddress
]);
}
Help me to sort out this problem
$modelsAddress=$modelCustomer->addresses in that example mean array of related Address() instances
public function actionCreate()
{
$modelCustomer = new Customer;
$modelsAddress = $this->getaddressess($modelCustomer->id);
//...................
}
public function getaddressess($id)
{
$model = Address::find()->where(['id' => $id])->all();
return $model;
}
from
public function getaddressess($id)
{
$model = Address::find()->where(['id' => $id])->all();
return $model;
}
Shared above you will also need to add
on your Update view file :
'model' => $model,
'modelsAddress'=>$modelsAddress,
Hope this helps. It worked for me
It should be getAddresses() instead of getaddresses() (although both could work, I'd go with the first one to meet conventions). Or you could set a public $addresses if you don't need extra encapsulation.
suppose if i create a variable in model like public $addressess, it makes me the reload the table again, and that cause while update the same form, data's getting reload and form viewing as empty without empty,
I think you have a validation issue - no validator to mark the field as safe and you see it as empty after posting.
Add public $addresses to your Customer model.
Add "addresses" to your validation rules as safe (or more appropriate validator). This way after posting the form, it probably won't render empty.
This line code ---> $modelsAddress = $modelCustomer->addresses;
is get from model for customer at line ---> public function getAddresses()
this public function line code is code for get array related table from active record method on yii2.
$modelCustomer->addresses the word addresses should come from the $modelCustomer model you must have a relationship to the other table where you add the multiple values. In my example described in the video I have two tables po table and po_items table po_items table has foreign key of po_id. So when you make the Models using gii you will get a relationship in the model that is what you have to use instead of the addresses.
the relationship according my database should be - poItems you will see this at line 14
Add this to Customer Model
public function getAddresses(){
return $this->hasMany(Address::className(), ['id' => 'id']);
}
enter image description hereIn Po.php models:
public function getPoItems()
{
return $this->hasMany(PoItem::className(), ['po_id' => 'id']);
}
In PoController.php
public function actionUpdate($id)
{
$model = $this->findModel($id);
//$modelsPoItem = [new PoItem];
$modelsPoItem = $model->poItems;
if ($model->load(Yii::$app->request->post()) && $model->save())
{
$oldIDs = ArrayHelper::map($modelsPoItem, 'id', 'id');
$modelsPoItem = Model::createMultiple(PoItem::classname(), $modelsPoItem);
Model::loadMultiple($modelsPoItem, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsPoItem, 'id', 'id')));
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsPoItem) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs))
{
PoItem::deleteAll(['id' => $deletedIDs]);
}
foreach ($modelsPoItem as $modelPoItem)
{
$modelPoItem->po_id = $model->id;
if (! ($flag = $modelPoItem->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}
return $this->render('update', [
'model' => $model,
'modelsPoItem' => (empty($modelsPoItem)) ? [new PoItem] : $modelsPoItem
]);
}

How to force convert json action in Cakephp Rest

i need force convert json action in cakephp rest response. When i set '_serialize' like this
$this->set(array('message' => $lessons, '_serialize' => array('message')));
it works but some turkish characters view in unicode like "\u00e7al\u0131\u015fma alan\u0131".
It's solution is render data with json_encode($data, JSON_UNESCAPED_UNICODE) but cakephp render it automatically. How to force json_encode with JSON_UNESCAPED_UNICODE ?
Sorry for bad English.
in cakePHP 3 you can say in controller:
$this->set('_jsonOptions', JSON_UNESCAPED_UNICODE);
$this->set('_serialize', ['zones']);
which will override the options used.
JsonView doesn't accept options
There's no way to inject options in the json_encode() call invoked by JsonView, as it's hard coded optionless in the _serialize() method like this:
protected function _serialize($serialize) {
// ...
if (version_compare(PHP_VERSION, '5.4.0', '>=') && Configure::read('debug')) {
return json_encode($data, JSON_PRETTY_PRINT);
}
return json_encode($data);
}
Use a custom/extended view
So if you want to use automatic serialization, then you have to create your own/an extended view that either accepts options, or hard codes your desired options.
Here's an (untested) example with hard coded options. The _serialize() method is basically just a copy with the JSON_UNESCAPED_UNICODE option added:
App::uses('JsonView', 'View');
class MyJsonView extends JsonView {
protected function _serialize($serialize) {
if (is_array($serialize)) {
$data = array();
foreach ($serialize as $alias => $key) {
if (is_numeric($alias)) {
$alias = $key;
}
if (array_key_exists($key, $this->viewVars)) {
$data[$alias] = $this->viewVars[$key];
}
}
$data = !empty($data) ? $data : null;
} else {
$data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
}
if (version_compare(PHP_VERSION, '5.4.0', '>=') && Configure::read('debug')) {
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
}
See also http://book.cakephp.org/2.0/en/views.html#creating-your-own-view-classes
I haven't tested this myself, so it's just from the top of my head.
You could write your own View class extending JsonView and override the _serialize method.
https://github.com/cakephp/cakephp/blob/4e8e266754a25748f481b2f567e45f767808be53/lib/Cake/View/JsonView.php#L131
<?php
App::uses('JsonView', 'View');
class MyCustomView extends JsonView {
protected function _serialize($serialize) {
if (is_array($serialize)) {
$data = array();
foreach ($serialize as $alias => $key) {
if (is_numeric($alias)) {
$alias = $key;
}
if (array_key_exists($key, $this->viewVars)) {
$data[$alias] = $this->viewVars[$key];
}
}
$data = !empty($data) ? $data : null;
} else {
$data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
}
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
}
And then in your controller do something like
<?php
App::uses('MyCustomView', 'View');
class SomeController extends AppController {
public function someMethod() {
$this->viewClass = 'MyCustomView';
// What ever you normally do
}
}