Gowhich

Durban's Blog

这里示范一个基础的Hello World程序。

1
2
3
4
5
6
7
8
9
10
#import<Foundation/Foundation.h>

int main(int argc, char *argv[]){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSLog(@"Hello World!");

[pool drain];
return 0;
}

以上是Xcode的旧版”Hello World”程序代码,在4.3.1 xcode的代码为:

1
2
3
4
5
6
7
8
#import <Foundation/Foundation.h>

int main(int argc, char *argv[]){
@autoreleasepool{
NSLog(@"Hello World!");
}
return 0;
}

对于喜欢操作sql语句的人来说和对于sql语句基础不是很好的,能够明白每个CRUD操作是什么意思很重要,简单的介绍个例子,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
class Post extends CActiveRecord
{
public $fixtures = [
'posts' => 'Post',
'tags' => 'Tag',
];

public function findPost()
{
//调用find时,我们使用$condition和$params指定查询条件。
//此处$condition可以是SQL语句中的WHERE字符串,$params则是一个参数数组,
//其中的值应绑定到$condation中的占位符。
$post = $this->posts('post1');
$fPost = Post::model()->find('id=:id', [':id' => $post->id]);
//SELECT * FROM `tbl_post` `t` WHERE `t`.`id`=1 LIMIT 1

$fPost = Post::model()->find('?', [$post->id]);
//SELECT * FROM `tbl_post` `t` WHERE '1' LIMIT 1

//find返回符合条件的第一条记录,而findAll会返回符合条件的所有行。
$fAllPost = Post::model()->findAll('id=:id', [':id' => $post->id]);
//SELECT * FROM `tbl_post` `t` WHERE id = '1'

$fAllPost = Post::model()->findAll('?', [$post->id]);
//SELECT * FROM `tbl_post` `t` WHERE '1'

$criteria = new CDbCriteria();
$criteria->condition = 'id=:id AND title=:title';
$criteria->params = [':id' => $post->id, ':title' => $post->title];
$fPost = Post::model()->find($criteria);
//SELECT * FROM `tbl_post` `t` WHERE id = '1' AND title = 'post1' LIMIT 1

$fAllPost = Post::model()->findAll($criteria);
//SELECT * FROM `tbl_post` `t` WHERE id = '1' AND title = 'post1'

$fPost = Post::model()->findByPk($post->id, 'title=:title', [':title' => $post->title]);
//SELECT * FROM `tbl_post` `t` WHERE `t`.`id`=1 AND (title = 'post1') LIMIT 1

$fPost = Post::model()->findByAttributes(['id' => $post->id, 'title' => $post->title]);
//SELECT * FROM `tbl_post` `t` WHERE `t`.`id`='1' AND `t`.`title`='post1' LIMIT 1

$sql = 'SELECT id, title from {{post}} WHERE id = ? AND title = ?'; //必须设置表前缀
$fPost = Post::model()->findBySql($sql, [$post->id, $post->title]);

$sql = 'SELECT id, title from {{post}} WHERE id = :id AND title = :title';
$fPost = Post::model()->findBySql($sql, [':id' => $post->id, ':title' => $post->title]);

//如果没有找到符合条件的行,find返回null,findAll返回array()。
}

public function countPost()
{
$post = $this->posts('post1');

$cPost = Post::model()->count('?', [$post->title]);
//SELECT COUNT(*) FROM `tbl_post` `t` WHERE 'post1' 无意义

$cPost = Post::model()->countByAttributes(['title' => $post->title, 'content' => $post->content]);
//SELECT COUNT(*) FROM `tbl_post` `t` WHERE `t`.`title`='post1' AND `t`.`content`='content1'

$sql = "SELECT title from {{post}} WHERE title LIKE '%" . $post->title . "%'";
$cPost = Post::model()->countBySql($sql);
//至少有一条记录符合查询条件
$ePost = Post::model()->exists('id=?ANDtitle=?', [$post->id, $post->title]);
//SELECT 1 FROM `tbl_post` `t` WHERE id = '1' AND title = 'post1' LIMIT 1
}

public function updatePost()
{
$post = $this->posts('post1');
$post->title = 'updatepost1';

if ($post->isNewRecord) {
$post->create_time = $post->update_time = new CDbExpression('NOW()');
//UPDATE `tbl_post` SET `id`=1, `title`='update post 1', `content`='content1', `tags`=NULL, `status`=1, `create_time`=NULL, `update_time`=1302161123, `author_id`=1 WHERE `tbl_post`.`id`=1
} else {
$post->update_time = time();
}

$post->save();

//updateAll
$sql = "SELECT * FROM {{post}} WHERE title LIKE '%" . "post" . "%'";
//SELECT * FROM tbl_post WHERE title LIKE '%post%'

$post = Post::model()->findBySql($sql);
$post->updateAll(['update_time' => time()], 'id<=?', ['2']);
//UPDATE `tbl_post` SET `update_time`=1302161123 WHERE id <= '2'

$post->updateByPk($post->id + 2, ['title' => 'updatepost3']);
$post->updateByPk($post->id, ['title' => 'updatepost3'], 'id=?', ['3']);

//updateCounter更新某个字段的数值,一般是计数器(+/-)。
$tag = $this->tags('tag1');
$uTag = Tag::model()->updateCounters(['frequency' => '3'], 'id=?', ['1']);
}

public function deletePost()
{
$post = $this->posts('post1');
$post->delete();

$this->assertEquals(1, $post->id); //删除数据库表中的记录,但是post的这个实例还在。
$post2 = Post::model()->findByPk($post->id);
$this->assertEquals(null, $post2);

//多条记录
$delete = Post::model()->deleteAll('(id = ? AND title = ?) || (id = \'4\') ', [1, 'post1']);
$this->assertEquals(0, $delete);

$delete = Post::model()->deleteAllByAttributes(['id' => '2'], 'content=?', ['content2']);
//DELETE FROM `tbl_post` WHERE `tbl_post`.`id`='2' AND (content = 'content2')
$this->assertEquals(1, $delete);
}
}

