Reputation: 43
Hi I'm getting an error when I attempt to access a RESTful web service endpoint in my Zend Framework 2.2.2 project. I am creating a module named V1 and I am receiving the following error:
Zend\View\Renderer\PhpRenderer::render: Unable to render template "v1/collateral/get-list"; resolver could not resolve to a file
I assume that this indicates that the application cannot find a required view file. I started with this tutorial. I've searched for an answer to my issue and I've found some others with a similar issue but I haven't found the answer that I'm looking for at this point because I've still got an error. I'm relatively new to Zend Framework 2 so this may be an easy one for someone more experienced.
Here is what I have done thus far regarding routing and the view manager strategy:
module.config.php:
return array(
'router' => array(
'routes' => array(
'collateral' => array(
'type' => 'segment',
'options' => array(
'route' => '/v1/collateral[/:id]',
'constraints' => array(
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'V1\Controller\Collateral',
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'V1\Controller\Collateral' => 'V1\Controller\CollateralController',
),
),
'view_manager' => array(
'strategies' => array(
'ViewJsonStrategy',
),
),
);
Here is my controller code
CollateralController.php
namespace V1\Controller;
use Zend\Mvc\Controller\AbstractRestfulController;
use V1\Model\Collateral;
//use V1\Form\CollateralForm;
use V1\Model\CollateralTable;
use Zend\View\Model\JsonModel;
class CollateralController extends AbstractRestfulController
{
protected $collateralTable;
public function getList()
{
$results = $this->getCollateralTable()->fetchAll();
$data = array();
foreach($results as $result) {
$data[] = $result;
}
return array('data' => $data);
}
public function get($id)
{
# code...
}
/*public function create($data)
{
# code...
}
public function update($id, $data)
{
# code...
}
public function delete($id)
{
# code...
}*/
public function getCollateralTable()
{
if (!$this->collateralTable) {
$sm = $this->getServiceLocator();
$this->collateralTable = $sm->get('V1\Model\CollateralTable');
}
return $this->collateralTable;
}
}
And for good measure here is my Module.php file
namespace V1;
// Add these import statements:
use V1\Model\Collateral;
use V1\Model\CollateralTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
class Module
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getServiceConfig()
{
return array(
'factories' => array(
'V1\Model\CollateralTable' => function($sm) {
$tableGateway = $sm->get('CollateralTableGateway');
$table = new CollateralTable($tableGateway);
return $table;
},
'CollateralTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Collateral());
return new TableGateway('collateral', $dbAdapter, null, $resultSetPrototype);
},
),
);
}
}
Although I'm not sure based on what I read in the tutorial if I need it or not I have created the following empty view file:
\module\V1\view\v1\collateral\get-list.phtml
I am wondering if this view file is required and is it in the correct location and named properly?
Any other assistance with this error would be greatly appreciated. I'm happy to provide more info if it would be helpful.
Thank you.
Upvotes: 4
Views: 2236
Reputation: 101
Enabling the ViewJsonStrategy does not mean responses will be automatically returned as JSON. What it means is that if you return a JsonModel from your controller, the JsonStrategy will intercept it and return JSON. (http://zend-framework-community.634137.n4.nabble.com/Returning-JSON-for-404-and-for-exception-td4660236.html)
So you need to manualy replace ViewModel to the JsonModel
RestApi\Module.php
public function onBootstrap($e)
{
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach('render', array($this, 'registerJsonStrategy'), 100);
}
/**
* @param \Zend\Mvc\MvcEvent $e The MvcEvent instance
* @return void
*/
public function registerJsonStrategy(\Zend\Mvc\MvcEvent $e) {
$matches = $e->getRouteMatch();
$controller = $matches->getParam('controller');
if (false === strpos($controller, __NAMESPACE__)) {
// not a controller from this module
return;
}
// Potentially, you could be even more selective at this point, and test
// for specific controller classes, and even specific actions or request
// methods.
// Set the JSON model when controllers from this module are selected
$model = $e->getResult();
if($model instanceof \Zend\View\Model\ViewModel)
{
$newModel = new \Zend\View\Model\JsonModel($model->getVariables());
//$e->setResult($newModel);
$e->setViewModel($newModel);
}
}
Upvotes: 1
Reputation: 1210
You're correct that that "render error" is because it can't find your view template, but the good news is that you don't necessarily need one:
Assuming your restful service is returning JSON, try this at the bottom of your controller action:
$result = new \Zend\View\Model\JsonModel($data_you_were_already_returning);
return $result;
Upvotes: 3