phalcon(费尔康)框架学习笔记

http://www.qixing318.com/article/phalcon-framework-to-study-notes.html

目录结构
 

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;

即可解决。

路由规则

添加路由规则:

<?php
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。

指定参数名称

  • 方式一,在数组中指定:

    <?php
    $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中,这些被命名的参数可以用如下方式这样访问:

<?php
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'
));

钩子事件

转换某个参数的值:

<?php
//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');

路由分组

<?php
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);

或者:

<?php
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:

<?php
//Add the group to the router
$router->mount(new BlogRoutes());

路由命名

<?php
$route = $router->add("/posts/{year}/{title}", "Posts::show");
$route->setName("show-posts"); //或者这样
$router->add("/posts/{year}/{title}", "Posts::show")->setName("show-posts");

然后,我们就可以根据命名来生成符合这条路由的网址了:

<?php
// returns /posts/2012/phalcon-1-0-released
echo $url->get(array(
"for" => "show-posts", //路由名称
"year" => "2012", //参数year的值
"title" => "phalcon-1-0-released" //参数title的值
));

指定URI来源

<?php
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 定义默认值。当一个路由缺少其中任何一项时,路由器可以自动用默认值填充:

<?php
//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'
));

匿名路由

此组件提供了一个与注解服务集成的变体。使用此策略可以在控制器中直接写路由。

<?php
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;
};

可以按如下方式定义注解:

<?php
/**
* @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方法:

<?php
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');选择视图:

  1. 如果pick方法接收到一个不包含“/”的字符串则仅仅设置LEVEL_ACTION_VIEW级视图;如果包含“/”则同时还会把第一个“/”前面的部分作为LEVEL_LAYOUT级视图,比如这里会使用“视图文件目录/layouts/index.phtml”文件
  2. 如果接收到一个数字索引数组,则会将编号为0的元素作为LEVEL_ACTION_VIEW级视图,将编号为1的元素作为LEVEL_LAYOUT级视图

关闭视图

如果你的控制器不在视图里产生(或没有)任何输出,你可以禁用视图组件来避免不必要的处理:

$this->view->disable();

在模板中包含局部模板

<?php $this->partial('shared/login');?>

或者同时传递变量给局部模板,每一个索引最终会作为变量在局部模板中被赋值:

<?php
$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' //缓存索引名
));

注册缓存服务:

<?php

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服务时全局指定模板引擎:

    <?php
    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种不同含义的起始标签

  1. {% ... %}包裹的标签用于赋值或执行for循环、if条件判断等语句
  2. {{ ... }}包裹的标签用于打印表达式的结果到模板
  3. {# ... #}包裹注释,前后标签可以处于不同行

语法详解

  • {{ 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 (<br />). 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 }} <br/>
{% 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
  • 宏定义:https://docs.phalconphp.com/zh/latest/reference/volt.html#macros

    {%- macro my_input(name, class="input-text") %}
    {% return text_field(name, 'class': class) %}
    {%- endmacro %} {# Call the macro #}
    {{ '<p>' ~ my_input('name') ~ '</p>' }}
    {{ '<p>' ~ my_input('name', 'input-text') ~ '</p>' }}

    由以上代码可见,模板中字符串间连接符为~!

  • 使用标签助手:https://docs.phalconphp.com/zh/latest/reference/volt.html#using-tag-helpers

    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() }}

  • 新增模板函数

    <?php
    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');//第二个参数可以是函数名或匿名函数
  • 编写扩展:https://docs.phalconphp.com/zh/latest/reference/volt.html#extensions

  • 缓存视图片段

    {% cache ("article-" ~ post.id) 3600 %}
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
    {% endcache %}
  • 可以在模板中直接通过服务名访问通过DI注册的服务。
    在php模板中使用“$this->服务名”来访问。

设计表单

https://docs.phalconphp.com/zh/latest/reference/tags.html

模型

https://docs.phalconphp.com/zh/latest/reference/models.html

模型类的名称使用表名称且首字母大写(如果表名称含下划线“_”,需要删除下划线并将原下划线位置后的一个字符大写),继承于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):

<?php
$robots = Robots::query()
->where("type = :type:")
->andWhere("year < 2000")
->bind(array("type" => "mechanical")) //绑定参数(字符串占位符)
->order("name")
->execute();

最后,还有一个 findFirstBy<property-name>() 方法。这个方法扩展了前面提及的 “findFirst()” 方法。它允许您利用方法名中的属性名称,通过将要搜索的该字段的内容作为参数传给它,来快速从一个表执行检索操作。

<property-name>的内容为首字母大写的数据表字段名(如果字段名称含下划线“_”,需要删除下划线并将原下划线位置后的一个字符大写)。

例如,数据表字段名为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个模型,并分别设置它们的关联字段

<?php
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

验证数据

<?php

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包含以下验证:

Email
Exclusionin
Inclusionin
Numericality
PresenceOf
Regex
StringLength
Uniqueness
Url

字段注解策略

<?php

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类的实例来查询:

    <?php
    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(模型管理器)来查询:

    <?php
    //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重定向

重定向用来在当前的处理中跳转到其它的处理流:

<?php
// 此路由重定向到其它的路由
$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')。

支持的过滤器有:

  • email

  • 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"处理器。

<?php
$app->notFound(function () use ($app) {
$app->response->setStatusCode(404, "Not Found")->sendHeaders();
echo 'This is crazy, but this page was not found!';
});

微应用

https://docs.phalconphp.com/zh/latest/reference/micro.html
支持如下的中间件事件:

事件名 触发 是否可中止操作?
before 应用请求处理之前执行,常用来控制应用的访问权限 Yes
after 请求处理后执行,可以用来准备回复内容 No
finish 发送回复内容后执行, 可以用来执行清理工作 No

REST API

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下无法使用。

phalcon(费尔康)框架学习笔记的更多相关文章

  1. Yii框架学习笔记(二)将html前端模板整合到框架中

    选择Yii 2.0版本框架的7个理由 http://blog.chedushi.com/archives/8988 刚接触Yii谈一下对Yii框架的看法和感受 http://bbs.csdn.net/ ...

  2. JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue

    前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...

  3. JavaSE中Collection集合框架学习笔记(3)——遍历对象的Iterator和收集对象后的排序

    前言:暑期应该开始了,因为小区对面的小学这两天早上都没有像以往那样一到七八点钟就人声喧闹.车水马龙. 前两篇文章介绍了Collection框架的主要接口和常用类,例如List.Set.Queue,和A ...

  4. JavaSE中Map框架学习笔记

    前言:最近几天都在生病,退烧之后身体虚弱.头疼.在床上躺了几天,什么事情都干不了.接下来这段时间,要好好加快进度才好. 前面用了三篇文章的篇幅学习了Collection框架的相关内容,而Map框架相对 ...

  5. JavaSE中线程与并行API框架学习笔记1——线程是什么?

    前言:虽然工作了三年,但是几乎没有使用到多线程之类的内容.这其实是工作与学习的矛盾.我们在公司上班,很多时候都只是在处理业务代码,很少接触底层技术. 可是你不可能一辈子都写业务代码,而且跳槽之后新单位 ...

  6. JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?

    前言:休整一个多月之后,终于开始投简历了.这段时间休息了一阵子,又病了几天,真正用来复习准备的时间其实并不多.说实话,心里不是非常有底气. 这可能是学生时代遗留的思维惯性--总想着做好万全准备才去做事 ...

  7. scrapy爬虫框架学习笔记(一)

    scrapy爬虫框架学习笔记(一) 1.安装scrapy pip install scrapy 2.新建工程: (1)打开命令行模式 (2)进入要新建工程的目录 (3)运行命令: scrapy sta ...

  8. TensorFlow机器学习框架-学习笔记-001

    # TensorFlow机器学习框架-学习笔记-001 ### 测试TensorFlow环境是否安装完成-----------------------------```import tensorflo ...

  9. spring mvc 及NUI前端框架学习笔记

    spring mvc 及NUI前端框架学习笔记 页面传值 一.同一页面 直接通过$J.getbyName("id").setValue(id); Set值即可 二.跳转页面(bus ...

随机推荐

  1. Python类的定义与使用

    #! /usr/bin/python # Filename:objvar.py class Person: '''Represents a person.''' population = 0 def ...

  2. google prettify 代码高亮显示

    引入js和css文件 下载地址 http://files.cnblogs.com/jaday/prettify.zip js文件代码 !function(){var q=null;window.PR_ ...

  3. acdream 1148 GCD SUM 莫比乌斯反演 ansx,ansy

    GCD SUM Time Limit: 8000/4000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatis ...

  4. enc

    enc [问题背景] zhx 和他的妹子聊天. [问题描述] 考虑一种简单的加密算法. 假定所有句子都由小写英文字母构成,对于每一个字母,我们将它唯一地映射到另一个字母.例如考虑映射规则: a-> ...

  5. 简单封装JDBC

    package com.sunshine.frimework.tool;import java.sql.Connection;import java.sql.DriverManager;import ...

  6. 【leetcode❤python】206. Reverse Linked List

    # Definition for singly-linked list.# class ListNode(object):#     def __init__(self, x):#         s ...

  7. HDU 5013 City Tour

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5013 题意: 思路: 这里有错,是Hi(x)=sigama(Hji)(j属于x) const int ...

  8. 蒙特卡洛法计算定积分—Importance Sampling

    如上图所示,计算区间[a  b]上f(x)的积分即求曲线与X轴围成红色区域的面积.下面使用蒙特卡洛法计算区间[2  3]上的定积分:∫(x2+4*x*sin(x))dx # -*- coding: u ...

  9. vim使用札记

    最近开始用vim编辑器了,从最开始的配置到现在慢慢使用,我在这儿会贴出一些我的使用上遇到过的问题和如何解决的方案,留给自己和一些会用到的人看看 1.vim怎么使汇编语法高亮 开始不知道,然后把文件的后 ...

  10. SpringMVC 配置过滤器解决中文乱码问题

    <!-- 字符集过滤器 -->      <filter>          <filter-name>Charset</filter-name>   ...