RESTful webservice with Zend Framework 2.1.* - JsonModel is not shown - json

I read several Tutorials to create a restful webservice with ZF2. I saw that the last changes how ZF2 handles restful webservices happened in version 2.0.4. The most promising article to get me started was this:
http://dustint.com/post/543/getting-started-with-abstractrestfulcontroller
Anyway, I can't get it done, it seems to me, that in RestController.getList() my returned JsonModel is not working like expected. Due to my Debug-call I can recognize that my RestController.getList()-method will be invoked. All related code is in my github-repository here:
https://github.com/Jochen1980/EhcServer/blob/master/module/Application/src/Application/Controller/RestController.php
class RestController extends AbstractRestfulController{
public function indexAction(){
Debug::dump("indexAction()");
return new ViewModel();
}
public function getList() {
Debug::dump("getList()");
return new JsonModel(array(
array('name' => 'test'),
array('name' => 'second')
));
}
...
Currently I got this error message:
Fatal error: Uncaught exception 'Zend\View\Exception\RuntimeException' with message 'Zend\View\Renderer\PhpRenderer::render: Unable to render template "application/rest/get-list"; resolver could not resolve to a file' in C:\xampp\htdocs\EhcServer\vendor\zendframework\zendframework\library\Zend\View\Renderer\PhpRenderer.php on line 499
Thanks in advance!

Your strategies need to be inside view_manager in module.config.php
ie., the view manager section should look like this
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
// let the view manager know which strategies to use
'strategies' => array(
'ViewJsonStrategy',
),
),

If you are working on the Abstract RestfulConroller, simply
'view_manager' => array(
// let the view manager know which strategies to use
'strategies' => array(
'ViewJsonStrategy',
),
),
will make right, because the json itself enough to show in the rest methods,
$array = array();
return new JsonModel($array);
Thanks,

Related

Can I display pictures outside backend web folder in yii2?

I have a little problem. I can’t view images outside the backend web folder.
Aliases in common\config\main:
'aliases' => [
'#upload' => dirname(dirname(__DIR__)).'/upload',
],
View Dataprovider:
[
'format' => 'raw',
'label' => 'Immagine',
'value' => function ($data) {
return Html::img(Yii::getAlias('#upload') . $data->codice_prodotto . '/' . $data->immagine, ['width' => '70px', 'class' => 'img-thumbnail']);
},
],
Can I resolve? Thanks.
If your file is not accessible for http server, so you can't directly download it.
You can:
Move uploads directory to directory accessible for the http-server
Create action that will read the file from private directory and stream it to the browser (you can use yii\web\Response::sendFile() function for that)
Streaming file to the browser
Please read this official docs article to understand this deeply: https://www.yiiframework.com/doc/api/2.0/yii-web-response#sendFile()-detail
Action code example for your case: *
public function actionFile($filename)
{
$storagePath = Yii::getAlias('#upload');
// check filename for allowed chars (do not allow ../ to avoid security issue: downloading arbitrary files)
if (!preg_match('/^[a-z0-9]+\.[a-z0-9]+$/i', $filename) || !is_file("$storagePath/$filename")) {
throw new \yii\web\NotFoundHttpException('The file does not exists.');
}
return Yii::$app->response->sendFile("$storagePath/$filename", $filename);
}
And view Dataprovider configuration: *
[
'format' => 'raw',
'label' => 'Immagine',
'value' => function ($data) {
return Html::img(Url::to(['/path/to-streaming-action/file', 'filename' => $data->codice_prodotto . '/' . $data->immagine]), ['width' => '70px', 'class' => 'img-thumbnail']);
},
],
* Notice that this code is not ready to copy-paste, please read it carefully and try to understand the principle before implement it in your code.

Customize prestashop web service

I want to customize Prestashop web service for my own usage but I don't know how and I can't find any tutorial. I have a mobile application that want to retrieve data from website but the default web service is useless.
For example I want the list of categories (in a language) with they're pictures but It seems I should call two different service to retrieve categories and images separately.
Assume I want to have a JSON array of categories that a category is a JSON object that have these fields {id,title,imageUrl} but It seems I should get {id,title} with a method and after that I can get images on by one by another method!
I couldn't find any guide for extending or customizing web service in the documentation.
I'm a bit late but:
Prestashop version requier : > 1.6
If you want to customize a web service and return specific fields with a JSON format output. You need to do it this way:
First
In override :
Create a class : myClassForWs that extends myClassCore
Override WebserviceRequest in webservice/WebserviceRequest.php
In webservice/WebserviceRequest.php : Add myClassForWs to
ressources:
public static function getResources()
{
$resources = parent::getResources();
$resources['myClassForWs'] = array('description' => 'The class','class' => 'myClassForWs');
ksort($resources);
return $resources;
}
}
In myClassForWs : redefine $webserviceParameters and $definition with the fields you need:
protected $definition = array(
'table' => 'category',
'primary' => 'id_category',
'multilang' => true,
'multilang_shop' => true,
'fields' => array(
'name' =>array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128),
'link_rewrite' =>array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128),
'description' =>array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'),
),
);
protected $webserviceParameters = array(
'objectsNodeName' =>'categories',
'hidden_fields'=>array('nleft', 'nright', 'groupBox'),
'fields' => array(
'level_depth' => array('setter' => false),
),
'associations' => array(
'images' => array(
'resource' => 'image',
'fields' => array('id' => array())
),
),
);
Then
Go in your admin tab :
in performance : clear cache
in advanced settings > Web service: active a api Key and set myClassForWs for this key
Finally
Access to your web service with url :
my.prestashop/api/myClassForWs/{id_class}?output_format=**JSON**
And it returns your datas
I hope it helps.