Yii在IIS下的伪静态处理是,在根目录建立httpd.ini文件,然后使用IIS的伪静态规则,写入自己需要的规则:

我购买的虚拟主机在香港,因为windows的主机比较多,于是我也中招了,于是四处寻求方法,四处尝试,终于找到了适合Yii的伪静态规则:

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
[ISAPI_Rewrite]
# 3600 = 1 hour
CacheClockRate 3600
RepeatLimit 32
RewriteEngine On
#伪静态规则
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ $1/index.php?$2
RewriteRule !\.(js|ico|gif|jpe?g|bmp|png|css)$ index.php [L]
我在虚拟机上测试通过了,哈哈,希望对你也有用

Gii 是基于 web 的 Yii framework 代码生成器。

开始配置

可以在你的应用程序配置文件中增加以下代码以使用该模块:

1
2
3
4
5
6
7
'modules' => [
'gii' => [
'class' => 'system.gii.GiiModule',
'username' => 'dev',
'password' => 'yiidev',
],
],

运行

打开浏览器,输入 http://localhost/yourapp/index.php?r=gii,使用刚才在配置文件中填的 username 和 password 登录。

yii自己是带有自动分页功能的。只要在对应的controller里面,类似下面这样鞋代码,就会实现的

1
2
3
4
5
6
7
$dataProvider = new CActiveDataProvider(
'Blog',
[
'pagination' => ['pageSize' => 10],
'criteria' => ['order' => 'create_date DESC'],
]
);

但是样式还是yii中已经写好的,那么对于我,我要改掉这个样式,使用我提供的样式,可以像我下面这样写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$this->widget('zii.widgets.CListView', [
'dataProvider' => $dataProvider,
'itemView' => '_view',
'summaryCssClass' => 'hide',
'pagerCssClass' => 'pagination',
'pager' => [
'class' => 'CLinkPager',
'nextPageLabel' => '&raquo;',
'prevPageLabel' => '&laquo;',
'firstPageLabel' => '最前',
'lastPageLabel' => '最后',
'htmlOptions' => ['class' => ''],
'header' => '',
'hiddenPageCssClass' => 'disabled',
'selectedPageCssClass' => 'active',
'previousPageCssClass' => '',
'nextPageCssClass' => '',
],
]);

其实只要添加自己对应的class属性就可以了,因为yii有自己默认的class属性,这个是比较简单。

下次我们可以看看,如何修改侧边下拉框,改为自己的喜欢的样式。

Yii的Active Recorder包装了很多。

特别是把SQL中 把where,order,limit,IN/not IN,like等常用短句都包含进CDbCriteria这个类中去,这样整个代码会比较规范,一目了然。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$criteria = newCDbCriteria;
$criteria->addCondition("id=1"); //查询条件,即where id =1
$criteria->addInCondition('id', [1, 2, 3, 4, 5]); //代表where id IN (1,23,,4,5,);
$criteria->addNotInCondition('id', [1, 2, 3, 4, 5]); //与上面正好相法,是NOT IN
$criteria->addCondition('id=1', 'OR'); //这是OR条件,多个条件的时候,该条件是OR而非AND
$criteria->addSearchCondition('name', '分类'); //搜索条件,其实代表了。。where name like ‘%分类%’
$criteria->addBetweenCondition('id', 1, 4); //between1 and 4

