php框架费尔康,GitHub - majixian/study-phalcon: phalcon(费尔康)框架学习笔记
phalcon(費爾康)框架學習筆記
以實例程序invo為例(invo程序放在網站根目錄下的invo文件夾里,推薦php版本>=5.4)
環境不支持偽靜態網址時的配置
第一步:
在app\config\config.ini文件中的[application]節點內修改baseUri參數值為/invo/index.php/或/invo/index.php?_url=/,并增加一個參數staticBaseUri,值設為/invo/。
例如:
;支持非偽靜態網址
baseUri = "/invo/index.php?_url=/"
;靜態資源文件網址
staticBaseUri = /invo/
如果將baseUri設置為/invo/index.php/的話,需要在router服務中作如下設置,才能正常工作:
$di -> set('router', function () {
$router = new Router();
$router->setUriSource(Router::URI_SOURCE_SERVER_REQUEST_URI);//重要
return $router;
});
第二步:
在文件app\config\services.php中找到$di->set('url',所在位置,在其中的匿名函數內return語句前增加一行,輸入$url->setStaticBaseUri($config->application->staticBaseUri);
這里使用的是phalcon v2.0.2,此版本在使用非偽靜態網址的過程中,發現存在一個bug:當在模板中使用$this->tag->linkTo('products/search?page=1')函數生成網址時,由于第一個參數中包含了問號,再加上配置文件中的baseUri中也包含問號,這樣生成的網址中就包含兩處問號,只能通過自己擴展Url類來修復了,下面是修復步驟。
在文件app\config\services.php中添加以下代碼:
/**
* 重寫Url,修復動態網址中關于問號的bug
*
* @author:S.W.H
* @E-mail:swh@admpub.com
* @update:2015/6/9
*/
class MyUrl extends UrlProvider{
static public $hasDynamicUrl=null;
public function get($uri=null, $args=null, $local=null){
if(self::$hasDynamicUrl && strpos($uri,'?')!==false){
$uri=str_replace('?','&',$uri);
}
return parent::get($uri, $args, $local);
}
}
并將代碼:
$url = new UrlProvider();
替換為:
$url = new \MyUrl();
\MyUrl::$hasDynamicUrl=strpos($config->application->baseUri,'?')!==false;
即可解決。
路由規則
添加路由規則:
use Phalcon\Mvc\Router;
// Create the router
$router = new Router();
//Define a route
$router->add(
"/admin/:controller/a/:action/:params",
array(
"controller" => 1, //匹配第一個占位符(/:controller)
"action" => 2, //匹配第二個占位符(/:action)
"params" => 3, //匹配第三個占位符(/:params)
)
);
支持的占位符有:
占位符
正則表達式
Usage
/:module
/([a-zA-Z0-9_-]+)
Matches a valid module name with alpha-numeric characters only
/:controller
/([a-zA-Z0-9_-]+)
Matches a valid controller name with alpha-numeric characters only
/:action
/([a-zA-Z0-9_]+)
Matches a valid action name with alpha-numeric characters only
/:params
(/.*)*
Matches a list of optional words separated by slashes. Use only this placeholder at the end of a route
/:namespace
/([a-zA-Z0-9_-]+)
Matches a single level namespace name
/:int
/([0-9]+)
Matches an integer parameter
Controller名稱是采用駝峰命名法(camel),這意味著“-”和“_”將會被刪除并將其后的一個字符大寫。
例如,some_controller 會被轉換為 SomeController。
指定參數名稱
方式一,在數組中指定:
$router->add(
"/news/([0-9]{4})/([0-9]{2})/([0-9]{2})/:params",
array(
"controller" => "posts",
"action" => "show",
"year" => 1, // ([0-9]{4})
"month" => 2, // ([0-9]{2})
"day"=> 3, // ([0-9]{2})
"params" => 4, // :params
)
);
在上面的例子中,路由沒有定義“controller”和“action”部分,而是被指定為“posts”和“show”,這樣,用戶將不知道控制器的真實請求路徑。
在controller中,這些被命名的參數可以用如下方式這樣訪問:
use Phalcon\Mvc\Controller;
class PostsController extends Controller{
public function indexAction(){
}
public function showAction(){
// Return "year" parameter
$year = $this->dispatcher->getParam("year");
// Return "month" parameter
$month = $this->dispatcher->getParam("month");
// Return "day" parameter
$day = $this->dispatcher->getParam("day");
}
}
方式二,在路由中指定:
$router->add(
"/documentation/{chapter}/{name}.{type:[a-z]+}",
array(
"controller" => "documentation",
"action" => "show"
)
);
看見了嗎?花括號中的chaper、name和type就是相對應的名稱了。
總結:路由中的匹配項,可以使用
占位符
正則表達式
帶命名的正則表達式(命名與正則表達式間用冒號“:”隔開,并整個用花括號括起來)
{命名}
指定名稱空間的例子:
$router->add("/login", array(
'namespace' => 'Backend\Controllers',
'controller' => 'login',
'action' => 'index'
));
鉤子事件
轉換某個參數的值:
//The action name allows dashes, an action can be: /products/new-ipod-nano-4-generation
$router->add('/products/{slug:[a-z\-]+}', array(
'controller' => 'products',
'action' => 'show'
))->convert('slug', function($slug) {
//Transform the slug removing the dashes
return str_replace('-', '', $slug);
});
除了convert方法之外,還支持:
匹配回調函數
->beforeMatch(function($uri, $route) {
//Check if the request was made with Ajax
if ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'xmlhttprequest') {
return false;
}
return true;
});//參數可以是匿名函數,也可以采用數組的方式指定某個對象的方法:array(new AjaxFilter(), 'check')
限制主機名
->setHostName('([a-z+]).company.com');
路由分組
use Phalcon\Mvc\Router;
use Phalcon\Mvc\Router\Group as RouterGroup;
$router = new Router();
//Create a group with a common module and controller
$blog = new RouterGroup(array(
'module' => 'blog',
'controller' => 'index'
));
//All the routes start with /blog
$blog->setPrefix('/blog');
//Add another route to the group
$blog->add('/edit/{id}', array(
'action' => 'edit'
));
//Add the group to the router
$router->mount($blog);
或者:
use Phalcon\Mvc\Router\Group as RouterGroup;
class BlogRoutes extends RouterGroup{
public function initialize(){
//Default paths
$this->setPaths(array(
'module' => 'blog',
'namespace' => 'Blog\Controllers'
));
//All the routes start with /blog
$this->setPrefix('/blog');
//Add another route to the group
$this->add('/edit/{id}', array(
'action' => 'edit'
));
}
}
Then mount the group in the router:
//Add the group to the router
$router->mount(new BlogRoutes());
路由命名
$route = $router->add("/posts/{year}/{title}", "Posts::show");
$route->setName("show-posts");
//或者這樣
$router->add("/posts/{year}/{title}", "Posts::show")->setName("show-posts");
然后,我們就可以根據命名來生成符合這條路由的網址了:
// returns /posts/2012/phalcon-1-0-released
echo $url->get(array(
"for" => "show-posts",//路由名稱
"year" => "2012",//參數year的值
"title" => "phalcon-1-0-released" //參數title的值
));
指定URI來源
use Phalcon\Mvc\Router;
...
$router->setUriSource(Router::URI_SOURCE_GET_URL); // use $_GET['_url'] (default)
$router->setUriSource(Router::URI_SOURCE_SERVER_REQUEST_URI); // use $_SERVER['REQUEST_URI'] (default)
限制HTTP請求方式
當您使用路由的add方法時,意味著不限制HTTP請求方式。
有時我們可以限制一個路由使用一個特定的方式來訪問,這在創建RESTful應用程序時將非常有用:
// This route only will be matched if the HTTP method is GET
$router->addGet("/products/edit/{id}", "Products::edit");
// This route only will be matched if the HTTP method is POST
$router->addPost("/products/save", "Products::save");
// This route will be matched if the HTTP method is POST or PUT
$router->add("/products/update")->via(array("POST", "PUT"));
限制http請求方式:$router->addGet()、$router->addPut()、$router->addPost()……
設置默認
可以為通用路徑中的 module, controller, action 定義默認值。當一個路由缺少其中任何一項時,路由器可以自動用默認值填充:
//Setting a specific default
$router->setDefaultModule('backend');
$router->setDefaultNamespace('Backend\Controllers');
$router->setDefaultController('index');
$router->setDefaultAction('index');
//Using an array
$router->setDefaults(array(
'controller' => 'index',
'action' => 'index'
));
匿名路由
此組件提供了一個與注解服務集成的變體。使用此策略可以在控制器中直接寫路由。
use Phalcon\Mvc\Router\Annotations as RouterAnnotations;
$di['router'] = function() {
//Use the annotations router
$router = new RouterAnnotations(false);
//Read the annotations from ProductsController if the uri starts with /api/products
$router->addResource('Products', '/api/products');
return $router;
};
可以按如下方式定義注解:
/**
* @RoutePrefix("/api/products")
*/
class ProductsController
{
/**
* @Get("/")
*/
public function indexAction() {}
/**
* @Get("/edit/{id:[0-9]+}", name="edit-robot")
*/
public function editAction($id) {}
/**
* @Route("/save", methods={"POST", "PUT"}, name="save-robot")
*/
public function saveAction() {}
/**
* @Route("/delete/{id:[0-9]+}", methods="DELETE",
* conversors={id="MyConversors::checkId"})
*/
public function deleteAction($id) {}
public function infoAction($id) {}
}
支持的注解有:
Name
Description
Usage
RoutePrefix
A prefix to be prepended to each route uri. This annotation must be placed at the class’ docblock
@RoutePrefix(“/api/products”)
Route
This annotation marks a method as a route. This annotation must be placed in a method docblock
@Route(“/api/products/show”)
Get
This annotation marks a method as a route restricting the HTTP method to GET
@Get(“/api/products/search”)
Post
This annotation marks a method as a route restricting the HTTP method to POST
@Post(“/api/products/save”)
Put
This annotation marks a method as a route restricting the HTTP method to PUT
@Put(“/api/products/save”)
Delete
This annotation marks a method as a route restricting the HTTP method to DELETE
@Delete(“/api/products/delete/{id}”)
Options
This annotation marks a method as a route restricting the HTTP method to OPTIONS
@Option(“/api/products/info”)
用注解添加路由時,支持以下參數:
Name
Description
Usage
methods
Define one or more HTTP method that route must meet with
@Route(“/api/products”, methods={“GET”, “POST”})
name
Define a name for the route
@Route(“/api/products”, name=”get-products”)
paths
An array of paths like the one passed to Phalcon\Mvc\Router::add
@Route(“/posts/{id}/{slug}”, paths={module=”backend”})
conversors
A hash of conversors to be applied to the parameters
@Route(“/posts/{id}/{slug}”, conversors={id=”MyConversor::getId”})
如果要將路由映射到模塊中的控制器,可以使用addModuleResource方法:
use Phalcon\Mvc\Router\Annotations as RouterAnnotations;
$di['router'] = function() {
//Use the annotations router
$router = new RouterAnnotations(false);
//Read the annotations from Backend\Controllers\ProductsController if the uri starts with /api/products
$router->addModuleResource('backend', 'Products', '/api/products');
return $router;
};
###路由執行事件
依次按以下順序執行:
dispatch:beforeDispatchLoop
開始循環匹配路由
dispatch:beforeDispatch
dispatch:beforeNotFoundAction
dispatch:beforeExecuteRoute
beforeExecuteRoute($dispatcher)
initialize() -> dispatch:afterInitialize
執行路由到的方法
dispatch:afterExecuteRoute
dispatch:afterDispatch
afterExecuteRoute($dispatcher)
結束循環匹配路由
dispatch:afterDispatchLoop
其中,以“dispatch:”開頭的均為eventManager中定義的事件名稱。“xxx(...)”這種格式的均為控制器中的方法。
控制器命名
默認調用IndexController控制器中的indexAction方法。
控制器名稱需要加Controller后綴,動作名稱需要加Action后綴。
控制器的首字母要大寫且繼承自Phalcon\Mvc\Controller。
控制器的文件名稱與控制器全名完全相同并加擴展名“.php”。
視圖渲染
Phalcon\Mvc\View 默認采用PHP本身作為模板引擎,此時應該以.phtml作為視圖文件擴展名。
可以在控制器方法中使用$this->view->setVar("postId", $postId);來傳遞變量到視圖,然后在視圖中用php來使用此變量,比如:<?php echo $postId;?>,setVar方法也可以通過接收關鍵字索引數組來一次傳遞多個值(類似于smarty中assign的批量賦值)。
Phalcon\Mvc\View 支持視圖分層。
分層渲染
第一步、渲染模板:
視圖文件目錄/小寫的控制器名(不含后綴)/方法名(不含后綴).phtml
并保存結果。級別代號LEVEL_ACTION_VIEW。
可在此模板中通過調用<?php echo $this->getContent() ?>輸出控制器中的輸出內容(比如在控制器中使用echo輸出一些內容)。
第二步、渲染模板(如果有):
視圖文件目錄/layouts/小寫的控制器名(不含后綴).phtml
并保存結果。級別代號LEVEL_LAYOUT。
可在此模板中通過調用<?php echo $this->getContent() ?>輸出第一步的模板結果。
第三步、渲染模板(如果有):
視圖文件目錄/index.phtml
并保存結果。級別代號LEVEL_MAIN_LAYOUT。
同樣的,可在此模板中通過調用<?php echo $this->getContent() ?>輸出第二步的模板結果。
最后保存的結果就是視圖的最終結果。
可以在控制器方法中使用$this->view->setTemplateAfter('common');來在第三步之前插入一個渲染操作,比如這里渲染模板:視圖文件目錄/layouts/common.phtml
渲染級別控制
可以在控制器方法中使用$this->view->setRenderLevel(View::LEVEL_NO_RENDER);來關閉渲染,或者僅僅渲染某個級別$this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
也可以使用$this->view->disableLevel(View::LEVEL_MAIN_LAYOUT);來禁止某個級別的渲染。
可以用$this->view->pick('index/pick');選擇視圖:
如果pick方法接收到一個不包含“/”的字符串則僅僅設置LEVEL_ACTION_VIEW級視圖;如果包含“/”則同時還會把第一個“/”前面的部分作為LEVEL_LAYOUT級視圖,比如這里會使用“視圖文件目錄/layouts/index.phtml”文件
如果接收到一個數字索引數組,則會將編號為0的元素作為LEVEL_ACTION_VIEW級視圖,將編號為1的元素作為LEVEL_LAYOUT級視圖
關閉視圖
如果你的控制器不在視圖里產生(或沒有)任何輸出,你可以禁用視圖組件來避免不必要的處理:
$this->view->disable();
在模板中包含局部模板
<?php $this->partial('shared/login');?>
或者同時傳遞變量給局部模板,每一個索引最終會作為變量在局部模板中被賦值:
$this->partial('shared/login',array(
'var1'=>'val1',
'var2'=>'val2'
));
?>
緩存視圖
在控制器方法中的代碼例子:
//Check whether the cache with key "downloads" exists or has expired
if ($this->view->getCache()->exists('downloads')) {
//Query the latest downloads
$latest = Downloads::find(array(
'order' => 'created_at DESC'
));
$this->view->latest = $latest;
}
//Enable the cache with the same key "downloads"
$this->view->cache(array(
'service' => 'myCache',//使用自己的緩存服務,不設置時默認為viewCache
'lifetime' => 86400,//緩存時間
'key' => 'downloads'//緩存索引名
));
注冊緩存服務:
use Phalcon\Cache\Frontend\Output as OutputFrontend;
use Phalcon\Cache\Backend\Memcache as MemcacheBackend;
//Set the views cache service
$di->set('viewCache', function() {
//Cache data for one day by default
$frontCache = new OutputFrontend(array(
'lifetime' => 86400
));
//Memcached connection settings
$cache = new MemcacheBackend($frontCache, array(
'host' => 'localhost',
'port' => '11211'
));
return $cache;
});
其中“Phalcon\Cache\Frontend”中包含了對前臺數據的處理操作(比如數據格式編碼等);
“Phalcon\Cache\Backend”中包含了對各種后臺緩存引擎的操作。
使用模板引擎
在控制器方法中指定模板引擎:
// Using more than one template engine
$this->view->registerEngines(
array(
'.my-html' => 'MyTemplateAdapter',
'.phtml' => 'Phalcon\Mvc\View\Engine\Php'
)
);
方法Phalcon\Mvc\View::registerEngines()接受一個包含定義模板引擎數據的數組。每個引擎的鍵名是一個區別于其他引擎的拓展名。模板文件和特定的引擎關聯必須有這些擴展名。
Phalcon\Mvc\View::registerEngines()會按照相關模板引擎定義的順序來執行。如果Phalcon\Mvc\View發現視圖文件具有相同名稱但擴展名不同,它只會使用第一個。
在注冊view服務時全局指定模板引擎:
use Phalcon\Mvc\View;
//Setting up the view component
$di->set('view', function() {
$view = new View();
//A trailing directory separator is required
$view->setViewsDir('../app/views/');
$view->registerEngines(array(
'.my-html' ='MyTemplateAdapter' //元素值可以是類名、服務名或返回模板引擎對象的匿名函數
));
return $view;
}, true);
Volt 視圖最終會被編譯成純PHP代碼
Volt模板引擎語法
3種不同含義的起始標簽
{% ... %}包裹的標簽用于賦值或執行for循環、if條件判斷等語句
{{ ... }}包裹的標簽用于打印表達式的結果到模板
{# ... #}包裹注釋,前后標簽可以處于不同行
語法詳解
{{ post.title }}相當于$post->title;
{{ post.getTypes().name }}相當于$post->getTypes()->name;
{{ post['title'] }}相當于$post['title'];
{{ post.title|e }}使用過濾器,豎線左邊表達式的值將會作為過濾器的第一個參數;
{{ '%.2f'|format(post.price) }}相當于執行sprintf('%.2f', $post->price);
默認過濾器列表:
Filter
Description
e
Applies Phalcon\Escaper->escapeHtml to the value
escape
Applies Phalcon\Escaper->escapeHtml to the value
escape_css
Applies Phalcon\Escaper->escapeCss to the value
escape_js
Applies Phalcon\Escaper->escapeJs to the value
escape_attr
Applies Phalcon\Escaper->escapeHtmlAttr to the value
trim
Applies the trim PHP function to the value. Removing extra spaces
left_trim
Applies the ltrim PHP function to the value. Removing extra spaces
right_trim
Applies the rtrim PHP function to the value. Removing extra spaces
striptags
Applies the striptags PHP function to the value. Removing HTML tags
slashes
Applies the slashes PHP function to the value. Escaping values
stripslashes
Applies the stripslashes PHP function to the value. Removing escaped quotes
capitalize
Capitalizes a string by applying the ucwords PHP function to the value
lower
Change the case of a string to lowercase
upper
Change the case of a string to uppercase
length
Counts the string length or how many items are in an array or object
nl2br
Changes newlines \n by line breaks (
). Uses the PHP function nl2br
sort
Sorts an array using the PHP function asort
keys
Returns the array keys using array_keys
join
Joins the array parts using a separator join
format
Formats a string using sprintf.
json_encode
Converts a value into its JSON representation
json_decode
Converts a value from its JSON representation to a PHP representation
abs
Applies the abs PHP function to a value.
url_encode
Applies the urlencode PHP function to the value
default
Sets a default value in case that the evaluated expression is empty
(is not set or evaluates to a falsy value)
convert_encoding
Converts a string from one charset to another
for循環用法
基礎用法:
{% for robot in robots %}
{{ robot.name|e }}
{% endfor %}
嵌套循環:
{% for robot in robots %}
{% for part in robot.parts %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% endfor %}
{% endfor %}
獲取索引值
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for name, value in numbers %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
用if進行篩選
{% for value in numbers if value < 2 %}
Value: {{ value }}
{% endfor %}
{% for name, value in numbers if name != 'two' %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
else、elsefor
{% for robot in robots %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% else %}{# else也可以寫成elsefor #}
There are no robots to show
{% endfor %}
可以在for結構中使用{% break %}和{% continue %}來跳出和執行下一次循環
if條件判斷
基本用法
{% if robot.type == "cyborg" %}
{{ robot.name|e }}
{% endif %}
{% if robot.type == "cyborg" %}
{{ robot.name|e }}
{% else %}
{{ robot.name|e }} (not a cyborg)
{% endif %}
{% if robot.type == "cyborg" %}
Robot is a cyborg
{% elseif robot.type == "virtual" %}
Robot is virtual
{% elseif robot.type == "mechanical" %}
Robot is mechanical
{% endif %}
if中可以使用的內置變量:
Variable
Description
loop.index
The current iteration of the loop. (1 indexed)
loop.index0
The current iteration of the loop. (0 indexed)
loop.revindex
The number of iterations from the end of the loop (1 indexed)
loop.revindex0
The number of iterations from the end of the loop (0 indexed)
loop.first
True if in the first iteration.
loop.last
True if in the last iteration.
loop.length
The number of items to iterate
賦值
單個變量賦值:
{% set fruits = ['Apple', 'Banana', 'Orange'] %}
{% set name = robot.name %}
多個變量賦值:
{% set fruits = ['Apple', 'Banana', 'Orange'], name = robot.name, active = true %}
支持的字面值:
字面值
說明
“this is a string”
被單引號或雙引號括起來的內容作為字符串
100.25
帶小數部分的數字作為(double/float)
100
不帶小數的數字作為整數(integer)
false
靜態內容“false”作為布爾值中false
true
Constant “true” is the boolean true value
null
Constant “null” is the Null value
數組可以用中括號或花括號定義
{# Other simple array #}
{{ ['Apple', 1, 2.5, false, null] }}
{# Multi-Dimensional array #}
{{ [[1, 2], [3, 4], [5, 6]] }}
{# Hash-style array #}
{{ ['first': 1, 'second': 4/2, 'third': '3'] }}
{% set myArray = {'Apple', 'Banana', 'Orange'} %}
{% set myHash = {'first': 1, 'second': 4/2, 'third': '3'} %}
算術運算符和比較符與PHP語法中的一致,邏輯運算符為:or,and,not
if中的is測試操作
內置支持的測試:
Test
Description
defined
Checks if a variable is defined (isset)
empty
Checks if a variable is empty
even
Checks if a numeric value is even
odd
Checks if a numeric value is odd
numeric
Checks if value is numeric
scalar
Checks if value is scalar (not an array or object)
iterable
Checks if a value is iterable. Can be traversed by a “for” statement
divisibleby
Checks if a value is divisible by other value
sameas
Checks if a value is identical to other value
type
Checks if a value is of the specified type
{%- macro my_input(name, class="input-text") %}
{% return text_field(name, 'class': class) %}
{%- endmacro %}
{# Call the macro #}
{{ '
' ~ my_input('name') ~ '
' }}{{ '
' ~ my_input('name', 'input-text') ~ '
' }}由以上代碼可見,模板中字符串間連接符為~!
Method
Volt function
Phalcon\Tag::linkTo
link_to
Phalcon\Tag::textField
text_field
Phalcon\Tag::passwordField
password_field
Phalcon\Tag::hiddenField
hidden_field
Phalcon\Tag::fileField
file_field
Phalcon\Tag::checkField
check_field
Phalcon\Tag::radioField
radio_field
Phalcon\Tag::dateField
date_field
Phalcon\Tag::emailField
email_field
Phalcon\Tag::numberField
number_field
Phalcon\Tag::submitButton
submit_button
Phalcon\Tag::selectStatic
select_static
Phalcon\Tag::select
select
Phalcon\Tag::textArea
text_area
Phalcon\Tag::form
form
Phalcon\Tag::endForm
end_form
Phalcon\Tag::getTitle
get_title
Phalcon\Tag::stylesheetLink
stylesheet_link
Phalcon\Tag::javascriptInclude
javascript_include
Phalcon\Tag::image
image
Phalcon\Tag::friendlyTitle
friendly_title
函數
Name
Description
content
Includes the content produced in a previous rendering stage
get_content
Same as ‘content’
partial
Dynamically loads a partial view in the current template
super
Render the contents of the parent block
time
Calls the PHP function with the same name
date
Calls the PHP function with the same name
dump
Calls the PHP function ‘var_dump’
version
Returns the current version of the framework
constant
Reads a PHP constant
url
Generate a URL using the ‘url’ service
模板的繼承
父模板(templates/base.volt)
`{% block title %}默認標題{% endblock %}`
子模板
{% extends "templates/base.volt" %}
{% block title %}重新定義的標題{% endblock %}
父模板中塊(block)內的內容會被子模板中的同名塊中的內容替換,除非在子模板中不存在該塊的定義。
如果想要保留或引用父模板中某block的內容,可以在子模板的同名塊中使用`{{ super() }}`
新增模板函數
use Phalcon\Mvc\View\Engine\Volt;
$volt = new Volt($view, $di);
$compiler = $volt->getCompiler();
//This binds the function name 'shuffle' in Volt to the PHP function 'str_shuffle'
$compiler->addFunction('shuffle', 'str_shuffle');//第二個參數可以是函數名或匿名函數
新增過濾器
//This creates a filter 'hash' that uses the PHP function 'md5'
$compiler->addFilter('hash', 'md5');//第二個參數可以是函數名或匿名函數
緩存視圖片段
{% cache ("article-" ~ post.id) 3600 %}
{{ post.title }}
{{ post.content }}
{% endcache %}
可以在模板中直接通過服務名訪問通過DI注冊的服務。
在php模板中使用“$this->服務名”來訪問。
設計表單
模型
模型類的名稱使用表名稱且首字母大寫(如果表名稱含下劃線“_”,需要刪除下劃線并將原下劃線位置后的一個字符大寫),繼承于Phalcon\Mvc\Model。
例如,我們有數據表member_account,那么我們需要創建一個模型類MemberAccount。
模型類的文件名稱與模型類名稱一致。
數據庫操作方法
查找: find() findFirst()
$robots = Robots::find(array(
"type = 'virtual'",
"order" => "name",
"limit" => 100
));
foreach ($robots as $robot) {
echo $robot->name, "\n";
}
$robots = Robots::find(array(
"conditions" => "type = ?1",
"bind" => array(1 => "virtual") //綁定參數(數字占位符)
));
$robot = Robots::findFirst(array("type = 'virtual'", "order" => "name"));
echo "The first virtual robot name is ", $robot->name, "\n";
可用的查詢選項如下:
參數
描述
舉例
conditions
查詢操作的搜索條件。用于提取只有那些滿足指定條件的記錄。默認情況下 Phalcon\Mvc\Model 假定第一個參數就是查詢條件。
"conditions" => "name LIKE 'steve%'"
columns
只返回指定的字段,而不是模型所有的字段。 當用這個選項時,返回的是一個不完整的對象。
"columns" => "id, name"
bind
綁定與選項一起使用,通過替換占位符以及轉義字段值從而增加安全性。
"bind" => array("status" => "A", "type" => "some-time")
bindTypes
當綁定參數時,可以使用這個參數為綁定參數定義額外的類型限制從而更加增強安全性。
"bindTypes" => array(Column::BIND_TYPE_STR, Column::BIND_TYPE_INT)
order
用于結果排序。使用一個或者多個字段,逗號分隔。
"order" => "name DESC, status"
limit
限制查詢結果的數量在一定范圍內。
"limit" => 10 / "limit" => array("number" => 10, "offset" => 5)
group
從多條記錄中獲取數據并且根據一個或多個字段對結果進行分組。
"group" => "name, status"
for_update
通過這個選項, Phalcon\Mvc\Model 讀取最新的可用數據,并且為讀到的每條記錄設置獨占鎖。
"for_update" => true
shared_lock
通過這個選項, Phalcon\Mvc\Model 讀取最新的可用數據,并且為讀到的每條記錄設置共享鎖。
"shared_lock" => true
cache
緩存結果集,減少了連續訪問數據庫。
"cache" => array("lifetime" => 3600, "key" => "my-find-key")
hydration
Sets the hydration strategy to represent each returned record in the result
"hydration" => Resultset::HYDRATE_OBJECTS
如果你愿意,除了使用數組作為查詢參數外,還可以通過一種面向對象的方式來創建查詢(更多可用類方法詳見源碼phalcon/mvc/model/criteria.zep):
$robots = Robots::query()
->where("type = :type:")
->andWhere("year < 2000")
->bind(array("type" => "mechanical")) //綁定參數(字符串占位符)
->order("name")
->execute();
最后,還有一個 findFirstBy() 方法。這個方法擴展了前面提及的 “findFirst()” 方法。它允許您利用方法名中的屬性名稱,通過將要搜索的該字段的內容作為參數傳給它,來快速從一個表執行檢索操作。
的內容為首字母大寫的數據表字段名(如果字段名稱含下劃線“_”,需要刪除下劃線并將原下劃線位置后的一個字符大寫)。
例如,數據表字段名為user_name,可以采用findFirstByUserName('admpub')方法查詢。
添加: create() 或 save()
//Creating a new robot
$robot = new Robots();
$robot->type = 'mechanical';
$robot->name = 'Astro Boy';
$robot->year = 1952;
$robot->create();
//Passing an array to create
$robot = new Robots();
$robot->create(array(
'type' => 'mechanical',
'name' => 'Astroy Boy',
'year' => 1952
));
更新: update() 或 save()
//Updating a robot name
$robot = Robots::findFirst("id=100");
$robot->name = "Biomass";
$robot->update();
//Passing an array to update
$robot->create(array(
'name' => 'Biomass'
),array('name'));//第二個參數用于指定允許設置的字段的名稱,不指定的話則表示允許數據表內全部字段名稱的鍵。
如果傳入的數組的鍵與數據表字段名不一致,可以使用$robot->assign(, , )來賦值。例如:
$robot = new Robots();
$robot->assign(
array(
'name' ='Biomass'
),
array('name'=>'user_name'),
array('user_name')
);
$robot->create();
刪除: delete()
$robot = Robots::findFirst("id=100");
$robot->delete();
foreach (Robots::find("type = 'mechanical'") as $robot) {
$robot->delete();
}
運算:
count()
//How many robots are there?
$number = Robots::count();
echo "There are ", $number, "\n";
//How many mechanical robots are there?
$number = Robots::count("type='mechanical'");
echo "There are ", $number, " mechanical robots\n"
sum()
//How much are all robots?
$sum = Robots::sum(array('column' => 'price'));
echo "The total price of robots is ", $sum, "\n";
//How much are mechanical robots?
$sum = Robots::sum(array("type='mechanical'", 'column' => 'price'));
echo "The total price of mechanical robots is ", $sum, "\n";
average()
用法與sum類似
maximum()
用法與sum類似
minimum()
用法與sum類似
保存: save()
$robot = new Robots();
$robot->type = 'mechanical';
$robot->name = 'Astro Boy';
$robot->year = 1952;
if ($robot->save() == false) {
echo "Umh, We can't store robots right now ";
foreach ($robot->getMessages() as $message) {
echo $message;
}
} else {
echo "Great, a new robot was saved successfully!";
}
$robot = new Robots();
$robot->save(array('type'=>'mechanical'),array('type'));//參數分別為array data,array whiteList
指定數據返回類型
$findResult->setHydrateMode(Resultset::HYDRATE_ARRAYS);
可選的值有:Resultset::HYDRATE_ARRAYS、Resultset::HYDRATE_OBJECTS、Resultset::HYDRATE_RECORDS。
也可以這樣指定:
$robots = Robots::find(array(
'hydration' => Resultset::HYDRATE_ARRAYS
));
綁定參數
占位符
數字占位符在sql中的格式為“?數字”;
字符串占位符在sql中的格式為“:字符串:”。
參數類型
默認的參數類型為\Phalcon\Db\Column::BIND_PARAM_STR。
支持的參數類型:
Column::BIND_PARAM_NULL 綁定null類型
Column::BIND_PARAM_INT 綁定整數類型
Column::BIND_PARAM_STR 綁定字符串類型
Column::BIND_PARAM_BOOL 綁定bool值類型
Column::BIND_PARAM_DECIMAL 綁定小數類型
$robots = Robots::find(array(
"conditions" => "name = :name: AND type = ?1",
"bind" => array('name'=>'admpub',1 => 'virtual'),
"bindTypes" => array(Column::BIND_TYPE_STR, Column::BIND_TYPE_STR)
));
模型關聯
有四種關聯類型:1對1,1對多,多對1,多對多。關聯可以是單向或者雙向的,每個關聯可以是簡單的(一個1對1的模型)也可以是復雜的(1組模型)。
在Phalcon中,關聯必須定義在某個模型的initialize()方法。通過方法belongsTo(),hasOne(),hasMany()和hasManyToMany()來定義當前模型中字段到另一個模型中字段之間的關聯。上述每種方法都需要三個參數:本地字段,引用的模型,引用的字段。
方法的具體含義:
Method
Description
hasMany
Defines a 1-n relationship
hasOne
Defines a 1-1 relationship
belongsTo
Defines a n-1 relationship
hasManyToMany
Defines a n-n relationship
多對多必須關聯3個模型,并分別設置它們的關聯字段
use Phalcon\Mvc\Model;
class Robots extends Model
{
public $id;
public $name;
public function initialize()
{
$this->hasManyToMany(
"id",//當前模型中的字段
"RobotsParts",//關聯到的中間表模型
"robots_id", "parts_id",//分別為當前模型id與中間表相關聯的字段和中間表與第三張表關聯的字段,這兩個字段都在中間表內
"Parts",//第三張表模型名
"id"//第三張表中與中間表關聯的字段
);
}
}
對于使用名稱空間的情況下,可以設置別名,或在model類中使用以下方法,但是對于多對多的情況,對于第三張表由于無法設置別名,只能使用以下方法:
$this->getRelated('Robots\Parts');
驗證信息
Phalcon\Mvc\Model可以生成如下驗證類型信息:
Type
Description
PresenceOf
Generated when a field with a non-null attribute on the database is trying to insert/update a null value
ConstraintViolation
Generated when a field part of a virtual foreign key is trying to insert/update a value that doesn’t exist in the referenced model
InvalidValue
Generated when a validator failed because of an invalid value
InvalidCreateAttempt
Produced when a record is attempted to be created but it already exists
InvalidUpdateAttempt
Produced when a record is attempted to be updated but it doesn’t exist
###事件
Phalcon\Mvc\Model會根據各個操作依序各自執行如下事件:
操作
事件名
是否能終止執行?
說明
Inserting/Updating
beforeValidation
YES
Is executed before the fields are validated for not nulls/empty strings or foreign keys
Inserting
beforeValidationOnCreate
YES
Is executed before the fields are validated for not nulls/empty strings or foreign keys when an insertion operation is being made
Updating
beforeValidationOnUpdate
YES
Is executed before the fields are validated for not nulls/empty strings or foreign keys when an updating operation is being made
Inserting/Updating
onValidationFails
YES (already stopped)
Is executed after an integrity validator fails
Inserting
afterValidationOnCreate
YES
Is executed after the fields are validated for not nulls/empty strings or foreign keys when an insertion operation is being made
Updating
afterValidationOnUpdate
YES
Is executed after the fields are validated for not nulls/empty strings or foreign keys when an updating operation is being made
Inserting/Updating
afterValidation
YES
Is executed after the fields are validated for not nulls/empty strings or foreign keys
Inserting/Updating
beforeSave
YES
Runs before the required operation over the database system
Updating
beforeUpdate
YES
Runs before the required operation over the database system only when an updating operation is being made
Inserting
beforeCreate
YES
Runs before the required operation over the database system only when an inserting operation is being made
Updating
afterUpdate
NO
Runs after the required operation over the database system only when an updating operation is being made
Inserting
afterCreate
NO
Runs after the required operation over the database system only when an inserting operation is being made
Inserting/Updating
afterSave
NO
Runs after the required operation over the database system
驗證數據
use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Validator\Uniqueness;
use Phalcon\Mvc\Model\Validator\InclusionIn;
class Robots extends \Phalcon\Mvc\Model
{
public function validation()
{
$this->validate(new InclusionIn(
array(
"field" => "type",
"domain" => array("Mechanical", "Virtual")
)
));
$this->validate(new Uniqueness(
array(
"field" => "name",
"message" => "The robot name must be unique"
)
));
return $this->validationHasFailed() != true;
}
}
Phalcon\Mvc\Model\Validator包含以下驗證:
Exclusionin
Inclusionin
Numericality
PresenceOf
Regex
StringLength
Uniqueness
Url
字段注解策略
use Phalcon\Mvc\Model;
class Robots extends Model
{
/**
* @Primary
* @Identity
* @Column(type="integer", nullable=false)
*/
public $id;
/**
* @Column(type="string", length=70, nullable=false)
*/
public $name;
/**
* @Column(type="string", length=32, nullable=false)
*/
public $type;
/**
* @Column(type="integer", nullable=false)
*/
public $year;
}
支持如下注解:
Name
Description
Primary
Mark the field as part of the table’s primary key
Identity
The field is an auto_increment/serial column
Column
This marks an attribute as a mapped column
注解@Column支持如下參數:
Name
Description
type
The column’s type (string, integer, decimal, boolean)
length
The column’s length if any
nullable
Set whether the column accepts null values or not
PHQL
在執行操作之前必須要有相應的model文件存在。
創建 PHQL 查詢
方式一、直接通過創建Phalcon\Mvc\Model\Query類的實例來查詢:
use Phalcon\Mvc\Model\Query;
// Instantiate the Query
$query = new Query("SELECT * FROM Cars", $this->getDI());
// Execute the query returning a result if any
$cars = $query->execute();
方式二、在控制器或視圖中,通過modelsManager(模型管理器)來查詢:
//Executing a simple query
$query = $this->modelsManager->createQuery("SELECT * FROM Cars");
$cars = $query->execute();
//With bound parameters
$query = $this->modelsManager->createQuery("SELECT * FROM Cars WHERE name = :name:");
$cars = $query->execute(array('name' => 'Audi'));
也可以簡化的寫為:
//Executing a simple query
$cars = $this->modelsManager->executeQuery("SELECT * FROM Cars");
//Executing with bound parameters
$cars = $this->modelsManager->executeQuery("SELECT * FROM Cars WHERE name = :name:", array('name' => 'Audi'));
注意:FROM后面的那個不是表名稱而是模型類名稱,這與真正的SQL語句是不同的。由于是模型類名稱,所以也可以帶名稱空間。
executeQuery($phql)與Cars::find()的查詢結果是一樣的;
executeQuery($phql)->getFirst()與Cars::findFirst()結果一樣。
插入數據:
// Inserting using placeholders
$phql = "INSERT INTO Cars (name, brand_id, year, style) "
. "VALUES (:name:, :brand_id:, :year:, :style:)";
$status=$manager->executeQuery($sql,
array(
'name' => 'Lamborghini Espada',
'brand_id' => 7,
'year' => 1969,
'style' => 'Grand Tourer',
)
);
//Create a response
#$response = new Response();
//Check if the insertion was successful
if ($status->success() == true) {
//Change the HTTP status
#$response->setStatusCode(201, "Created");
#$robot->id = $status->getModel()->id;
#$response->setJsonContent(array('status' => 'OK', 'data' => $robot));
} else {
//Change the HTTP status
#$response->setStatusCode(409, "Conflict");
//Send errors to the client
$errors = array();
foreach ($status->getMessages() as $message) {
$errors[] = $message->getMessage();
}
#$response->setJsonContent(array('status' => 'ERROR', 'messages' => $errors));
}
更新、刪除數據與插入數據類似。
使用查詢構建器創建查詢
//Getting a whole set
$robots = $this->modelsManager->createBuilder()
->from('Robots')
->join('RobotsParts')
->orderBy('Robots.name')
->getQuery()
->execute();
//Getting the first row
$robots = $this->modelsManager->createBuilder()
->from('Robots')
->join('RobotsParts')
->orderBy('Robots.name')
->getQuery()
->getSingleResult();
綁定參數
//Passing parameters in the query construction
$robots = $this->modelsManager->createBuilder()
->from('Robots')
->where('name = :name:', array('name' => $name))
->andWhere('type = :type:', array('type' => $type))
->getQuery()
->execute();
//Passing parameters in query execution
$robots = $this->modelsManager->createBuilder()
->from('Robots')
->where('name = :name:')
->andWhere('type = :type:')
->getQuery()
->execute(array('name' => $name, 'type' => $type));
轉義保留字
將保留字用中括號括起來。例如:
$phql = "SELECT * FROM [Update]";
$result = $manager->executeQuery($phql);
$phql = "SELECT id, [Like] FROM Posts";
$result = $manager->executeQuery($phql);
其它
URL重定向
重定向用來在當前的處理中跳轉到其它的處理流:
// 此路由重定向到其它的路由
$app->post('/old/welcome', function () use ($app) {
$app->response->redirect("new/welcome")->sendHeaders();
});
$app->post('/new/welcome', function () use ($app) {
echo 'This is the new Welcome';
});
有以下跳轉方式:
//設置一個內部跳轉
$this->response->redirect( 'posts/index' );
// 外部跳轉url
$this->response->redirect( 'http://www.admpub.com/blog', true );
// 設置跳轉 http狀態
$this->resopnse->redirect( 'http://www.admpub.com/blog' , true , 301 );
重定向不會禁用視圖組件。因此,如果你想從一個controller/action重定向到另一個controller/acton上,視圖將正常顯示。當然,你也可以使用 $this->view->disable() 禁用視圖輸出。
存儲/獲取 Session數據
$this->session->set("session_name", "session_value");
$this->session->has("session-name");
$this->session->get("session-name");
$this->session->remove("session-name");
$this->session->destroy();
From 表單接收
//獲取$_POST['name'],第二個參數是過濾器,還可以傳遞第三個參數作為默認值,第四個參數為是否允許為空。
//如果第一個參數為null或不傳遞任何參數的話,返回$_POST,以下getXXX()方法類似。
$name= $this->request->getPost("name", "string");
//獲取$_GET['email']
$email=$this->request->getQuery("email", "email");
//獲取$_REQUEST['email']
$email=$this->request->get("email", "email");
還有 $this->request->getPut、$this->request->getServer等等。
要判斷某個鍵的元素是否存在只需要將這里的get換成has即可。
比如:hasQuery('email')、has('email')、hasPost('email')、hasPut('email')、hasServer('HTTP_REFERER')。
支持的過濾器有:
absint
int
int!
使用intval函數處理
string
float
float!
使用doubleval函數處理
alphanum
trim
striptags
lower
upper
request的更多方法請參考phalcon源代碼:phalcon/http/request.zep
從容器中獲取的服務的最簡單方式就是只用get方法,它將從容器中返回一個新的實例:
<?php $request = $di->get('request'); ?>
或者通過下面這種魔術方法的形式調用:
<?php $request = $di->getRequest(); ?>
處理Not-Found
當用戶訪問未定義的路由時, 微應用會試著執行 "Not-Found"處理器。
$app->notFound(function () use ($app) {
$app->response->setStatusCode(404, "Not Found")->sendHeaders();
echo 'This is crazy, but this page was not found!';
});
微應用
事件名
觸發
是否可中止操作?
before
應用請求處理之前執行,常用來控制應用的訪問權限
Yes
after
請求處理后執行,可以用來準備回復內容
No
finish
發送回復內容后執行, 可以用來執行清理工作
No
### REST API
[https://docs.phalconphp.com/zh/latest/reference/tutorial-rest.html](https://docs.phalconphp.com/zh/latest/reference/tutorial-rest.html)
使用 phalcon devtools
如果提醒無法找到類這樣的錯誤提示,需要在phalcon.php文件中添加以下代碼:
spl_autoload_register(function($className){
$classDir = __DIR__.'/scripts/';
$classFile = $classDir . str_replace('\\', '/', $className) . '.php';
if (file_exists($classFile)) require_once($classFile);
});
把所有文件復制到現有phalcon項目下新建的“devtools”文件夾中,并將其中的webtools.php復制到public文件夾下,并在public文件夾內新建文件webtools.config.php,內容為:
define('PTOOLSPATH',__DIR__.'/../devtools/');
define('PTOOLS_IP','127.0.0.1');
spl_autoload_register(function($className){
$classDir = PTOOLSPATH.'/scripts/';
$classFile = $classDir . str_replace('\\', '/', $className) . '.php';
if (file_exists($classFile)) require_once($classFile);
});
修改public文件夾下的webtools.php文件,將其中的require 'webtools.config.php';剪切到文件最開頭的<?php下一行 。
經過測試,該工具對PHP版本要求較高,我在PHP5.4下無法使用。
#End
總結
以上是生活随笔為你收集整理的php框架费尔康,GitHub - majixian/study-phalcon: phalcon(费尔康)框架学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA语言中流程控制(顺序结构、判断语
- 下一篇: android 触摸防抖,一种触摸屏防抖