Yii2 render two models on one view

Yii is the best but I'm having a wee bit of trouble replicating some of the code from yii1 to yii2, below I use the code in yii to render two models in one view and would like to replicate this using yii2. Grateful for any help. thanks
VwContractDetailsController
public function actionView($id)//create new dataprovider and pass param from url
{
$events=$dataProvider=new CActiveDataProvider('VwContractEvents', array(
'criteria'=>array(
'condition'=>'Contractkey_id=:aid',
'params'=>array(':aid'=>$id)
),
'pagination'=>array(
'pageSize'=>2
),
'sort' => array(
'defaultOrder' => 'EventDate DESC',
),
));
$this->render('view',array(
'model'=>$this->loadModel($id),
'events'=>$events,
));
}
vwContractEvents Index //provide full path for itemview
<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'/vwcontractevents/_view',
'enablePagination' => true,
)); ?>
vwContractDetails view //render VwcontractEvents/index on vwContractDetails view
<?php
$this->renderPartial('/VwContractEvents/index',array('dataProvider'=>$events));
?>
The equivalent of renderPartial() in yii2 view is:
yii\base\View::render()
In controller you render with:
yii\base\Controller::render()

CakePHP basic auth on API (json) request

I want to make a request to resource/index.json, but since I index is not allowed without authentication it redirects me to login page. That's the behavior I want when no username:password has been sent
The thing is how do I set AuthComponent to work with both Form and Basic and only check for basic when the request goes through api prefix.
Also, does it automatically authenticate when found username and password in the header or do I have to do it manually?
in respective controller add few lines
class NameController extends AppController {
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow("index");
}
}
This will allow index without authentication.
I decided to use Friend's of Cake TokenAuthenticate, and yes, it works along with FormAuthenticate so I am able to use both.
As a matter of fact, it automatically chooses the component it's going to use based on if there is an existing _token param or a X-MyApiTokenHeader header.
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form',
'Authenticate.Token' => array(
'parameter' => '_token',
'header' => 'X-MyApiTokenHeader',
'userModel' => 'User',
'scope' => array('User.active' => 1),
'fields' => array(
'username' => 'username',
'password' => 'password',
'token' => 'public_key',
),
'continue' => true
)
)
)
);

Error: SQLSTATE[42000]: Syntax error or access violation with cakePHP

I am using the framework cakePHP for my application. I programmed it on localhost with xampp and try to upload it on my website now. It worked without any problems on localhost. Now there is only this one page, which does not work on the new server. The other sites (which use the database connection too) work alright.
For this one site the following message appears:
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'add' at line 1
SQL Query: add
The function add() looks like this.
public function add() {
//$this->create();
$word_id = $this->Word->getWord_id();
$save = $this->save(array('word_id' => $word_id, 'text' => $this->getText($word_id), 'mistake' => 0));
return $save['Game']['id'];
}
On localhost I used MySQL-Client-Version: mysqlnd 5.0.8-dev - 20102224 - $Revision: 310735 $ and PHP Version 5.3.8.
On the server I use MySQL-Client-Version: 5.1.62 and PHP Version 5.3.17.
Thank you very much for helping!
Edit:
The model 'Game':
class Game extends AppModel {
public $name = 'Game';
public $belongsTo = 'Word';
public $searchedWord = '';
public function addGame() { // Create new game
$word_id = $this->Word->getWord_id();
$save = $this->save(array('word_id' => $word_id, 'text' => $this->getText($word_id), 'mistake' => 0));
return $save['Game']['id']; // Build the hangman
}
}
When I debug $this->Game, the output is:
object(AppModel) {
useDbConfig => 'default'
useTable => 'games'
id => null
data => array()
schemaName => null
table => 'games'
primaryKey => 'id'
validate => array()
validationErrors => array()
validationDomain => null
name => 'Game'
alias => 'Game'
tableToModel => array(
'games' => 'Game'
)
cacheQueries => false
belongsTo => array()
hasOne => array()
hasMany => array()
hasAndBelongsToMany => array()
actsAs => null
Behaviors => object(BehaviorCollection) {
modelName => 'Game'
defaultPriority => (int) 10
}
whitelist => array()
cacheSources => true
findQueryType => null
recursive => (int) 1
order => null
virtualFields => array()
__backAssociation => array()
__backInnerAssociation => array()
__backOriginalAssociation => array()
__backContainableAssociation => array()
findMethods => array(
'all' => true,
'first' => true,
'count' => true,
'neighbors' => true,
'list' => true,
'threaded' => true
)
}
usually, if this error happens, you don't have the model instance, but an app model instance you work on. the app model instance doesnt have the add() method and directly queries the db with add().
so make sure your model is properly included. since you didnt show us the code how you call the method (and how you make the model available to the controller) I cannot offer any concrete advice, though.
if you manually include it:
$this->ModelName = ClassRegistry::init('ModelName');
add is a reserved word in MySQL and you're probably using it in a SQL query without "escape".
Check if you have any field named add in your database.
I just had this error and I felt pretty stupid. I'm sure this has been solved a long time ago, but in case anyone else comes across it...
Using your example I'll show basically what I also stupidly did in my Controller and how it caused the same type of error you had:
public function index($gameid = null, $letter = null) {
if ($gameid == null) {
// New game
$gameid = $this->Game->addGame();
}
}
Since you already have the instance (controller class) and you're not calling the Model method of addGame here, but the Controller's method, you simply remove the Game-> from your one-line command.
$gameid = $this->addGame();
Simple and easy oversight. That said, if you moved the addGame method to your Model class, it probably would have worked as expected. :)