$criteria->compare('id', 1); //这个方法比较特殊,他会根据你的参数自动处理成addCondition或者addInCondition,
//即如果第二个参数是数组就会调用addInCondition

$criteria->addCondition("id = :id");
$criteria->params[':id'] = 1;

$criteria->select = 'id,parentid,name'; //代表了要查询的字段,默认select=’*';
$criteria->join = 'xxx'; //连接表
$criteria->with = 'xxx'; //调用relations
$criteria->limit = 10; //取1条数据,如果小于0,则不作处理
$criteria->offset = 1; //两条合并起来,则表示 limit 10 offset1,或者代表了。limit 1,10
$criteria->order = 'xxx DESC,XXX ASC'; //排序条件
$criteria->group = 'group 条件';
$criteria->having = 'having 条件 ';
$criteria->distinct = false; //是否唯一查询

生产环境中的 Web 应用常需要具有完善的事件日志功能。在我们的博客应用中,我们想记录它在使用时发生的错误。这些错误可能是程序错误或者是用户对系统的不当使用导致的错误。记录这些错误可以帮助我们完善此博客应用。

为启用错误日志功能,我们修改 应用配置 如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
return [
'preload' => ['log'],

// ......

'components' => [
'log' => [
'class' => 'CLogRouter',
'routes' => [
[
'class' => 'CFileLogRoute',
'levels' => 'error, warning',
],
[
'class' => 'CProfileLogRoute', //显示页面加载的整个流程,包括mysql语句
'levels' => 'profile',
],
[
'class' => 'CWebLogRoute',
'levels' => 'profile,trace',
],
],
],
//......
],
];

通过上述配置,如果有错误(error)或警告(warning)发生,其详细信息将被记录并保存到位于/wwwroot/blog/protected/runtime目录的文件中。

log组件还提供了更多的高级功能,例如将日志信息发送到一个 Email 列表,在 JavaScript 控制台窗口中显示日志信息等。更多详情,请参考指南

hexo在处理markdown文档的时候,默认将heading的内容作为了id来处理锚点,如果是英文是没有问题的。

1
## 我的标题

处理后的html内容

1
<h2 id="我的标题"><a href="#我的标题" class="headerlink" title="我的标题"></a><a href="#我的标题">我的标题</a></h2>

但是作为标题是中文的话就会有问题,以为在js的代码中,id是中文是不支持的,这会导致很多js库无法正常运行

找了很多资料,其中就有安装hexo-renderer-markdown-it

但是我自己亲自测试下来,还是很复杂,然后也没有解决我的问题,于是我思考这个hexo不会烂到这个程度吧

于是我看到了一种写法

1
## [我的标题](#custom-id)

处理后的html内容

1
<h2 id="custom-id"><a href="#custom-id" class="headerlink" title="我的标题"></a><a href="#custom-id">我的标题</a></h2>

哎,可以,就这么轻松的解决了,不需要什么卸载安装什么的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function filters()
{
return [
'accessControl', // perform access control for CRUD operations
];
}

function accessRules()
{
return [
[
'allow',
'action' => ['admin'],
'roles' => ['staff', 'devel'],
],
[
'deny', // deny all users
'users' => ['*'],
],
];
}

用户模型

在用户表中新增一列,列名 roles。建立相应的模型。在这里它将被命名为 “User”。

当添加用户可以给他们分配角色 “管理员”,“用户”,“员工”等等。

验证

在文件 protected/components/UserIdentity.php 添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class UserIdentity extends CUserIdentity
{
private $id;

public function authenticate()
{
$record = User::model()->findByAttributes(['email' => $this->username]);
if (null === $record) {
$this->errorCode = self::ERROR_USERNAME_INVALID;
} else if (md5($this->password) !== $record->password) {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
} else {
$this->id = $record->id;
$this->setState('roles', $record->roles);
$this->errorCode = self::ERROR_NONE;
}
return !$this->errorCode;
}

public function getId()
{
return $this->id;
}
}

重要的一行是

1
$this->setState('roles', $record->roles);

他给会话增加了用户角色。你可以使用如下代码获取用户角色。

1
Yii:app()->user->getState("roles")

1
Yii::app()->user->roles

检查权限:结构

