基本使用phalcon
安装
wget https://github.com/phalcon/cphalcon/archive/v3.4.1.tar.gz
cd cphalcon/build/
./install --phpize /mnt/d/vhs/php/php71phlone/bin/phpize --php-config /mnt/d/vhs/php/php71phlone/bin/php-config
# OR
cd /cphalcon/build/php7/64bits
phpize
./configure
make
sudo make install
echo "extension=phalcon.so" > /etc/opt/appnode/scls/appnode-php71/php.d/99-Phalcon.ini
idea 提示
composer require phalcon/ide-stubs
通过 phalcon-devtools 创建项目基本结构
# 创建多多模块的项目
# /opt/appnode/appnode-php71/root/bin/php /home/vagrant/phalcon-devtools-3.4.0/phalcon.php create-project projectName --type=modules
phalcon project projectName --type=modules
# 基本使用
/opt/appnode/appnode-php71/root/bin/php /home/vagrant/phalcon-devtools-3.4.0/phalcon.php
# 创建模型
/opt/appnode/appnode-php71/root/bin/php /home/vagrant/phalcon-devtools-3.4.0/phalcon.php model --name order --namespace=Demo\\Modules\\Frontend\\Models --output=/vagrant_data/test_lxx_mo/app/modules/frontend/models
## 如果提示未找到配置文件,查看是不是rootPath有误,在__construct()里面重新指定根目录即可
/home/vagrant/phalcon-devtools-3.4.0/scripts/Phalcon/Builder/Path.php
$this->rootPath = '/vagrant_data/test_lxx_mo/';
跨模块使用,需要注册对应模块的命名空间
# 如在 CLI(bootstrap_cli)模块使用Frontend模块,那么应该在CLI模块里面的loader注册Frontend的命名空间
$loader->registerNamespaces([
'Demo\Common\Models' => APP_PATH . '/common/models/',
'Demo\Common\Library' => APP_PATH . '/common/library/',
'Demo\Modules\Frontend' => APP_PATH . '/modules/frontend/', // 注册Frontend模块,在APP_PATH . '/modules/frontend/'目录里面存在这个文件app/modules/frontend/Module.php
]);
使用多模块mvc
创建多模块目录和控制器 模块wap 创建一个默认的控制器 /app/wap/controllers/IndexController.php
<?php
namespace App\Wap\Controllers;
use Phalcon\Mvc\Controller;
class IndexController extends Controller
{
public function indexAction()
{
$this->view->pick("index/index");
}
public function loginAction()
{
$this->view->pick("index/login");
}
}
每一个模块都存在一个Module配置,必需包含registerAutoloaders和registerServices 独立出来的配置 /app/wap/Module.php
<?php
namespace App\Wap;
use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\DiInterface;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\ModuleDefinitionInterface;
class Module implements ModuleDefinitionInterface
{
/**
* 注册自定义加载器
*/
public function registerAutoloaders(DiInterface $di = null)
{
$loader = new Loader();
$loader->registerNamespaces(
[
'App\Wap\Controllers' => APP_PATH . '/wap/controllers/'
]
);
$loader->register();
}
/**
* 注册自定义服务
*/
public function registerServices(DiInterface $di)
{
// Registering a dispatcher
$di->set(
"dispatcher",
function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('App\\Wap\\Controllers');
return $dispatcher;
}
);
// Registering the view component
$di->set(
"view",
function () {
$view = new View();
$view->setViewsDir("../app/views/wap/");
return $view;
}
);
}
}
配置路由 /app/config/router.php
<?php
$router = $di->getRouter();
// Define your routes here
$router->add(
"/wap",
[
"module" => "wap",
"controller" => 'index',
"action" => 'index',
]
);
$router->add(
"/wap/index",
[
"module" => "wap",
"controller" => 'index',
"action" => 'index',
]
);
$router->add(
"/wap/:controller/:action",
[
"module" => "wap",
"controller" => 1,// :controller 参数
"action" => 2,// :action 参数
]
);
$router->handle();
配置入口文件 注册多模块 /public/index.php
$application = new \Phalcon\Mvc\Application($di);
/**
* 注册多模块
*/
$application->registerModules([
'wap' => [
'className' => 'App\Wap\Module',
'path' => APP_PATH . '/wap/Module.php',
]
]);
创建模板文件 /app/views/wap/index/index.phtml 访问即可 http://host/wap/index/index http://host/wap/index/login
这是html
隐藏index.php webserver-setup#nginx
nginx原文
server {
listen 80;
server_name 192.168.1.114;
root /var/www/phalcon/public/;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.php?_url=$uri&$args;
}
location ~ ^/.+\.php {
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
lighttpd原文
#######################################################################
##
## For more examples check:
##
## https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_Configuration
##
$HTTP["host"] == "lxx.phalcon.net" {
var.server_name = "lxx.phalcon.net"
url.rewrite-if-not-file = (
"^/(.+)/?$" => "/index.php/?_url=/$1",
)
server.name = server_name
## example how to include another config:
## use trigger before download
##
# include "conf.d/trigger_b4_dl.conf"
server.document-root = "/home/lxx/work/tp/phalcon-demo/public/"
##
## use a seperate access log file
## At the moment you cant have different error log files.
##
#accesslog.filename = log_root + "/" + server_name + "/access.log"
}
##
#######################################################################
php 内置服务器
php -S localhost:8000 -t /public .htrouter.php
# .htrouter.php
<?php
if (!file_exists(__DIR__ . '/' . $_SERVER['REQUEST_URI'])) {
$_GET['_url'] = $_SERVER['REQUEST_URI'];
}
return false;
index.php原文
<?php
use Phalcon\Di\FactoryDefault;
error_reporting(E_ALL);
define('BASE_PATH', dirname(__DIR__));
define('APP_PATH', BASE_PATH . '/app');
try {
/**
* The FactoryDefault Dependency Injector automatically registers
* the services that provide a full stack framework.
*/
$di = new FactoryDefault();
/**
* Handle routes
*/
include APP_PATH . '/config/router.php';
/**
* Read services
*/
include APP_PATH . '/config/services.php';
/**
* Get config service for use in inline setup below
*/
$config = $di->getConfig();
/**
* Include Autoloader
*/
include APP_PATH . '/config/loader.php';
/**
* Include Composer Autoloader
*/
include BASE_PATH . '/vendor/autoload.php';
/**
* Handle the request
*/
$application = new \Phalcon\Mvc\Application($di);
/**
* 注册多模块
*/
$application->registerModules([
'wap' => [
'className' => 'App\Wap\Module',
'path' => APP_PATH . '/wap/Module.php',
]
]);
echo str_replace(["\n", "\r", "\t"], '', $application->handle()->getContent());
} catch (\Exception $e) {
echo $e->getMessage() . '<br>';
echo '<pre>' . $e->getTraceAsString() . '</pre>';
}
控制器和模型的命名空间
配置命名空间 文件:phalcon/app/config/loader.php
<?php
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerDirs([$config->application->controllersDir, $config->application->modelsDir]);
// 加载一下命名空间
$loader->registerNamespaces([
'App\\Models' => APP_PATH . '/models/',
'App\\Library' => APP_PATH . '/library/',
'App\\Controllers' => APP_PATH . '/controllers/']);
$loader->register();
Registering a dispatcher 文件:phalcon/app/config/services.php
use Phalcon\Mvc\Dispatcher;
// Registering a dispatcher
// 默认命名空间
$di->set(
"dispatcher",
function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace(
"App\\Controllers"
);
return $dispatcher;
}
);
注册模版引擎服务/Volt模版引擎
文件:phalcon/app/config/services.php
use Phalcon\Mvc\View\Engine\Volt as VoltEngine;
use Phalcon\Mvc\View;
// 注册模版引擎服务
$di->set(
"voltService",
function ($view, $di) {
$volt = new VoltEngine($view, $di);
$volt->setOptions(
[
"compiledPath" => "../app/views/",
// "compiledExtension" => ".compiled",
]
);
return $volt;
}
);
// Register Volt as template engine
// 注册Volt模版引擎
$di->set(
"view",
function () {
$view = new View();
$view->setViewsDir("../app/views/");
$view->registerEngines(
[
".volt" => "voltService",
".phtml" => "voltService",
]
);
return $view;
}
);
关于生成的路径带index.php
修改配置baseUri 文件:phalcon/app/config/config.php
'baseUri' => '',
配置原文/数据库配置
<?php
/*
* Modified: prepend directory path of current file, because of this file own different ENV under between Apache and command line.
* NOTE: please remove this comment.
*/
defined('BASE_PATH') || define('BASE_PATH', getenv('BASE_PATH') ?: realpath(dirname(__FILE__) . '/../..'));
defined('APP_PATH') || define('APP_PATH', BASE_PATH . '/app');
return new \Phalcon\Config([
'database' => [
'adapter' => 'Mysql',
'host' => '127.0.0.1:3306',
'username' => 'root',
'password' => '19961129',
'dbname' => 'phalcon',
'charset' => 'utf8',
],
'application' => [
'appDir' => APP_PATH . '/',
'controllersDir' => APP_PATH . '/controllers/',
'modelsDir' => APP_PATH . '/models/',
'migrationsDir' => APP_PATH . '/migrations/',
'viewsDir' => APP_PATH . '/views/',
'pluginsDir' => APP_PATH . '/plugins/',
'libraryDir' => APP_PATH . '/library/',
'cacheDir' => BASE_PATH . '/cache/',
// This allows the baseUri to be understand project paths that are not in the root directory
// of the webpspace. This will break if the public/index.php entry point is moved or
// possibly if the web server rewrite rules are changed. This can also be set to a static path.
'baseUri' => '',
// 'baseUri' => preg_replace('/public([\/\\\\])index.php$/', '', $_SERVER["PHP_SELF"]),
]
]);
Composer使用
加载Composer 文件:phalcon/public/index.php
/**
* Include Composer Autoloader
*/
include BASE_PATH . '/vendor/autoload.php';
入口文件原文
<?php
use Phalcon\Di\FactoryDefault;
error_reporting(E_ALL);
define('BASE_PATH', dirname(__DIR__));
define('APP_PATH', BASE_PATH . '/app');
try {
/**
* The FactoryDefault Dependency Injector automatically registers
* the services that provide a full stack framework.
*/
$di = new FactoryDefault();
/**
* Handle routes
*/
include APP_PATH . '/config/router.php';
/**
* Read services
*/
include APP_PATH . '/config/services.php';
/**
* Get config service for use in inline setup below
*/
$config = $di->getConfig();
/**
* Include Autoloader
*/
include APP_PATH . '/config/loader.php';
/**
* Include Composer Autoloader
*/
include BASE_PATH . '/vendor/autoload.php';
/**
* Handle the request
*/
$application = new \Phalcon\Mvc\Application($di);
echo str_replace(["\n", "\r", "\t"], '', $application->handle()->getContent());
} catch (\Exception $e) {
echo $e->getMessage() . '<br>';
echo '<pre>' . $e->getTraceAsString() . '</pre>';
}
获取值
(1)直接获取值:
$customerName = $this->request->getPost("name");
(2)自动添加过滤器:
$email = $this->request->getPost("user_email", "email");
(3)手动添加过滤器:
$filter = new Filter();
$email = $filter->sanitize($this->request->getPost("user_email"), "email");
(4)若值为空,设置默认值
$email = $this->request->getPost("user_email", "email", "[email protected]");
(5)获取ajax的json
$robot = $app->request->getJsonRawBody();
$robot->name;
过滤数据
use Phalcon\Filter;
$filter = new Filter();
// 返回 "Hello"
$filter->sanitize("<h1>Hello</h1>", "striptags");
// 返回 "Hello"
$filter->sanitize(" Hello ", "trim");
// 返回 "Hello"
$filter->sanitize(
" <h1> Hello </h1> ",
[
"striptags",
"trim",
]
);
返回json
$this->response->setJsonContent([
"status" => "ERROR",
"messages" => $errors,
]);
return $this->response;
响应/请求
// 检查请求是否为POST
if ($this->request->isPost()) {
// 获取POST数据
$customerName = $this->request->getPost("name");
$customerBorn = $this->request->getPost("born");
}
模型
读取
# 读取
$user = new UsersModel();
$find = UsersModel::findFirst(3);
$users = UsersModel::find(
[
"mobile = :mobile: AND password = :password:",
"bind" => [
"mobile" => $data['user'],
"password" => md5($data['password']),
],
]
);
$users->count();
# 结果集的第一条
$loginuser = $users->getFirst();
$loginuser->id;
# 单条
$users = new UsersModel();
$loginuser = $users->findFirst(1);
#
UsersModel::findFirstById(3);
# 全部
$smsloglist = $smslog->find();
参数绑定 查询选项
$articleModel->find([
'columns' => 'aid, title', //查询字段
'conditions' => 'aid = :aid:', //查询条件
'bind' => [ //参数绑定
'aid' => 2
],
'order' => 'aid DESC', //排序
'limit' => 10, //限制查询结果的数量
'offset' => 10, //偏移量
]);
# in的用法
$result3 = $articleModel->find([
'conditions' => 'aid IN ({aids:array})',
'bind' => [
'aids' => [1, 2]
],
]);
# like的用法
$result4 = $articleModel->find([
'conditions' => 'title like :title:',
'bind' => [
'title' => '%英语%',
],
]);
添加单条记录
$articleModel = new ArticlesModel();
$result = $articleModel->create([
'title' => 'phalcon测试',
'introduce' => 'Phalcon入门教程',
'status' => 1,
'view_number' => 1,
'is_recommend' => 1,
'is_top' => 1,
'create_by' => 1,
'create_time' => date('Y-m-d H:i:s'),
'modify_by' => 1,
'modify_time' => date('Y-m-d H:i:s')
]);
# 更新
# 默认判断数据的非空,在模型初始化initialize里面
$this->setup(
array('notNullValidations' => false)
);
# 先调用 findFirst() 获取一条记录,返回值是当前模型对象 //
# 使用返回的模型对象调用 update() 函数执行更新操作
$articleModel = new ArticlesModel();
$article = $articleModel->findFirst([
'conditions' => 'aid = :aid:',
'bind' => [
'aid' => 3
],
]);
# $users = new UsersModel();
# $loginuser = $users->findFirst(1);
if($article) {
//使用返回的模型对象调用 update() 函数执行更新操作
$result = $article->update([
'title' => 'Phalcon更新测试1',
]);
//update() 函数返回值为boolean
var_dump($result);
}
注入think orm
/**
* 使用think orm
* composer require topthink/think-orm
*/
$di->setShared('thinkorm', function () {
$config = $this->getConfig();
$params = [
'type' => $config->database->adapter,
'hostname' => $config->database->host,
'username' => $config->database->username,
'password' => $config->database->password,
'database' => $config->database->dbname,
'charset' => $config->database->charset,
];
$class = 'think\Db';
$connection = new $class($params);
$connection->setConfig($params);
return $connection;
});
使用
function indexAction()
{
$Db = $this->thinkorm;
$ret = $Db::table('phalcon_sms_log')->find();
// $ret = ($this->thinkorm)::table('phalcon_sms_log')->find();
var_dump($ret);
die();
}
注入
使用nette/database
/**
* 使用nette/database
* Building queries, advanced joins, drivers for MySQL, PostgreSQL, SQLite, MS SQL Server and Oracle.
* https://doc.nette.org/en/2.4/database-core
* composer require nette/database
*/
$di->setShared('pdodatabase', function () {
$config = $this->getConfig();
$params = [
'type' => $config->database->adapter,
'hostname' => $config->database->host,
'username' => $config->database->username,
'password' => $config->database->password,
'database' => $config->database->dbname,
'charset' => $config->database->charset,
];
$class = 'Nette\Database\Connection';
$connection = new $class(strtolower($params['type']) . ':' . 'host=' . $params['hostname'] . ';dbname=' . $params['database'], $params['username'], $params['password']);
return $connection;
});
使用
public function indexAction()
{
// 打印sql和信息
$ret = $this->pdodatabase->query('SELECT * FROM phalcon_sms_log')->dump();
die();
}
cookie
$this->cookies->set(
"uid",
$loginuser->id,
time() + 60 * 60 * 24 * 15
);
# 删除
$cookieuid = $this->cookies->get("uid");
$cookieuid->delete();
模板渲染
赋值
// 赋值
$this->view->password = '';
// 选择视图
$this->view->pick("index/login");
Volt模板渲染
用户姓名:{{userinfo.id}}
{% for vo in smsloglist %}
<div>
ID: {{ vo.id|e }}
{% if vo.is_send == "1" %}
发送ok
{% endif %}
</div>
{% endfor %}
加载公共部分
<?php $this->partial("public/assets_head"); ?>
原文
<html>
<head>
<title>用户主页</title>
<?php $this->partial("public/assets_head"); ?>
<style type="text/css">
.weui_cells {
margin-bottom: 1.17647059em;
}
</style>
</head>
<body ontouchstart="" style="background-color: #f8f8f8;">
</body>
</html>
资源文件
例子
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
<link rel="stylesheet" href="/css/weui/style/weui.css">
<link rel="stylesheet" href="/css/weui/style/weui2.css">
<link rel="stylesheet" href="/css/weui/style/weui3.css">
<script src="/css/weui/zepto.min.js"></script>
实际目录 相对于/public/目录
/public/css/weui/zepto.min.js
分页
use App\Models\SmsLogs as SmsLogsModel; // 表
use Phalcon\Paginator\Adapter\Model as PaginatorModel; // 分页
// $this->request->getQuery("page", "int"); // GET
// $this->request->getPost("page", "int"); // POST
$currentPage = $this->request->getQuery("page", "int");
$smslog = SmsLogsModel::find();
$paginator = new PaginatorModel([
"data" => $smslog,
"limit" => 2,
"page" => $currentPage,
]);
$page = $paginator->getPaginate();
$this->view->page = $page; // 渲染到数据
// 前端
<body ontouchstart="" style="background-color: #f8f8f8;">
<table>
<?php foreach ($page->items as $item) { ?>
<tr>
<td><?php echo $item->id; ?></td>
</tr>
<?php } ?>
</table>
<div>
<a href="/user/index">首页</a>
<a href="/user/index?page=<?= $page->before; ?>">上一页</a>
<a href="/user/index?page=<?= $page->next; ?>">下一页</a>
<a href="/user/index?page=<?= $page->last; ?>">末页</a>
<?php echo "当前页", $page->current, " 共 ", $page->total_pages,"条:", $page->total_items; ?>
</div>
</body>
获取di
$this->getDI()->get('config');
命令行使用
# 创建admin模块
/opt/appnode/appnode-php71/root/bin/php /home/vagrant/phalcon-devtools-3.4.0/phalcon.php module --name admin --namespace=Demo\\Modules --output=/vagrant_data/test_lxx_mo/app/modules
# 创建公共模型
/opt/appnode/appnode-php71/root/bin/php /home/vagrant/phalcon-devtools-3.4.0/phalcon.php model --name order --namespace=Demo\\Common\\Models --output=/vagrant_data/test_lxx_mo/app/common/models
# 创建admin基类控制器
/opt/appnode/appnode-php71/root/bin/php /home/vagrant/phalcon-devtools-3.4.0/phalcon.php controller --name base --namespace=Demo\\Modules\\Admin\\Controllers --output=/vagrant_data/test_lxx_mo/app/modules/admin/controllers
# 创建admin的index控制器
/opt/appnode/appnode-php71/root/bin/php /home/vagrant/phalcon-devtools-3.4.0/phalcon.php controller --name index --namespace=Demo\\Modules\\Admin\\Controllers --base-class=\\Demo\\Modules\\Admin\\Controllers\\BaseController --output=/vagrant_data/test_lxx_mo/app/modules/admin/controllers
# app/bootstrap_web.php文件注册模块(web服务里面引入多模块)
/**
* 注册模块,$application->getModules();可以获取当前所有模块(路由可使用)
*/
$application->registerModules([
'frontend' => ['className' => 'Demo\Modules\Frontend\Module'],
'admin' => ['className' => 'Demo\Modules\Admin\Module'],
]);
# $loader里面注册Admin模块
/**
* 首先注册命名空间进行加载
*/
$loader->registerNamespaces([
// 公共部分
'Demo\Common\Models' => APP_PATH . '/common/models/',
'Demo\Common\Library' => APP_PATH . '/common/library/',
// 不同模块部分
'Demo\Modules\Frontend' => APP_PATH . '/modules/frontend/',
'Demo\Modules\Admin' => APP_PATH . '/modules/admin/',
]);
/**
* 注册新的模块的类文件(该Module.php文件又会注册命名空间,包含该模块的控制器等)
*/
$loader->registerClasses([
'Demo\Modules\Frontend\Module' => APP_PATH . '/modules/frontend/Module.php',
'Demo\Modules\Admin\Module' => APP_PATH . '/modules/admin/Module.php',
'Demo\Modules\Cli\Module' => APP_PATH . '/modules/cli/Module.php',
]);
# modules/admin/Module.php 文件的view修正为
$di['view'] = function () {
$view = new View();
$view->setDI($this);
$view->setViewsDir(__DIR__ . '/views/');
$view->registerEngines([
'.volt' => 'voltShared',
'.phtml' => PhpEngine::class
]);
return $view;
};
.
├── bootstrap_cli.php
├── bootstrap_web.php
├── common
│ ├── library
│ │ └── TpDb.php
│ └── models
│ └── Order.php
├── config
│ ├── config.php
│ ├── loader.php
│ ├── routes.php
│ ├── services_cli.php
│ ├── services.php
│ └── services_web.php
└── modules
├── admin
│ ├── controllers
│ │ ├── BaseController.php
│ │ └── IndexController.php
│ ├── Module.php
│ └── views
├── cli
│ ├── migrations
│ ├── Module.php
│ └── tasks
│ ├── MainTask.php
│ └── VersionTask.php
└── frontend
├── controllers
│ ├── ControllerBase.php
│ └── IndexController.php
├── Module.php
└── views
├── index
├── index.phtml
└── layouts
模型使用redis缓存
## 注册 modelsCache,且配置statsKey默认为_PHCR
$di->setShared(
'modelsCache',
function () {
// Cache data for one day (default setting)
$frontCache = new \Phalcon\Cache\Frontend\Data(
[
'lifetime' => 86400,
]
);
// Memcached connection settings
$cache = new \Phalcon\Cache\Backend\Redis(
$frontCache,
[
'host' => '127.0.0.1',
'port' => '6379',
"auth" => "easyswoole",
"index" => 0,
'statsKey' => '_PHCR',
]
);
return $cache;
}
);
## 使用
$ret = Order::query()
->where('id > :virtual:', ['virtual' => '1'])
->orderBy('id desc,userid asc')
->cache([
'key' => 'order_list_' . time(),
])
->execute();
/**
* @var array $ret 模糊查询,返回 key
*/
$ret = $this->modelsCache
->queryKeys("order_");
/**
* @var mix $ret2 精确查询,返回 value
*/
$ret2 = $this->modelsCache
->get("order_list");
return $this->response->setJsonContent(['ret' => $ret, '$ret2' => $ret2]);
多模块的视图
### 多模块的视图
/**
* 设置disableLevel,还是不要进行layout布局,每一个页面就是一个整体
*/
$di['view'] = function () {
$view = new View();
$view->setDI($this);
$view->setViewsDir(__DIR__ . '/views/');
$view->disableLevel(
[
View::LEVEL_MAIN_LAYOUT => true,
]
);
$view->registerEngines([
'.volt' => 'voltShared',
'.phtml' => PhpEngine::class
]);
return $view;
};
### 多模块渲染请指定文件名称
class IndexController extends \Demo\Modules\Admin\Controllers\BaseController
{
public function loginAction()
{
return $this->view->pick('login');
}
}
# /vagrant_data/test_lxx_mo/app/modules
.
└── admin
├── controllers
│ ├── BaseController.php
│ └── IndexController.php
├── Module.php
└── views
└── login.phtml
public function loginAction()
{
/**
* <input type='hidden' name='<?php echo $this->security->getTokenKey() ?>' value='<?php echo $this->security->getToken() ?>' />
*/
if ($this->request->isPost()) {
if (!$this->security->checkToken()) {
$this->flashSession->error("checkToken err");
} else {
// ok
}
}
return $this->view->pick('login');
}