Where is defined the according type for the JSON output in Zend Framework 2? - json

I activated the JsonStrategy in a ZF2 application and can get JSON output now using AcceptableViewModelSelector Controller Plugin.
It works only with the HTTP Request parameter Accept containing application/json.
Where is application/json defined as proper value for JSON output? (How) Can I define and use foo/bar instead?

Take a look here:
Zend\View\Strategy\JsonStrategy;
You can implement your own custom strategy in the same manner no problem. Much cleaner than hard coding into the controller as it can be reused.

Directly in the definition array of the accept criteria:
class SomeController extends AbstractActionController
{
protected $acceptCriteria = array(
'Zend\View\Model\JsonModel' => array(
'application/json', // <-- here
),
'Zend\View\Model\FeedModel' => array(
'application/rss+xml',
),
);
public function apiAction()
{
$viewModel = $this->acceptableViewModelSelector($this->acceptCriteria);
// Potentially vary execution based on model returned
if ($viewModel instanceof JsonModel) {
// ...
}
}
}

Related

How to convert Laravel DB data into a suitable JSON form to use it in vuejs

The attributes of laravel modal are named using underscore (_), for example :
first_name
but attributes of javascript objects are named with camelCase:
{ firstName: "..." }
And this presents a conflict, is there a solution to resolve it ?
Try to use Laravel eloquent resource pattern will do that for You.
Check this helpful documentation.
https://laravel.com/docs/8.x/eloquent-resources
Like Zrelli Mjdi mentioned it's done with Resource Collections.
I did not find a way to let this resources transform the result recursively for nested JSON-Objects, so I created a middleware (see the github-gist) for this, which should take a rather heavy toll on performance. So use it sparsely.
I'd use this middleware only temporary if your frontend demands camel-case properties. In the long run I'd modify my migrations to use camel-case fieldnames. This should, according to this reddit-thread, be possible and won't affect performance like my middleware.
Edit: The code in the gist had a bug which is now fixed.
This is about how it's done with Resource-Collections and non-nested JSON-Results:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class MyResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'userId' => $this->user_id,
'createdAt' => $this->created_at,
];
}
}
in the controller:
public function myControllerMethod(Request $request)
{
// ...
return MyResource::collection($logs)
}

Yii2 how can an model attribute is modified after load method? (like the afterFind method)

I have an attribute of the model which should be modified after it's loaded from the database.
I could extend the afterFind method, which could the convert the varchar value to a php array. So it works find.
But when the model is loaded I have no idea how to convert that varchar to the php array.
I have tried with rules but does not works:
[['languages'], 'each', 'rule' => ['string']],
or this one
[['languages'], 'safe'],
So this one works afterFind:
public function afterFind()
{
$this->languages = $this->convertToPHPArray($this->languages);
parent::afterFind();
}
By the way I have tried to extend the init or the __constructor method with this conversation, but no success, after load method the languages attribute is still a string instead of a php array.
If I understood your question, I think that you could use a property in the model:
public class Model {
public function getLanguagesArray()
{
return $this->convertToPHPArray($this->languages);
}
}
Then, use it:
$arr = $model->languagesArray;

How to make every action in a zend (1.12) controller return JSON?

I have a controller that is purely for API use (no view or layout).
I want every action to return JSON format and have the Content-Type in the response be application/json.
I could achieve the header part by using the controller postDispatch() but couldn't find a way to do json_encode() from single place (I know I can do it from every action however I wanted it to be centralized).
I have even tried to use a plugin and there to manipulate the request body but for some reason that is not clear to me it is always empty.
Currently my solution is as follows:
public function init()
{
// no Layout
$this->_helper->layout()->disableLayout();
// no views
$this->_helper->viewRenderer->setNoRender(true);
}
public function indexAction()
{
$data = array("likes","to","sleep");
echo Zend_Json::encode($data);
}
public function postDispatch()
{
$this->getResponse()->setHeader('Content-Type', 'application/json');
}
Now, if i only managed to do the echo Zend_Json::encode in one single place...
You can use the ContextSwitch action helper
The JSON context sets the 'Content-Type' response header to 'application/json', and the view script suffix to 'json.phtml'. By default, however, no view script is required. It will simply serialize all view variables, and emit the JSON response immediately.
You will need to register it within the controller.
class FooController extends \Zend_Controller_Action
{
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('list', 'json')
->addActionContext('bar', 'json')
->initContext('json'); // json arg here means that we only allow json
}
}
You would then need to pass the format parameter in the url /module/foo/bar/format/json or as a query parameter ?format=json
You can create your own controller plugin.
In preDispatch turn off layout and view renderer and in postDispatch set content-type header in response.
Next option is to assing data to view.
public function indexAction() {
$data = array("likes","to","sleep");
$this->view->assign('data', $data);
}
and in view script call json view helper <?php echo $this->json($this->data); and do not use layout.

Laravel: decode JSON within Eloquent

I need to JSON decode a certain column in my Eloquent query. Is there a way to do this without breaking all apart?
So far I have this.
public function index()
{
return Offer::all();
}
Use an accessor on the model:
public function getColumnNameAttribute($value) {
return json_decode($value);
}
or use attribute casting to tell Laravel to do it automatically:
protected $casts = [
'column_name' => 'array',
];
The array cast type is particularly useful when working with columns that are stored as serialized JSON.
Note that you may have to stop json_encodeing your data if you use casts, as Laravel will now do that step automatically as well.

ZF2 View strategy

I'm trying to implement the following:
Simple controller and action. Action should return response of 2 types depending on the request:
HTML in case of ordinary request (text\html),
JSON in case of ajax request (application\json)
I've managed to do this via a plugin for controller, but this requres to write
return $this->myCallBackFunction($data)
in each action. And what if I wan't to do this to whole controller? Was trying to figure out how to implement it via event listener, but could not succed.
Any tips or link to some article would be appreciated!
ZF2 has the acceptable view model selector controller plugin specifically for this purpose. It will select an appropriate ViewModel based on a mapping you define by looking at the Accepts header sent by the client.
For your example, you first need to enable the JSON view strategy by adding it to your view manager config (typically in module.config.php):
'view_manager' => array(
'strategies' => array(
'ViewJsonStrategy'
)
),
(It's likely you'll already have a view_manager key in there, in which case add the 'strategies' part to your current configuration.)
Then in your controller you call the controller plugin, using your mapping as the parameter:
class IndexController extends AbstractActionController
{
protected $acceptMapping = array(
'Zend\View\Model\ViewModel' => array(
'text/html'
),
'Zend\View\Model\JsonModel' => array(
'application/json'
)
);
public function indexAction()
{
$viewModel = $this->acceptableViewModelSelector($this->acceptMapping);
return $viewModel;
}
}
This will return a normal ViewModel for standard requests, and a JsonModel for requests that accept a JSON response (i.e. AJAX requests).
Any variables you assign to the JsonModel will be shown in the JSON output.