在 protected/components 文件夹下修改并创建文件 WebUser.php ,然后重写 checkAccess() 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
class WebUser extends CWebUser
{
/**
* Overrides a Yii method that is used for roles in controllers (accessRules).
*
* @param string $operation Name of the operation required (here, a role).
* @param mixed $params (opt) Parameters for this operation, usually the object to access.
* @return bool Permission granted?
*/
public function checkAccess($operation, $params = [])
{
if (empty($this->id)) {
// Not identified => no rights
return false;
}
$role = $this->getState("roles");
if ('admin' === $role) {
return true; // admin role has access to everything
}
// allow access if the operation request is the current user's role
return ($operation === $role);
}
}

在 checkAccess() 方法中你可以定义自己的逻辑。
确保类可以被yii使用配置文件 “protected/config/main.php” 必须包含以下内容:

1
2
3
4
5
6
'components' => [
// ...
'user' => [
'class' => 'WebUser',
],
]

旁注:
[CWebUser::checkAccess()] 通常连接yii的验证系统。这里我们使用一个简单的处理角色的系统来替换[CAuthManager] 定义的分级系统。详细教程参加 Role-Based Access Control

检查权限: 使用

在你的 PHP 代码中使用 Yii::app()->user->checkAccess('admin') 来检查当前用户是否有 ‘admin’ 角色。

当用户拥有 “staff” 或 “admin” 角色时,调用 Yii::app()->user->checkAccess("staff") 将会返回 true。

在控制器中你可以使用 accessRules() 中的 “roles” 属性进行过滤。

见下面的例子。 怎样过滤动作 控制器必须包含以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function filters()
{
return [
'accessControl', // perform access control for CRUD operations
];
}

function accessRules()
{
return [
[
'allow',
'action' => ['admin'],
'roles' => ['staff', 'devel'],
],
[
'deny', // deny all users
'users' => ['*'],
],
];
}

这里对控制器中的 “admin” 动作进行了限制访问: 只有拥有 “staff” 或 “devel” 角色才可以访问。 像API文档中描述的那样 CAccessRule, “roles” 属性实际上调用的是 Yii::app()->user->checkAccess() 方法。 怎样根据角色显示不同菜单 你只需使用一个基于用户角色的菜单。例如

1
2
3
4
5
6
7
8
9
10
<?php
$user = Yii::app()->user; // just a convenience to shorten expressions
$this->widget('zii.widgets.CMenu', [
'items' => [
['label' => 'Users', 'url' => ['/manageUser/admin'], 'visible' => $user->checkAcces('staff')],
['label' => 'Your Ideas', 'url' => ['/userarea/ideaList'], 'visible' => $user->checkAcces('normal')],
['label' => 'Login', 'url' => ['/site/login'], 'visible' => $user->isGuest],
['label' => 'Logout (' . Yii::app()->user->name . ')', 'url' => ['/site/logout'], 'visible' => !$user->isGuest],
],
]);

更进一步: 访问上下文

一个通常的需求,用户只能够修改自己的数据。在这种情况下,用户的角色是没有任何意义的:将要修改的数据。 这就是为什么 [CWebUser::checkAccess()] 有一个可选的参数 “$param” 。现在假设我们要检查的是一个用户是否有权更新Post记录的权限。我们可以这样写:

1
2
3
if (Yii::app()->user->checkAccess('normal', $post)) {
// .....
}

当然 WebUser::checkAccess() 必须被扩展来使用 “$params” 参数。这将取决于你的应用程序的逻辑。比如, 这可能是非常简单的 $post->userId == $this->id

下面举个例子:

如果我想写个截取字符串长度的函数功能,可以在extensions目录下面新建一个文件,命名为Helper.php

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class Helper extends CController{
public static function truncate_utf8_string($string, $length, $etc = '...') {
$result = '';
$string = html_entity_decode(trim(strip_tags($string)), ENT_QUOTES, 'UTF-8');
$strlen = strlen($string);
for ($i = 0; (($i < $strlen) && ($length > 0)); $i++){
if ($number = strpos(str_pad(decbin(ord(substr($string, $i, 1))), 8, '0', STR_PAD_LEFT), '0')){
if ($length < 1.0){
break;
}
$result .= substr($string, $i, $number);
$length -= 1.0;
$i += $number - 1;
}else{
$result .= substr($string, $i, 1);
$length -= 0.5;
}
}
$result = htmlspecialchars($result, ENT_QUOTES, 'UTF-8');
if ($i < $strlen){
$result .= $etc;
}
return $result;
}
}

然后就可以在自己的代码中引用了Helper::truncate_utf8_string('XXXXXXXXXXX',10,'.......');

如果出现问题可以在config/main.php中加入在import引入要加载扩展的目录

类似:

1
2
3
4
5
6
'import'=> array(
'application.models.*',
'application.components.*',
'application.extensions.*', // 新加
'application.extensions.yii-mail.*',
),
0%