Phalcon / REST 到现有项目
Phalcon / REST to existing project
我正在开发一个具有以下目录结构的 phalcon 网络应用程序:
/app/
/cache/
...
/config/
config.php
loader.php
services.php
/controllers/
contorllerBase.php
...
/models/
...
/views/
...
/public/
/css/
/img/
/js/
.htacces
index.php
webtools.config.php
webtools.php
index.html
我用 phalcon devtools 创建了这个项目,到目前为止它工作正常,但现在我必须为这个项目实现一个 REST 函数。
我的问题是:
- 在此结构中我在哪里创建 REST 逻辑?
- 推荐的 REST 实施方式是什么?
因为我想要访问视图并且我也需要休息(即:http://localhost/api/..。)
我在互联网上找到了一些解决方案,但它们让我感到困惑,因为大多数情况下只实现一个没有视图的 REST api。
config.php
return new \Phalcon\Config(array(
'database' => array(
...
),
'application' => array(
'controllersDir' => __DIR__ . '/../../app/controllers/',
'modelsDir' => __DIR__ . '/../../app/models/',
'viewsDir' => __DIR__ . '/../../app/views/',
'pluginsDir' => __DIR__ . '/../../app/plugins/',
'libraryDir' => __DIR__ . '/../../app/library/',
'cacheDir' => __DIR__ . '/../../app/cache/',
'logsDir' => __DIR__ . '/../../app/logs',
'baseUri' => '/',
)
));
loader.php
<?php
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerDirs(
array(
$config->application->controllersDir,
$config->application->modelsDir
)
)->register();
services.php
<?php
use Phalcon\DI\FactoryDefault;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Mvc\Model\Metadata\Memory as MetaDataAdapter;
use Phalcon\Session\Adapter\Files as SessionAdapter;
/**
* The FactoryDefault Dependency Injector automatically register the right services providing a full stack framework
*/
$di = new FactoryDefault();
/**
* The URL component is used to generate all kind of urls in the application
*/
$di->set('url', function () use ($config) {
$url = new UrlResolver();
$url->setBaseUri($config->application->baseUri);
return $url;
}, true);
/**
* Setting up the view component
*/
$di->set('view', function () use ($config) {
$view = new View();
$view->setViewsDir($config->application->viewsDir);
$view->registerEngines(array(
'.volt' => function ($view, $di) use ($config) {
$volt = new VoltEngine($view, $di);
$volt->setOptions(array(
'compiledPath' => $config->application->cacheDir,
'compiledSeparator' => '_'
));
return $volt;
},
'.phtml' => 'Phalcon\Mvc\View\Engine\Php'
));
return $view;
}, true);
/**
* Database connection is created based in the parameters defined in the configuration file
*/
$di->set('db', function () use ($config) {
return new DbAdapter(array(
'host' => $config->database->host,
'username' => $config->database->username,
'password' => $config->database->password,
'dbname' => $config->database->dbname,
"charset" => $config->database->charset
));
});
/**
* If the configuration specify the use of metadata adapter use it or use memory otherwise
*/
$di->set('modelsMetadata', function () {
return new MetaDataAdapter();
});
/**
* Start the session the first time some component request the session service
*/
$di->set('session', function () {
$session = new SessionAdapter();
$session->start();
return $session;
});
index.php
<?php
error_reporting(E_ALL);
$debug = new \Phalcon\Debug();
$debug->listen();
try {
/**
* Read the configuration
*/
$config = include __DIR__ . "/../app/config/config.php";
/**
* Read auto-loader
*/
include __DIR__ . "/../app/config/loader.php";
/**
* Read services
*/
include __DIR__ . "/../app/config/services.php";
/**
* Handle the request
*/
$application = new \Phalcon\Mvc\Application($di);
echo $application->handle()->getContent();
} catch (\Exception $e) {
echo $e->getMessage();
}
非常感谢任何帮助。
我用过:
路由:
在路由文件中(非API部分的路由)
include __DIR__ . '/routes_api.php';
$router->mount($api);
在这个routes_api中,我创建了一个组并为这个组定义了一个控制器命名空间
$api = new \Phalcon\Mvc\Router\Group(array(
'namespace' => '\X\Controllers\API',
));
// --- Base API URL prefix
$api->setPrefix('/api');
路由定义如常,采用 REST 服务风格,例如:
$api->addGet('/addresses', array('controller' => 'addresses', 'action' => 'listMe'));
控制器:
我在controllers下创建了一个文件夹api,classes在命名空间中作为组中定义的那个(命名空间X\Controllers\API),带有一个 class 基础,它为所有 REST 控制器实现了一些 REST 礼貌方法:
class AddressesController extends \X\ApiControllerBase
控制器底座:
class ApiControllerBase extends \Phalcon\Mvc\Controller
为所有 REST
提供 JSON 样式响应的自定义实现
public function initialize()
{
$this->response = new \X\ApiResponse();
}
通过 OAuth 服务器为 REST 部分提供授权网关,并在入站查询字符串上做一些 acquisition/filtering/sanitizing 分页和其他实用程序,这些实用程序可供我覆盖的所有 REST 控制器使用:
public function beforeExecuteRoute($dispatcher)
在控制器操作中,我 return 使用一种方法的响应,该方法从我的自定义响应实现中的分页器获取数据(遵循):
$this->response->setResponse($paginator);
return $this->response;
对于输出样式则:
class ApiResponse extends \Phalcon\Http\Response
{
public function __construct($content=null, $code=null, $status=null)
{
parent::__construct($content, $code, $status);
$this->setHeader('Content-Type', 'application/json');
}
public function setResponse($response, $limit = null, $processitems = null)
{
// .... some manipulations of data from controllers ... building of arrays ....
$this->setContent(json_encode(array('error' => false) + $response));
}
public function setResponseError($description, $error = true) {
//Set status code
$this->setStatusCode(200, 'OK');
$this->setContent(json_encode(array('error' => $error, 'error_description' => $description)));
}
}
需要一个控制器来管理对/api的请求而不需要任何rest操作,默认情况下它应该以路由命名,所以它应该是ApiController,您可以调整路由系统以更改它或引发错误 (http://docs.phalconphp.com/en/latest/reference/dispatching.html#inject-model-instances)
服务:
最后,为了管理几种错误(以及抛出的异常),输出结果为 JSON {error: true, message: "...."},在 index.php 我已经实现了调度程序的 beforeException 事件:
$di->setShared('dispatcher', function() {
$eventsManager = new Phalcon\Events\Manager();
$eventsManager->attach("dispatch", function($event, $dispatcher, $exception) {
/* @var $dispatcher Phalcon\Mvc\Dispatcher */
if ($event->getType() == 'beforeException') {
$ctrl = $dispatcher->getActiveController();
if($ctrl instanceof \X\ApiControllerBase) {
$dispatcher->forward(array(
'namespace' => '\',
'controller' => 'error',
'action' => 'api',
'params' => array('message' => $exception->getMessage())
));
return false;
}
$dispatcher = new Phalcon\Mvc\Dispatcher();
//Bind the EventsManager to the Dispatcher
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
);
然后是错误控制器,由调度程序使用转发方法调用(在这种情况下没有命名空间,它位于控制器文件夹内):
class ErrorController extends \Phalcon\Mvc\Controller {
public function route404Action() {
$this->response->setStatusCode(404 , 'Not Found');
}
public function apiAction() {
$pars = $this->dispatcher->getParams();
$this->response = new \X\ApiResponse();
$this->response->setResponseError($pars['message']);
return $this->response;
}
}
希望对您有所帮助:)
我正在开发一个具有以下目录结构的 phalcon 网络应用程序:
/app/
/cache/
...
/config/
config.php
loader.php
services.php
/controllers/
contorllerBase.php
...
/models/
...
/views/
...
/public/
/css/
/img/
/js/
.htacces
index.php
webtools.config.php
webtools.php
index.html
我用 phalcon devtools 创建了这个项目,到目前为止它工作正常,但现在我必须为这个项目实现一个 REST 函数。 我的问题是:
- 在此结构中我在哪里创建 REST 逻辑?
- 推荐的 REST 实施方式是什么? 因为我想要访问视图并且我也需要休息(即:http://localhost/api/..。)
我在互联网上找到了一些解决方案,但它们让我感到困惑,因为大多数情况下只实现一个没有视图的 REST api。
config.php
return new \Phalcon\Config(array(
'database' => array(
...
),
'application' => array(
'controllersDir' => __DIR__ . '/../../app/controllers/',
'modelsDir' => __DIR__ . '/../../app/models/',
'viewsDir' => __DIR__ . '/../../app/views/',
'pluginsDir' => __DIR__ . '/../../app/plugins/',
'libraryDir' => __DIR__ . '/../../app/library/',
'cacheDir' => __DIR__ . '/../../app/cache/',
'logsDir' => __DIR__ . '/../../app/logs',
'baseUri' => '/',
)
));
loader.php
<?php
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerDirs(
array(
$config->application->controllersDir,
$config->application->modelsDir
)
)->register();
services.php
<?php
use Phalcon\DI\FactoryDefault;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Mvc\Model\Metadata\Memory as MetaDataAdapter;
use Phalcon\Session\Adapter\Files as SessionAdapter;
/**
* The FactoryDefault Dependency Injector automatically register the right services providing a full stack framework
*/
$di = new FactoryDefault();
/**
* The URL component is used to generate all kind of urls in the application
*/
$di->set('url', function () use ($config) {
$url = new UrlResolver();
$url->setBaseUri($config->application->baseUri);
return $url;
}, true);
/**
* Setting up the view component
*/
$di->set('view', function () use ($config) {
$view = new View();
$view->setViewsDir($config->application->viewsDir);
$view->registerEngines(array(
'.volt' => function ($view, $di) use ($config) {
$volt = new VoltEngine($view, $di);
$volt->setOptions(array(
'compiledPath' => $config->application->cacheDir,
'compiledSeparator' => '_'
));
return $volt;
},
'.phtml' => 'Phalcon\Mvc\View\Engine\Php'
));
return $view;
}, true);
/**
* Database connection is created based in the parameters defined in the configuration file
*/
$di->set('db', function () use ($config) {
return new DbAdapter(array(
'host' => $config->database->host,
'username' => $config->database->username,
'password' => $config->database->password,
'dbname' => $config->database->dbname,
"charset" => $config->database->charset
));
});
/**
* If the configuration specify the use of metadata adapter use it or use memory otherwise
*/
$di->set('modelsMetadata', function () {
return new MetaDataAdapter();
});
/**
* Start the session the first time some component request the session service
*/
$di->set('session', function () {
$session = new SessionAdapter();
$session->start();
return $session;
});
index.php
<?php
error_reporting(E_ALL);
$debug = new \Phalcon\Debug();
$debug->listen();
try {
/**
* Read the configuration
*/
$config = include __DIR__ . "/../app/config/config.php";
/**
* Read auto-loader
*/
include __DIR__ . "/../app/config/loader.php";
/**
* Read services
*/
include __DIR__ . "/../app/config/services.php";
/**
* Handle the request
*/
$application = new \Phalcon\Mvc\Application($di);
echo $application->handle()->getContent();
} catch (\Exception $e) {
echo $e->getMessage();
}
非常感谢任何帮助。
我用过:
路由:
在路由文件中(非API部分的路由)
include __DIR__ . '/routes_api.php';
$router->mount($api);
在这个routes_api中,我创建了一个组并为这个组定义了一个控制器命名空间
$api = new \Phalcon\Mvc\Router\Group(array(
'namespace' => '\X\Controllers\API',
));
// --- Base API URL prefix
$api->setPrefix('/api');
路由定义如常,采用 REST 服务风格,例如:
$api->addGet('/addresses', array('controller' => 'addresses', 'action' => 'listMe'));
控制器:
我在controllers下创建了一个文件夹api,classes在命名空间中作为组中定义的那个(命名空间X\Controllers\API),带有一个 class 基础,它为所有 REST 控制器实现了一些 REST 礼貌方法:
class AddressesController extends \X\ApiControllerBase
控制器底座:
class ApiControllerBase extends \Phalcon\Mvc\Controller
为所有 REST
提供 JSON 样式响应的自定义实现public function initialize()
{
$this->response = new \X\ApiResponse();
}
通过 OAuth 服务器为 REST 部分提供授权网关,并在入站查询字符串上做一些 acquisition/filtering/sanitizing 分页和其他实用程序,这些实用程序可供我覆盖的所有 REST 控制器使用:
public function beforeExecuteRoute($dispatcher)
在控制器操作中,我 return 使用一种方法的响应,该方法从我的自定义响应实现中的分页器获取数据(遵循):
$this->response->setResponse($paginator);
return $this->response;
对于输出样式则:
class ApiResponse extends \Phalcon\Http\Response
{
public function __construct($content=null, $code=null, $status=null)
{
parent::__construct($content, $code, $status);
$this->setHeader('Content-Type', 'application/json');
}
public function setResponse($response, $limit = null, $processitems = null)
{
// .... some manipulations of data from controllers ... building of arrays ....
$this->setContent(json_encode(array('error' => false) + $response));
}
public function setResponseError($description, $error = true) {
//Set status code
$this->setStatusCode(200, 'OK');
$this->setContent(json_encode(array('error' => $error, 'error_description' => $description)));
}
}
需要一个控制器来管理对/api的请求而不需要任何rest操作,默认情况下它应该以路由命名,所以它应该是ApiController,您可以调整路由系统以更改它或引发错误 (http://docs.phalconphp.com/en/latest/reference/dispatching.html#inject-model-instances)
服务:
最后,为了管理几种错误(以及抛出的异常),输出结果为 JSON {error: true, message: "...."},在 index.php 我已经实现了调度程序的 beforeException 事件:
$di->setShared('dispatcher', function() {
$eventsManager = new Phalcon\Events\Manager();
$eventsManager->attach("dispatch", function($event, $dispatcher, $exception) {
/* @var $dispatcher Phalcon\Mvc\Dispatcher */
if ($event->getType() == 'beforeException') {
$ctrl = $dispatcher->getActiveController();
if($ctrl instanceof \X\ApiControllerBase) {
$dispatcher->forward(array(
'namespace' => '\',
'controller' => 'error',
'action' => 'api',
'params' => array('message' => $exception->getMessage())
));
return false;
}
$dispatcher = new Phalcon\Mvc\Dispatcher();
//Bind the EventsManager to the Dispatcher
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
);
然后是错误控制器,由调度程序使用转发方法调用(在这种情况下没有命名空间,它位于控制器文件夹内):
class ErrorController extends \Phalcon\Mvc\Controller {
public function route404Action() {
$this->response->setStatusCode(404 , 'Not Found');
}
public function apiAction() {
$pars = $this->dispatcher->getParams();
$this->response = new \X\ApiResponse();
$this->response->setResponseError($pars['message']);
return $this->response;
}
}
希望对您有所帮助:)