CakePHP之控制器
控制器
控制器是MVC中的“C”。
如果你的网站使用Cake框架制作,一般根据url地址和通过路由,就会找到正确的控制器,然后控制器的动作就会被调用。
一个控制器需要解释请求数据、确保使用正确的模型、渲染正确的视图。
控制器可以被认为是模型和视图的中间人。
我们一般保持控制器瘦小,而模型肥胖。 这样代码更容易复用和测试。
通常,控制器用于管理关于单个模型的逻辑。
例如,如果你为一个在线面包店制作网站, 你可能会有 RecipesController 和 IngredientsController,来管理你的食谱和它们的成分。
在 CakePHP 中,控制器根据它们处理的主要模型来命名。
当然也完全可以让控制器处理多个模型。
你的应用程序的控制器都继承于 AppController 类,而 AppController 类又继承于核心的 Controller 类。
AppController 类定义在 /app/Controller/AppController.php
控制器提供了一些方法,称为*动作*(action)。动作是控制器处理请求的方法。
在默认情况下, 控制器所有的公有方法都是动作,可以从网址(URL)访问。
动作负责解释请求,并生成响应。 通常响应是以渲染视图的方式产生,但也可以用其他的方式来生成响应。
App 控制器
如介绍中说所说, AppController 控制器是你应用程序中所有控制器的父类。
AppController 本身继承了 CakePHP 核心库中的 Controller 类。 AppController 定义在 /app/Controller/AppController.php 中,像这样:
class AppController extends Controller {
}
在你的 AppController 中创建的控制器的属性和方法, 可以被你应用程序中所有的控制器使用。这是为你应用程序中所有的控制器编写共享代码的理想地方。
组件(你以后将会了解到)最好用于多个(但不一定是所有)控制器中用到的共享代码。
虽然通常的面向对象继承规则依然适用, CakePHP 针对特殊的控制器属性做了一些额外的工作。
控制器使用的组件(components)和助件(helpers)列表被特别处理。
对这两个列表, AppController 中的值会和控制器子类中的(同名)数组合并。
子类中的值总是覆盖 AppController 中的值。
Note
CakePHP 将下列变量从 AppController 合并到你应用程序的控制器:
- $components
- $helpers
- $uses
如果你在你的 AppController 中定义 var $helpers,记住加入缺省的 Html 和 Form 助件。
也请记住,最好在控制器子类的回调方法中调用 AppController 的回调方法:
public function beforeFilter() {
parent::beforeFilter();
}
请求参数
当一个url请求提交给 CakePHP 应用程序时, CakePHP 的 Router 和 Dispatcher 类使用 Routes Configuration 来查找和创建正确的控制器。
请求数据被封装在一个请求对象中。 CakePHP 把所有重要的请求信息放在 $this->request 属性中。
关于 CakePHP 请求对象的更多信息,请参看 CakeRequest 这一节。
控制器动作
控制器动作负责将请求参数转换成对提交请求的 浏览器/用户 的响应。 CakePHP 用命名约定使这个过程简单化了,去掉了一些你要自己写的样板(boiler-plate)代码。
根据约定 CakePHP 会渲染一个以动作名称命名的视图。
回到我们在线烹饪的例子,我们的 RecipesController 也许会有view(),share() 和 search() 动作。
控制器可以在 /app/Controller/RecipesController.php 文件中找到,有如下内容:
# /app/Controller/RecipesController.php class RecipesController extends AppController {
public function view($id) {
// 这里是动作逻辑 ...
} public function share($customerId, $recipeId) {
// 这里是动作逻辑 ...
} public function search($query) {
// 这里是动作逻辑 ...
}
}
这些动作的视图文件将会是 app/View/Recipes/view.ctp,app/View/Recipes/share.ctp 和app/View/Recipes/search.ctp。
根据约定,视图文件名是动作名称的下划线分隔的小写版本。
控制器动作通常用 set() 创建上下文,供 View 来渲染视图。正是得益于 CakePHP 使用的约定,你不必手动创建和渲染视图。
而是,一旦控制器动作完成, CakePHP 会处理视图的渲染和发送。
如果出于某种原因,你想要跳过默认的行为,下面的两种技术都可以跳过默认的视图渲染过程。
- 如果你从你的控制器动作返回一个字符串,或者可以转换成字符串的对象,这就会被作为响应体。(其实就是把动作变成一个有返回值的函数!!)
- 你可以返回一个 CakeResponse 对象,包含创建的完整响应。(这个还不太明白!!)
当控制器方法用于 requestAction() 时,你经常想返回不是字符串的数据。
如果你有用于正常网页请求+ requestAction 的控制器方法,你应当在返回前检查请求类型:
class RecipesController extends AppController {
public function popular() {
$popular = $this->Recipe->popular();
if (!empty($this->request->params['requested'])) {
return $popular;
}
$this->set('popular', $popular);
}
}
上面的控制器动作是一例,说明同一个方法如何用于 requestAction() 和正常的请求。
对非 requestAction 请求返回数组数据会引起错误,应当避免。(对于非 requestAction 请求,动作是不该给予返回值的!!)
关于使用 requestAction() 的更多窍门,请参看 Controller::requestAction() 一节。
为了让你在自己的应用程序中有效地使用控制器,我们来介绍一些 CakePHP 的控制器提供的核心属性和方法。
请求生命周期回调
- class Controller
CakePHP 控制器带有的回调,让你可以用来在请求生命周期的各个阶段插入逻辑:
- Controller::beforeFilter()
-
这个函数在控制器每个动作之前执行。 这里可以方便地检查有效的会话,或者检查用户的权限。
Note
对未找到的动作和脚手架动作,beforeFilter() 方法也会被调用。
- Controller::beforeRender()
-
在控制器动作逻辑之后,但在视图渲染之前被调用。这个回调不常用,但如果你在一个动作结束前自己调用 render(),就可能会需要。
- Controller::afterFilter()
-
在每个动作之后,且在渲染完成之后,才调用。这是控制器运行的最后一个方法。
除了控制器生命周期的回调, 组件 Components 也提供了一组类似的回调。
控制器方法
如果想要知道控制器方法的完整列表和描述,请查阅 CakePHP API, http://api20.cakephp.org/class/controller。
与视图交互
控制器有若干种方式与视图交互。首先可以用 set() 传递数据给视图。你也可以决定用哪个视图类,从控制器渲染哪个视图文件。
- Controller::set(string $var, mixed $value)
-
set() 方法是从你的控制器传递数据到你的视图的主要方式。一旦你用了 set(),变量就可以在你的视图中访问到。
// 首先从控制器传递数据:
$this->set(‘color’, ‘pink’);
// 然后,在视图里,你可以运用该数据: ?>
你为蛋糕选择了 <?php echo $color; ?> 色的糖霜。
set() 方法也接受关联数组作为其第一个参数。这经常是快速为视图设置一组信息的方法。
Changed in version 1.3: 数组的键在赋值给视图前,不再会被 inflected 了(‘underscored_key’ 不再会变成 ‘underscoredKey’,等等)
$data = array(
'color' => 'pink',
'type' => 'sugar',
'base_price' => 23.95
); // 使 $color,$type 和 $base_price 能够被视图使用:
$this->set($data);属性 $pageTitle 不再存在,用 set() 设置标题:
$this->set('title_for_layout', '这是页面标题');
- Controller::render(string $view, string $layout)
-
render() 方法在每个请求的控制器动作结束时会被自动调用。这个方法执行所有的视图逻辑(使用你用 set() 方法给出的数据),将视图放入其布局中,并把视图提供给最终用户。
渲染使用的缺省视图文件由约定决定。如果请求的是 RecipesController 的 search() 动作,视图文件 /app/View/Recipes/search.ctp 将被渲染:
class RecipesController extends AppController {
// ...
public function search() {
// 渲染视图 /View/Recipes/search.ctp
$this->render();
}
// ...
}虽然 CakePHP 会在每个动作的逻辑之后自动调用它(除非你设置了 $this->autoRender 为 false),你仍然可以用该方法通过用$action 指定一个控制器的动作来指定另外一个视图文件。
如果 $view 以 ‘/’ 开头,就被认为是相对于 /app/View 的视图或者元素文件。这允许直接渲染元素,在 ajax 请求中很有用。
// 渲染 /View/Elements/ajaxreturn.ctp 中的元素
$this->render('/Elements/ajaxreturn');$layout 参数允许你指定视图渲染于其中的布局。
渲染某个视图
在你的控制器中你也许想要渲染与约定不同的视图。为此你可以直接调用 render()。你一旦调用了 render(), CakePHP 就不会试图再次渲染该视图了:
class PostsController extends AppController {
public function my_action() {
$this->render('custom_file');
}
}
这会渲染 app/View/Posts/custom_file.ctp,而不是 app/View/Posts/my_action.ctp。
你也可以用下面的语法渲染插件中的视图: $this->render('PluginName.PluginController/custom_file')。例如:
class PostsController extends AppController {
public function my_action() {
$this->render('Users.UserDetails/custom_file');
}
}
这会渲染 app/Plugin/Users/View/UserDetails/custom_file.ctp。
流程控制
- Controller::redirect(mixed $url, integer $status, boolean $exit)
-
你最常用到的流程控制方法是 redirect()。
这个方法的第一个参数接受的是 CakePHP 相对网址的形式。当一个用户成功地提交了一份订单之后,你也许想要引导他们到收据页面。:
public function place_order() {
// 这里是确认订单的逻辑
if ($success) {
$this->redirect(array('controller' => 'orders', 'action' => 'thanks'));
} else {
$this->redirect(array('controller' => 'orders', 'action' => 'confirm'));
}
}$url 参数可以使用相对或者绝对路径:
$this->redirect('/orders/thanks'));
$this->redirect('http://www.example.com');你也可以传递数据给动作:
$this->redirect(array('action' => 'edit', $id));
redirect() 的第二个参数允许你指定伴随跳转的 HTTP 状态编码。你也许要根据跳转的性质,使用301(页面永久性移动)或者303(参见其他页面)。
该方法会在跳转后调用 exit(),除非你设置第三个参数为 false。
如果你需要跳转到 referer 页面,你可以用:
$this->redirect($this->referer());
该方法也支持命名的参数。如果你要跳转到类似 http://www.example.com/orders/confirm/product:pizza/quantity:5的页面,你可以用:
$this->redirect(array('controller' => 'orders', 'action' => 'confirm', 'product' => 'pizza', 'quantity' => 5));
- Controller::flash(string $message, string|array $url, integer $pause, string $layout)
-
如同 redirect(),flash() 方法用于在一项操作之后引导用户到一个新的页面。
flash() 方法的不同之处在于,它会显示一条信息,然后才引导用户到另一个网址。
第一个参数应当为要显示的信息,而第二个参数是 CakePHP 的相对地址。
CakePHP 会显示 $message 并停留 $pause 秒,再引导用户跳转。
如果你有想用某个模板来显示你的跳转信息,你可以在 $layout 参数指定那个布局的名字。
对于页面内的闪现提示信息,请务必参考 SessionComponent 组件的 setFlash() 方法。
回调
除了 请求生命周期回调, CakePHP 还支持脚手架相关的的回调。
- Controller::beforeScaffold($method)
-
$method 是调用的方法名,例如 index,edit,等等。
- Controller::afterScaffoldSave($method)
-
$method 是调用的方法名,为 edit 或 update。
- Controller::afterScaffoldSaveError($method)
-
$method 是调用的方法名,为 edit 或 update。
- Controller::scaffoldError($method)
-
$method 是调用的方法名,例如 index,edit,等等。
其它有用的方法
- Controller::constructClasses()
-
这个方法加载控制器需要的模型。此加载过程通常由 CakePHP 执行,但在不同的情况下使用控制器时,有该方法就很方便。
如果你在命令行脚本或者一些其它外部应用中需要 CakePHP,那么 constructClasses() 就会很方便。
- Controller::referer(mixed $default = null, boolean $local = false)
-
返回当前请求的 referring 网址。如果 HTTP_REFERER 无法从请求文件头部读出,参数 $default 可以用来提供一个缺省的网址。所以与其这样:
class UserController extends AppController {
public function delete($id) {
// 删除的代码在这里,然后...
if ($this->referer() != '/') {
$this->redirect($this->referer());
} else {
$this->redirect(array('action' => 'index'));
}
}
}你可以这样:
class UserController extends AppController {
public function delete($id) {
// 删除的代码在这里,然后...
$this->redirect($this->referer(array('action' => 'index')));
}
}如果 $default 没有设置,该功能的缺省值为域的根目录 - ‘/’。
参数 $local 如果设为 true, referring 网址会被限制为本地服务器。
- Controller::disableCache()
-
用来告诉用户的**浏览器**不要缓存当前请求的结果。这不同于视图缓存,稍后的章节会介绍到。
在此作用下发送的(响应)头部信息为:
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: [current datetime] GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
- Controller::postConditions(array $data, mixed $op, string $bool, boolean $exclusive)
-
用此方法来将一组提交(POSTed)的模型数据(来自与 HtmlHelper 兼容的输入)转换成一组模型的查找条件。
这个函数提供了一个建立查找逻辑的快捷方式。例如,管理人员也许想要能够查询订单,以便知道发送什么货物。
你可以用 CakePHP 的 FormHelper 和HtmlHelper 来快速创建基于 Order 模型的表单。然后控制器的动作就能够用从该表单提交的数据创建出查找条件:
public function index() {
$conditions = $this->postConditions($this->request->data);
$orders = $this->Order->find('all', compact('conditions'));
$this->set('orders', $orders);
}如果 $this->request->data['Order']['destination'] 等于 “Old Towne Bakery”,
postConditions 方法会把该条件转换成 Model->find() 方法可以使用的数组。在此例中,将是 array('Order.destination' => 'Old Towne Bakery')。
如果你要在条件间使用不同的 SQL 运算符,用第二个参数指定:
/*
Contents of $this->request->data
array(
'Order' => array(
'num_items' => '4',
'referrer' => 'Ye Olde'
)
)
*/ // 让我们得到至少4份包含 'Ye Olde' 的订单
$conditions = $this->postConditions(
$this->request->data,
array(
'num_items' => '>=',
'referrer' => 'LIKE'
)
);
$orders = $this->Order->find('all', compact('conditions'));第三个参数让你可以告诉 CakePHP 在查找条件之间使用什么 SQL 逻辑运算符。象 ‘AND’,‘OR’ 和 ‘XOR’ 这样的字符串都是合法的值。
最后,如果最后一个参数设为 true,而 $op 参数是一个数组, $op 未包含的字段将不会出现在返回的条件中。
- Controller::paginate()
-
该方法用于将模型得到的结果分页。你可以指定分页大小,模型的查找条件,等等。请参看 pagination 一节以得到关于如何使用 paginate 的更多细节。
- Controller::requestAction(string $url, array $options)
-
该函数从任何地方调用一个控制器的动作,并从该动作返回数据。
传入的 $url 参数是一个 CakePHP 网址(/controllername/actionname/params)。要给接受的控制器动作传入更多数据,就加入到 $options 数组中。
Note
从 options 参数传入 ‘return’,你就能用 requestAction() 得到完整渲染的视图: requestAction($url,array('return'));。重要的是,请注意,从控制器方法用 ‘return’ 调用 requestAction,可能引起脚本和 css 标签工作不正常。
Warning
如果不使用缓存,requestAction 会导致糟糕的性能。所以在控制器或者模型中都极少适用。
requestAction 最好和(缓存的)元素一起使用 —— 作为一种在渲染前为元素获取数据的方法。
让我们用一个把“近期评论”的元素放入布局的例子。首先我们要增加一个控制器函数来返回数据:
// Controller/CommentsController.php
class CommentsController extends AppController {
public function latest() {
if (empty($this->request->params['requested'])) {
throw new ForbiddenException();
}
return $this->Comment->find('all', array('order' => 'Comment.created DESC', 'limit' => 10));
}
}你应当总是包括确保 requestAction 方法的调用确实源自 requestAction 的检查。
不做此检查,将允许 requestAction 可以从网址直接访问,通常这样不好。
如果我们现在增加一个简单的元素来调用此函数:
// View/Elements/latest_comments.ctp $comments = $this->requestAction('/comments/latest');
foreach ($comments as $comment) {
echo $comment['Comment']['title'];
}然后我们就可以象下面这样,把这个元素放在任何地方,得到输出:
echo $this->element('latest_comments');
用这样的写法,任何时候元素被渲染,都会有一个请求被提交到控制器来获取数据,数据会被处理并返回。
当然,与上面的警告相一致,最好使用元素缓存,来避免不必要的处理。这样修改对元素的调用:
echo $this->element('latest_comments', array('cache' => '+1 hour'));
只要缓存的元素视图文件还存在并有效, requestAction 就不会被调用。
另外,现在 requestAction 接受基于数组的 Cake 风格的网址:
echo $this->requestAction(
array('controller' => 'articles', 'action' => 'featured'),
array('return')
);这允许 requestAction 的调用略过 Router::url 的使用,从而可以改善性能。基于网址的数组与 HtmlHelper::link() 使用的相同,除了有一点区别 - 如果你使用命名参数或者传入参数(named or passed parameters),你必须把它们放入第二个数组并配以正确的键。这是因为 requestAction 会把命名参数数组(requestAction 的第二个参数)与 Controller::params 成员数组合并,而不把命名参数数组明确地放在 ‘named’ 键中; $option 数组中其它成员也可以在请求的动作的 Controller::params 数组中可以得到:
echo $this->requestAction('/articles/featured/limit:3');
echo $this->requestAction('/articles/view/5');以数组形式在 requestAction 中就会是:
echo $this->requestAction(
array('controller' => 'articles', 'action' => 'featured'),
array('named' => array('limit' => 3))
); echo $this->requestAction(
array('controller' => 'articles', 'action' => 'view'),
array('pass' => array(5))
);Note
不像其它地方,数组网址和字符串网址类似,requestAction 对它们的处理不同。
当把数组网址和 requestAction() 一起使用时,你一定要给出请求的动作所需要的**所有**参数。这包括象 $this->request->data这样的参数。除了传入所有需要的参数外,命名参数和传入参数必须在第二个数组提供,如上面所示。
- Controller::loadModel(string $modelClass, mixed $id)
-
当你要使用的模型不是控制器的缺省模型或者关联模型时,loadModel 函数就很方便:
$this->loadModel('Article');
$recentArticles = $this->Article->find('all', array('limit' => 5, 'order' => 'Article.created DESC')); $this->loadModel('User', 2);
$user = $this->User->read();
控制器属性
控制器属性的完整列表及其描述,请参看 CakePHP API,http://api20.cakephp.org/class/controller。
- property Controller::$name
-
$name 属性应当置为控制器名称。通常这只是控制器使用的模型的复数形式。该属性可以省略,如果 CakePHP 不 inflecting 它的话:
// $name 控制器属性用法示例
class RecipesController extends AppController {
public $name = 'Recipes';
}
$components,$helpers 和 $uses
下一个最常用的控制器属性告诉 CakePHP 当前控制器使用什么助件,组件和模型。使用这些属性让由 $components 和 $uses 指定的 MVC 类成为类变量(例如 $this->模型名称)可以为控制器所用,而由 $helpers 指定的类作为对象引用变量($this->{$helpername})可以被视图使用。
Note
每个控制器缺省就有这些类中的某些,所以你也许完全不用配置你的控制器。
- property Controller::$uses
-
缺省情况下,控制器可以访问它们的主模型。我们的 RecipesController 可以用 $this->Recipe 访问 Recipe 模型类,而我们的 ProductsController 也可以通过 $this->Product 来访问 Product 模型。然而,当要使用 $uses 变量让控制器访问更多的模型时,当前控制器的(主要)模型名称一定也要包括在内。
如果你在控制器中不想使用(任何)模型,就设置 public $uses = array()。这允许你使用控制器,而不需要相应的模型文件。然而 AppController 中定义的模型仍然会加载。你也可以用 false 来完全不加载任何模型,即使是 AppController 中定义的模型。
Changed in version 2.1: Uses 变量现在有了新的缺省值,而且它对 false 的处理也不同了。
- property Controller::$helpers
-
缺省情况下 Html,Form 和 Session 助件都是可用的,就像 SessionComponent 组件一样。但如果你选择在 AppController 中定义你自己的 $helpers 数组,记得包括 Html 和 Form,如果你还想让它们在控制器中缺省就可用的话。要了解更多关于这些类的信息,就请查看本手册后面的相关章节。
让我们来看看如何让 CakePHP 控制器知道你打算使用额外的 MVC 类:
class RecipesController extends AppController {
public $uses = array('Recipe', 'User');
public $helpers = array('Js');
public $components = array('RequestHandler');
}这些变量每个都会与它们继承的值合并,所以没有必要(比如)再次声明 Form 助件,或者任何你在 App 控制器中已经声明的东西。
- property Controller::$components
-
数组 components 允许你设置控制器要用哪个 组件 Components。
就像 $helpers 和 $uses 一样,你控制器中的组件(components)会与 AppController 中的合并。如同 $helpers,你可以传递参数给组件。
CakePHP之控制器的更多相关文章
- cakephp引入其他控制器封装方法
- CakePHP之请求与响应对象
请求与响应对象 请求与响应对象在 CakePHP 2.0 是新增加的.在之前的版本中,这两个对象是由数组表示的,而相关的方法是分散在RequestHandlerComponent,Router,Dis ...
- CakePHP之Model
模型 模型在应用程序中是作为业务层而存在的(怎么感觉是数据层......).这就意味着,模型应当负责管理几乎所有涉及数据的事情,其合法性,以及你的业务领域中数据在工作流程中的演化和互动 . 通常模型类 ...
- CakePHP的blog教程三
简单的身份验证和授权应用 接着我们blog教程的例子,如果我们想要建立一个根据登录的用户身份来决定其安全访问到正确的urls. 同时我们还有其他的需求: 允许我们的blog有多个作者,每一个作者都可以 ...
- 主流PHP框架间的比较(Zend Framework,CakePHP,CodeIgniter,Symfony,ThinkPHP,FleaPHP)
Zend Framework 优点: Zend Framework大量应用了PHP5中面向对象的新特征:接口.异常.抽象类.SPL等等.这些东西的应用让Zend Framework具有高度的模块化和灵 ...
- CakePHP不支持path/to路径,前后台无法方法
本来想把前后台分离,可是阅读了cakephp的说明,才发现.cakephp根本就不支持path/to路径. cakephp官网给出的 管理员分离方式:http://book.cakephp.org/2 ...
- 从CakePHP 1.3升级到2.5
从CakePHP 1.3升级到2.5 摘要:最近把一个CakePHP 1.3的项目升级到了2.x,当然就用最新的版本2.5.3了,结果基本满意.本文记录了升级的过程,包括使用的工具,遇到的问题和相应的 ...
- 2016/5/6 thinkphp ①框架 ② 框架项目部署 ③MVC模式 ④控制器访问及路由解析 ⑤开发和生产模式 ⑥控制器和对应方法创建 ⑦视图模板文件创建 ⑧url地址大小写设置 ⑨空操作空控制器 ⑩项目分组
真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分困难,代码风格不一样) 项目稳 ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库
在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...
随机推荐
- 【UVA10829】 L-Gap Substrings (后缀数组)
Description If a string is in the form UVU, where U is not empty, and V has exactly L characters, we ...
- 几个外国Delphi Blog网站
http://blog.blong.com/search?updated-max=2012-09-19T03:21:00-07:00&max-results=7&start=42&am ...
- 8.WCF简化的 AJAX(*)
开发步骤: 添加一个Web项目,在Web项目中新建“新建项”->"Web"->"启用了AJAX的WCF服务" 页面上拖放ScriptManager控 ...
- Node.js权威指南 (3) - Node.js基础知识
3.1 Node.js中的控制台 / 19 3.1.1 console.log方法 / 19 3.1.2 console.error方法 / 20 3.1.3 console.dir方法 / 21 3 ...
- (转载)mysql group by 用法解析(详细)
(转载)http://blog.tianya.cn/blogger/post_read.asp?BlogID=4221189&PostID=47881614 mysql distinct 去重 ...
- json串的使用
一:在C#中使用json字符串 从这里下载:http://www.newtonsoft.com/products/json/ 安装: 1.解压下载文件,得到Newtonsoft.Json.dll 2. ...
- IE的表头固定/表头不动(使用expression)
本文主要介绍在IE浏览器中,实现表头固定的一种方法.这种方法使用到了 IE 浏览器特有的 expression 方法. 表头固定DEMO1 主要代码: <style type="tex ...
- 邮件发送小demo
//send email public static bool SendEmail() { //实例化发件人地址 MailAddress from = new MailAddress("aa ...
- 在Ubuntu中设置中文输入法
在Ubuntu中设置中文输入法 */--> pre { background-color: #2f4f4f;line-height: 1.6; FONT: 10.5pt Consola,&quo ...
- 安卓系统运行Debian-7.0环境(Debian for android)
新手使用说明(下载地址在文章末尾): 〇.警告:root 有风险,折腾 Linux 更有风险,因使用 Debian for Armel 导致任何直接或间接的损失,本人不负任何责任:一.将 debian ...