Hi I'm trying to make an API to send data encapsulating with json.
as cakephp manual said, I added extensions in routes.php
$routes->extensions(['json]);
and I've made an index function in controller.
public function index(){
$item = $this->Items->find('all');
$this->set(['items' => $items, '_serialize' => ['items']]);
}
here are the problem.
what should i do after this to make api encapsulating with json??
Please help.
thank you
According to Cake 2.x Book (http://book.cakephp.org/2.0/en/development/rest.html)
You have to add this to your routes.php file:
Router::mapResources('items');
Router::parseExtensions();
Then, in your items controller, add the RequestHandler to your components array:
public $components = array('RequestHandler');
Then, in your items controller, add your methods, in your example:
public function index() {
$recipes = $this->Items->find('all');
$this->set(array(
'items' => $items,
'_serialize' => array('items')
));
}
Note: according to model names convention you should call $this->Item instead of $this->Items unless you previously defined the model name as "Item" (singular) in your item model file.
Finally, the API is done, you can access to yourprojecturl/items.json and see the json result.
I had trouble with RicardoCamacho's code until I used the $recipes, which is $this->Items->find('all'); in the $this->set(array...
public function index() {
$recipes = $this->Items->find('all');
$this->set(array(
'items' => $recipes,
'_serialize' => array('items')
));
}
Related
I need to use the function in my view/template page.
My code:
public function getAppNumber($id = null){
$aPPLICATIONINFO = $this->AppEstLto->APPLICATIONINFO->find('all', [
'fields'=>['application_number'],
'conditions'=>['application_id'=>$id],
'limit' => 200
]);
foreach($aPPLICATIONINFO as $aPPLICATIONINFO){
$aPPLICATIONINFOx = $aPPLICATIONINFO;
}
return $aPPLICATIONINFOx;
}
You can use set() to use the function variables in your view as given in cookbook:https://book.cakephp.org/3/en/views.html#setting-view-variables
public function get_app_number($id = null){
$applicationInfo = $this->AppEstLto->APPLICATIONINFO->find('all',
[
'fields'=>['application_number'],
'conditions'=>['application_id'=>$id],
'limit' => 200
]);
//Create an array
$applicationArray = new array();
//Store all results in array
foreach($applicationInfo as $application){
$applicationArray = $application;
}
// Pass the array to view
$this->set(compact('applicationArray'));
}
Now, you can use it in your view:
get_app_number.ctp:
<?php
foreach($applicationArray as $application)
{
echo $application['application_number'];
}
?>
You should be doing something like this in your routes.php file inside your Config folder:
Router::connect('/get-app-number', array('controller' => 'yourController', 'action' => 'get_app_number'));
That way you will be able to connect the url that will be used for your view.
Your action corresponds and sends data to your view.
The action is the function that is inside your controller in which you developed for setting the data and variables.
The example of the slug which would be generated:
http://localhost/get-app-number
When a user visits a particular url in my yii 2.0 application without required parameters, I want to present a form to collect the required missing parameters.
for this purpose, I need the names of missing parameters, e.g. I have a function
public function actionBlast ($bomb, $building) {
}
I expect the results as an array like this
$args = [0=>'bomb', 1=>'building'];
I tried func_get_args() but it returns null, and the undocumented ReflectionFunctionAbstract::getParameters ( void ) etc. Any other way out?
I think the best way to achieve what you want is to override the default ErrorAction.
Inside your controllers directory, create:
controllers
actions
ErrorAction.php
In ErrorAction.php, add:
<?php
namespace frontend\controllers\actions;
use Yii;
use yii\web\ErrorAction as DefaultErrorAction;
class ErrorAction extends DefaultErrorAction
{
public function run()
{
$missing_msg = 'Missing required parameters:';
$exception = Yii::$app->getErrorHandler()->exception;
if (substr($exception->getMessage(), 0, strlen($missing_msg)) === $missing_msg) {
$parameters = explode(',', substr($exception->getMessage(), strlen($missing_msg)));
return $this->controller->render('missing_params_form' ?: $this->id, [
'parameters' => $parameters,
]);
}
return parent::run();
}
}
In your controller add:
public function actions()
{
return [
'error' => [
'class' => 'frontend\controllers\actions\ErrorAction',
],
];
}
and create a view "missing_params_form.php" in your controller `s view directory, where you can generate your form fields.
I believe this to be your best option, though you may need to update it in case a Yii update changes the error message.
I'm creating a RESTful API with Yii2 and have successfully setup a model named Contacts by following the Quick Start Tutorial*. I love how records can be created, listed, updated and deleted without creating any actions.
However I can't see how to filter results. I would like to only return contacts where contact.user_id is equal to 1 (for example) as it currently will reply with all records. Is this possible without creating the actions?
I am unsure also how I can limit results. From what I've read I feel it should append the URI with ?limit=5.
http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html
You should return a dataprovider instead of a set of objects, that supports pagination for you.
Perhaps this approach will be a bit more useful:
public function actionIndex()
{
return new \yii\data\ActiveDataProvider([
'query' => Contact::find()->where(['user_id' => \Yii::$app->user-id]),
]);
}
You could also leave the index action intact, but provide the preset action with a prepareDataProvider-callback:
public function actions()
{
$actions = parent::actions();
$actions['index']['prepareDataProvider'] = function($action)
{
return new \yii\data\ActiveDataProvider([
'query' => Contact::find()->where(['user_id' => \Yii::$app->user-id]),
]);
};
return $actions;
}
Hope that helps.
I have had to override the index method despite not wanting to. My solution looks like this:
public function actions()
{
$actions = parent::actions();
unset($actions['index']);
return $actions;
}
public function actionIndex()
{
return Contact::findAll(['user_id' => \Yii::$app()->user-id]);
}
I guess this solution means I need to write my own pagination code however which is something else I was hoping to avoid.
So far, I have figured out how to return a typical JSON response in Zend Framework 2. First, I added the ViewJsonStrategy to the strategies section of the view_manager configuration. Then, instead of returning a ViewModel instance from the controller action, I return a JsonModel instance with all my variables set.
Now that I've figured that piece out, I need to understand how to render a view and return it within that JSON response. In ZF1, I was able to use $this->view->render($scriptName), which returned the HTML as a string. In ZF2, the Zend\View\View::render(...) method returns void.
So... how can I render an HTML view script and return it in a JSON response in one request?
This is what I have right now:
if ($this->getRequest()->isXmlHttpRequest()) {
$jsonModel = new JsonModel(...);
/* #todo Render HTML script into `$html` variable, and add to `JsonModel` */
return $jsonModel;
} else {
return new ViewModel(...);
}
OK, i think i finally understood what you're doing. I've found a solution that i think matches your criteria. Though i am sure that there is room for improvement, as there's some nasty handwork to be done...
public function indexAction()
{
if (!$this->getRequest()->isXmlHttpRequest()) {
return array();
}
$htmlViewPart = new ViewModel();
$htmlViewPart->setTerminal(true)
->setTemplate('module/controller/action')
->setVariables(array(
'key' => 'value'
));
$htmlOutput = $this->getServiceLocator()
->get('viewrenderer')
->render($htmlViewPart);
$jsonModel = new JsonModel();
$jsonModel->setVariables(array(
'html' => $htmlOutput,
'jsonVar1' => 'jsonVal2',
'jsonArray' => array(1,2,3,4,5,6)
));
return $jsonModel;
}
As you can see, the templateMap i create is ... nasty ... it's annoying and i'm sure it can be improved by quite a bit. It's a working solution but just not a clean one. Maybe somehow one would be able to grab the, probably already instantiated, default PhpRenderer from the ServiceLocator with it's template- and path-mapping and then it should be cleaner.
Thanks to the comment ot #DrBeza the work needed to be done could be reduced by a fair amount. Now, as I'd initially wanted, we will grab the viewrenderer with all the template mapping intact and simply render the ViewModel directly. The only important factor is that you need to specify the fully qualified template to render (e.g.: "$module/$controller/$action")
I hope this will get you started though ;)
PS: Response looks like this:
Object:
html: "<h1>Hello World</h1>"
jsonArray: Array[6]
jsonVar1: "jsonVal2"
You can use more easy way to render view for your JSON response.
public function indexAction() {
$partial = $this->getServiceLocator()->get('viewhelpermanager')->get('partial');
$data = array(
'html' => $partial('MyModule/MyPartView.phtml', array("key" => "value")),
'jsonVar1' => 'jsonVal2',
'jsonArray' => array(1, 2, 3, 4, 5, 6));
$isAjax = $this->getRequest()->isXmlHttpRequest());
return isAjax?new JsonModel($data):new ViewModel($data);
}
Please note before use JsonModel class you need to config View Manager in module.config.php file of your module.
'view_manager' => array(
.................
'strategies' => array(
'ViewJsonStrategy',
),
.................
),
it is work for me and hope it help you.
In ZF 3 you can achieve the same result with this code
MyControllerFactory.php
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$renderer = $container->get('ViewRenderer');
return new MyController(
$renderer
);
}
MyController.php
private $renderer;
public function __construct($renderer) {
$this->renderer = $renderer;
}
public function indexAction() {
$htmlViewPart = new ViewModel();
$htmlViewPart
->setTerminal(true)
->setTemplate('module/controller/action')
->setVariables(array('key' => 'value'));
$htmlOutput = $this->renderer->render($htmlViewPart);
$json = \Zend\Json\Json::encode(
array(
'html' => $htmlOutput,
'jsonVar1' => 'jsonVal2',
'jsonArray' => array(1, 2, 3, 4, 5, 6)
)
);
$response = $this->getResponse();
$response->setContent($json);
$response->getHeaders()->addHeaders(array(
'Content-Type' => 'application/json',
));
return $this->response;
}
As usual framework developer mess thing about AJAX following the rule why simple if might be complex Here is simple solution
in controller script
public function checkloginAction()
{
// some hosts need to this some not
//header ("Content-type: application/json"); // this work
// prepare json aray ....
$arr = $array("some" => .....);
echo json_encode($arr); // this works
exit;
}
This works in ZF1 and ZF2 as well
No need of view scrpt at all
If you use advise of ZF2 creator
use Zend\View\Model\JsonModel;
....
$result = new JsonModel($arr);
return $result;
AJAX got null as response at least in zf 2.0.0
Our Yii Framework application has the following defined as part of the UserProfileImages model:
public function getProfileImages($param, $user_id) {
if(isset($param['select']) && $param['select']=='all'){
$profile_images = UserProfileImages::model()->findAllByAttributes( array( 'user_id'=>$user_id) );
} else {
$profile_images = UserProfileImages::model()->findByAttributes( array( 'user_id'=>$user_id) );
}
return $profile_images;
}
How would I wire up the above snippet to a widget in my view to return all the images for a given user?
Bonus Question: Which image rotator do you suggest to render the above?
In your view file, add something like this, assuming that your controller specified $user_id:
$this->widget('UserProfileImagesWidget', array(
"userProfileImages" => UserProfileImages::getProfileImages(
array("select" => "all"),
$user_id
),
"user_id" => $user_id
));
Depending on your MVC philosophy, you could also retrieve the userProfileImages data in the controller and pass that data to your view.
Define a widget like this:
class UserProfileImagesWidget extends CWidget {
public $user_id;
public $userProfileImages = array();
public function run() {
$this->render("userProfileImage");
}
}
Finally, in the userProfileImages.php view file, you can do something like this:
if(!empty($this->userProfileImages)) {
// Your display magic
// You can access $this->user_id
}
As a side note: You might want to change the order of your parameters in getProfileImages. If $user_id is the first parameter, you can leave out $params completely in case you don't want to specify any.