forecho 的独立博客

把生命浪费在美好的事物上

Yii—accessRules用法

2012年12月12日

一、访问控制过滤器(Access Control Filter) 访问控制过滤器是检查当前用户是否能执行访问的controller action的初步授权模式。这种授权模式基于用户名,客户IP地址和访问类型。访问控制过滤器适用于简单的验证。需要复杂的访问控制,需要使用将要讲解到的基于角色访问控制(role-based access (RBAC)). 在控制器(controller)里重载CController::filters方法设置访问过滤器来控制访问动作(看 Filter 了解更多过滤器设置信息)。

class PostController extends CController
{
......
public function filters()
    {
        return array(
            'accessControl',
        );
    }
}

在上面,设置的access control过滤器将应用于PostController里每个动作。过滤器具体的授权规则通过重载控制器的CController::accessRules方法来指定。

class PostController extends CController
{
    ......
    public function accessRules()
    {
        return array(
            array('deny',
                'actions'=>array('create', 'edit'),
                'users'=>array('?'),
            ),
            array('allow',
                'actions'=>array('delete'),
                'roles'=>array('admin'),
            ),
            array('deny',
                'actions'=>array('delete'),
                'users'=>array('*'),
            ),
        );
    }
}

上面设定了三个规则,每个用个数组表示。数组的第一个元素不是'allow'就是'deny',其他的是名-值成对形式设置规则参数的。上面的规则这样理解:createedit动作不能被匿名执行;delete动作可以被admin角色的用户执行;delete动作不能被任何人执行。 访问规则是一个一个按照设定的顺序一个一个来执行判断的。和当前判断模式(例如:用户名、角色、客户端IP、地址)相匹配的第一条规则决定授权的结果。如果这个规则是allow,则动作可执行;如果是deny,不能执行;如果没有规则匹配,动作可以执行。 为了确保某类动作在没允许情况下不被执行,设置一个匹配所有人的deny规则在最后,类似如下:

return array(
 // ... 别的规则...
 // 以下匹配所有人规则拒绝'delete'动作
 array('deny',
 'action'=>'delete',
 ),
 );

因为如果没有设置规则匹配动作,动作缺省会被执行。 访问规则通过如下的上下文参数设置: actions: 设置哪个动作匹配此规则。 users: 设置哪个用户匹配此规则。此当前用户的name 被用来匹配. 三种设定字符在这里可以用:

  • *: 任何用户,包括匿名和验证通过的用户。
  • ?: 匿名用户。
  • @: 验证通过的用户。 roles: 设定哪个角色匹配此规则。这里用到了将在后面描述的role-based access control技术。In particular, the rule is applied if CWebUser::checkAccess returns true for one of the roles.提示,用户角色应该被设置成allow规则,因为角色代表能做某些事情。 ips: 设定哪个客户端IP匹配此规则。 verbs: 设定哪种请求类型(例如:GETPOST)匹配此规则。 二、访问规则中: expression: 设定一个PHP表达式。它的值用来表明这条规则是否适用。在表达式,你可以使用一个叫$user的变量,它代表的是Yii::app()->user。 expression的具体用法:

    class AdminController extends CController {

    …… public function accessRules() { return array( array(‘allow’, //允许所有人执行’login’,’error’,’index’ ‘actions’=>array(‘login’,’error’,’index’), ‘users’=>array(‘’), ), array(‘allow’, //允许超级管理员执行所有动作 ‘actions’=>array(‘create’,’update’,’delete’), ‘expression’=>array($this,’isSuperAdmin’), ), array(‘allow’,//允许普通管理员执行 ‘actions’=>array(‘update’), ‘expression’=>array($this,’isNormalAdmin’), //表示调用$this(即AdminController)中的isNormalAdmin方法。 ),
    array(‘deny’, // deny all users ‘users’=>array(‘
    ’), ), ); } protected function isSuperAdmin($user)//判断是否是超级管理员 { return ($this->loadModel($user->id)->adminAdminFlag==1); } protected function isNormalAdmin($user)//判断是否是普通管理员 { return ($this->loadModel($user->id)->adminAdminFlag==0); }

    public function loadModel($id)
    {
        $model=Admin::model()->findByPk((int)$id);
        if($model===null){
            throw new CHttpException(404,'页面不存在');     
        }
        return $model;
    } }
    

注:其中$user代表Yii::app()->user即登录用户。

一个很简单的jquery图片自动切换

2012年12月10日

效果页面~ html代码如下:

<div class="ad">
	<a href="" target="_blank"><img src="01.jpg"  /></a>
	<a href="" target="_blank"><img src="02.jpg"  /></a>
	<a href="" target="_blank"><img src="03.jpg"  /></a>
</div>

jquery代码如下:

<script>
	function swapImages(){
		var $active = $('.ad .active');
		var $next = ($('.ad .active').next().length > 0) ? $('.ad .active').next() : $('.ad a:first');
		$active.fadeOut(function(){
		$active.removeClass('active');
		$next.fadeIn().addClass('active');
		});
	}

    $(document).ready(function(){
		$('.ad a:first').addClass('active');
		  // Run our swapImages() function every 3secs
		  setInterval('swapImages()', 3000);
    });
</script>

CSS代码如下:

.ad a{
	display:none;
}
.ad .active{
    display:block;
}

Yii关于登录表单汉化操作

2012年12月06日

Yii自动生成的登录页面已经很完善了,非常好用,但是唯一不足的就是界面是英文版的,对于我们来说非常不友好,用户可能根本看不懂。 改为中文版的方法其实很简单,找到models/LoginForm.php模型文件,找到如下代码:

public function attributeLabels()
{
	return array(
		'rememberMe'=>'Remember me next time',
	);
}

改为如下代码:

public function attributeLabels()
{
	return array(
		'username'=>'用户名',
		'password'=>'密 码',
		'rememberMe'=>'记住并自动登录',
	);
}

OK,现在你去刷新你的登录页面,就会是中文的了,你不必去改动login.php页面的任何代码。

Yii怎样修改自动跳转到登录页面?

2012年12月05日

1、在配置文件main.php下的components里添加下面代码:

'user'=>array(
	// enable cookie-based authentication
	'allowAutoLogin'=>true,
),

2、在SiteController.php添加如下代码:

public function filters()
{
	return array(
		'accessControl', // perform access control for CRUD operations
	);
}
public function accessRules()
{
	return array(
		array('allow',  //未登录用户允许操作的action
				'actions'=>array('login','logout','register'),
				'users'=>array('*'),
		),
		array('allow',   //登录用户允许操作全部action
				'users'=>array('@')
		),
		array('deny',  // allow all users to perform 'index' and 'view' actions
				'users'=>array('*'),
		),
   );
}

更新一下更完善的方法: 2、在SiteController.php添加如下代码:

public function accessRules()
{
	return array(
		array('allow',  // allow all users to perform 'index' and 'view' actions
			'actions'=>array('login','error'),
			'users'=>array('*'),
		),
		array('allow', // allow admin user to perform 'admin' and 'delete' actions
			'actions'=>array('logout'),
			'users'=>array('@'),
		),
		array('deny',  // deny all users
			'users'=>array('*'),
		),
	);
}

3、在配置文件main.php下添加下面代码:

'defaultController'=>'options/welcome',//默认加载的控制器 页面

4、在OptionsController.php修改accessRules,修改后的代码如下:

public function accessRules()
{
	return array(
		array('allow', // allow admin user to perform 'admin' and 'delete' actions
			'actions'=>array('welcome'),
			'users'=>array('admin'),
		),
		array('deny',  // deny all users
			'users'=>array('*'),
		),
	);
}

Yii关于messages,多语言切换

2012年12月05日

1. 设置全局默认的语言 之前提到过在protected/config/main.php 文件内添加如下代码,默认语言为中文(有限的为中文)

'language' => 'zh_cn',

2.控制器根据用户选择动态切换语言

public function init()
{
    if(isset($_GET['lang']) && $_GET['lang'] != "")
    {
        Yii::app()->language = $_GET['lang'];
        Yii::app()->request->cookies['lang'] = new CHttpCookie('lang', $_GET['lang']);
    }
    else if(!empty(Yii::app()->request->cookies['lang']))
    {
        Yii::app()->language = Yii::app()->request->cookies['lang'];
    }
    else
    {
        $lang = explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']);
        Yii::app()->language = strtolower(str_replace('-', '_', $lang[0]));
    }
}

3. 页面提供切换语言选项 在公用的 layouts 头部,加入

<?php echo CHtml::link('中文', Yii::app()->createUrl('/', array('lang' => 'zh_cn')));?>
<?php echo CHtml::link('English', Yii::app()->createUrl('/', array('lang' => 'en_us')));?>

4. 多语言描述文字

//admin是对应的语言文件,路径:protected/messages/zh_cn/admin.php
Yii::t('admin', 'Management Center');

zh_cn/admin.php代码如下:

<?php
return array(
    'Management Center' => '管理中心',
);

Yii框架中使用bootstrap

2012年12月04日

把下载下来的bootstrap解压之后的整个文件夹,拷贝到项目中的protected\extensions文件夹里面,并且命名为bootstrap。 修改config目录下的main.php配置文件,修改完成之后的代码如下:

'preload'=>array('log','bootstrap'),


'gii'=>array(
	'class'=>'system.gii.GiiModule',
	'password'=>'password',
	// If removed, Gii defaults to localhost only. Edit carefully to taste.
	'ipFilters'=>array('127.0.0.1','::1'),
	'generatorPaths'=>array(
		'bootstrap.gii', // since 0.9.1
	),
),


// application components
'components'=>array(
	'user'=>array(
		// enable cookie-based authentication
		'allowAutoLogin'=>true,
	),
	// uncomment the following to enable URLs in path-format
	
	'bootstrap'=>array(
		 'class'=>'ext.bootstrap.components.Bootstrap', // assuming you extracted bootstrap under extensions
	 ),

使用方法参考如下:http://www.cniska.net/yii-bootstrap/

Mac输入法神器-鼠须管?

2012年11月30日

是不是神器我不知道,只有等我用过一阵子之后才能知道。 本篇文章就是讲讲我安装的过程以及一些最基本的配置,还有就是体验一下刚装上的这个神器。 官方的下载地址在这~,但是有时候会很慢,我共享的一个地址,目前最新的版本0.9.11,你可以在这下载~ 下载完之后,尼玛找半天没找到,为此还重启了一回电脑还是没发现,后来是网上搜了一些资料,这才发现位置,你可以参考下图: 我只想说隐藏的好深,不注意看很难找到。 安装好之后简单的配置一下: 一. 配置简繁体输入 鼠须管默认是繁体输入,需要切换到简体输入的话,请用快捷键 control+“~”  打开切换菜单,选“漢字→汉字” 即可。 二、配置显示方式 复制default.yaml和squirrel.yaml,并重命名为default.custom.yaml和squirrel.custom.yaml。 1、default.custom.yaml可以改输入的候选词个数。代码如下:

patch:
  "menu/page_size": 8

2、squirrel.custom.yaml可以改输入法配色方案和字号、横向展示等功能,具体请参考这个网址。代码如下:

patch:
  us_keyboard_layout: true      # 鍵盤選項:應用美式鍵盤佈局
  style/horizontal: true        # 候選窗横向顯示
  style/font_face: "Hiragino Sans GB W3"    # 我喜歡的字體名稱
  style/font_point: 18          # 字號
  style/corner_radius: 5       # 窗口圓角半徑
  style/border_height: 8        # 窗口邊界高度,大於圓角半徑才有效果
  style/border_width: 8         # 窗口邊界寬度,大於圓角半徑才有效果
  style/color_scheme: luna      # 選擇配色方案

iOS开发实例(五)- 自动旋转

2012年11月28日

自动旋转屏幕有3种常用方法: 一、自动调整属性(适用比较简单的界面)。        1、创建一个项目Autosize,系统是默认支持Portrait(纵版)、Landscape Left(向左横向)、Landscape Right(向右横向),不支持Upside Down(倒过来),如下图:** ** ** 2、打开.xib文件,在IB中拖出6个Round Rect Button,按下图摆放和命名: 这个时候Run一下程序,然后在菜单处找到硬件->向左旋转。然后得到如下图结果: 你会发现只有UL位置是对的,其他的都有问题。 3、选中按钮,在属性处找到大小检查器,如下图: 方块里面箭头(→):实线表示可在调整窗口大小时自由更改对象的宽度,虚线表示将对象尽可能的保持原始值。 方块周围的“I”形:表示选定对象的边与包含它的视图的同侧边之间的距离。虚线表示距离是可以灵活可变的,实线表示间距的指应尽可能的保持不变。 4、根据上面的规则修改,如下图: 然后我们在Run一下程序,然后依次点击硬件->向左旋转,如果得到如下图结果,那就证明你成功了。   **二、看到视图旋转提示时,手动调整视图中的对象位置。 1、选中6个按钮,同时把他们的高度和宽度设置成125点,然后效果图如下: 2、这个时候我们Run一下程序,然后旋转就会得到如下面的效果: 好混乱,感觉不会再看了。这样的问题要怎么样去解决呢? 3、手动调整视图位置:按住control键分别把6个按钮拖到.h文件的@end前,依次分别命名为:buttonULbuttonURbuttonLbuttonRbuttonLLbuttonLR。生成的代码如下:

@property (weak, nonatomic) IBOutlet UIButton *buttonUL;
@property (weak, nonatomic) IBOutlet UIButton *buttonUR;
@property (weak, nonatomic) IBOutlet UIButton *buttonL;
@property (weak, nonatomic) IBOutlet UIButton *buttonR;
@property (weak, nonatomic) IBOutlet UIButton *buttonLL;
@property (weak, nonatomic) IBOutlet UIButton *buttonLR;

4、在旋转时移动代码:在.m文件@end前写一个旋转开始之后的方法,最后的旋转动画发生之前自动调用。代码如下:

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration{
    if(UIInterfaceOrientationIsPortrait(interfaceOrientation)){
        buttonUL.frame = CGRectMake(20, 20, 125, 125);
        buttonUR.frame = CGRectMake(175, 20, 125, 125);
        buttonL.frame = CGRectMake(20, 168, 125, 125);
        buttonR.frame = CGRectMake(175, 168, 125, 125);
        buttonLL.frame = CGRectMake(20, 315, 125, 125);
        buttonLR.frame = CGRectMake(175, 315, 125, 125);
    }else{
        buttonUL.frame = CGRectMake(20, 20, 125, 125);
        buttonUR.frame = CGRectMake(20, 155, 125, 125);
        buttonL.frame = CGRectMake(177, 20, 125, 125);
        buttonR.frame = CGRectMake(177, 155, 125, 125);
        buttonLL.frame = CGRectMake(328, 20, 125, 125);
        buttonLR.frame = CGRectMake(328, 155, 125, 125);
    }
}

所有的视图的大小位置都在frame属性中指定,CGRectMake函数支持通过指定的x和y的位置以及widthheight来轻松创建CGRect。然后我们Run一下程序,得到如下效果: 其实这样做的有点复杂的。   三、在IB中为视图设计两个不同的版本,一个适用于纵版,一个适用于横板。 1、需要我们新建一个Swap项目。我们需要在nib文件中添加两个视图。默认的就是第一个视图,然后我们可以按住 option 键复制另一份视图,然后在属性检查器中的 Simulated Metrics 找到Orientation 菜单把 Portrait 改为 Landscape ,如下图所示: 2、创建两个视图:打开辅助编辑器,按住 Control 把视图拖到.h文件中,创建一名为 portrait 的输出口,Storage 为 Strong,如下图: 为横向视图重复以上操作,创建一名为 landscape 的输出口。 3、在IB库中拖出Round Rect Buttons,分别放入每个视图中,然后是大小检查器中将Width和Height属性改为125,然后移动位置,并且将标签改为FooBar。结果如下图所示: 4、创建和关联按钮的输出口:按住control 把横向视图中的Foo按钮拖到.h文件中,将Connection 弹出菜单的值从Outlet 改为Outlet Collection,并且命名为foos。从纵向视图中的Foo 按钮拖至已存在的foos 输出口,与之关联。 对Bar 按钮进行以上重复动作,命名为bars

CI使用PHP-ExcelReader类

2012年11月27日

关于PHP怎么使用PHP-ExcelReader,请参考这篇文章~,这个demo,你可以在这下载~。修改一下数据库资料就能使用。 下面转入正题,CI如何使用PHP-ExcelReader? 先把下载好的PHP-ExcelReader文件中的oleread.phpreader.php文件拷贝出来(reader.php文件可能需要把第 261行 “=&”  改为 “=” )放在phpexcelreader文件夹(这个文件夹可以放在项目更目录下),然后我们最好写一个函数文件命名为:my_excel_helper.php,放在application/helpers文件夹里面,代码如下:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

function excel()
{
	$CI = &get_instance();
	if(!isset($CI->excel))
	{
		require_once '/resources/phpexcelreader/reader.php';//此处是reader.php文件的相对路径,根据项目自行修改
		$CI->excel = new Spreadsheet_Excel_Reader();
		$CI->excel->setOutputEncoding('utf-8');
	}
	return $CI->excel;
}

ExcelController控制器代码如下:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Excel extends CI_Controller {

    function __construct() {
        parent::__construct();
		$this->load->library('session');
    }
	
	function excelList()
	{
		// 读取 excel 内容
		$this->load->helper('my_excel');
		$excel = excel();
		$excel->read('themes/default/demo.xls');
		$data['excel_datas'] = $excel->sheets[0]['cells'];
		//$data['excel_rows'] = $excel->sheets[0]['numRows'];//表的行数
		$data['excel_cols'] = $excel->sheets[0]['numCols'];//表的列数

		$data['title_for_layout'] = "Excel表格";
		// 加载视图输出
		$this->layout->view('admin/excelList', $data);
	}
	

}

View视图文件主要代码如下:

<h2>读取 excel 内容</h2>
<table cellpadding="0" cellspacing="0">
	<?php foreach($excel_datas as $row): ?>
    <tr>
		<?php for ($i = 1; $i <= $excel_cols; $i++):?>
    	<td width="80"><?php echo $row[$i]; ?></td>
		<?php endfor;?>
    </tr>
    <?php endforeach; ?>
</table>

然后就完成了,如果你能正确的浏览Excel内容,那么说明你成功了,注意本教程CI使用PHP-ExcelReader时没有涉及到数据库方面,需要自行扩充。

iOS开发实例(四)- 用户界面(下)

2012年11月20日

上上篇文章**我们讲了键盘的调用以及关闭,上篇文章我们讲了滑块控件,本篇文章主要讲开关、按钮和分段控件。** ** ** 一、添加分段控件:打开.xib文件在IB里找到Segmented Control分段控件,直接拖过来,然后调整大小,改First名为Switches,改Second名为Button,完成之后如下图:   二、添加开关控件: 1、在IB里直接找到Switch开关控件拖过来,然后按住键盘option键。拖动刚才的Switch,移动到另外一边生成另外一个开关。 2、链接开关的输出口和操作:按住control拖动左边的开关控件到.h文件的@end前,添加一个输出口,name输入leftSwitch,然后回车。然后右边的开关也是同样的操作,name名为rightSwitch,效果如下图: 3、关联两个开关:这个比较关键,关联之后,操作一个开关另一个开关也跟着动。先按住control键拖动左边的开关到.h文件的@end前,然后将Connection改为Action,将name输入switchChanged,然后回车。如下图: 比较关键的是下一步,你要按住control键拖动右边的开关控件,拖到已经创建的switchChanged上面。只有这样才能时两个开关关联起来,并且同时操作。如下图: 最后,按住control把分段控件拖到.h文件中,创建一个操作方法:将Connection改为Action,将name输入toggleControls。 4、实现功能还需要在.m的switchChanged操作方法添加代码,完成之后代码如下:

- (IBAction)switchChanged:(id)sender {
    UISwitch *whichSwitch = (UISwitch *)sender;
    BOOL setting = whichSwitch.isOn;//获得开关状态
    [leftSwitch setOn:setting animated:YES];//设置开关状态
    [rightSwitch setOn:setting animated:YES];//设置开关状态
}

这时候我们Run一下程序,当你操作一个开关时另一个开关也同时动,那就说明我们成功了。   三、添加按钮 1、在IB库里面找到Round Rect Button,直接拖到.xib文件的开关控件上面,并且调整大小,使之完全覆盖两个开关控件,并且添加名Do Something。 2、按住control键拖到按钮到.h文件的@end前,添加一个输出口,在name输入doSomethingButton,然后回车。再一次按住control键拖到按钮到.h文件的@end前,添加一个操作,将Connection改为Action,将name输入buttonPressed。如下图: 3、为了让程序启动时隐藏按钮,在按钮属性中找到View部分的Drawing,选中Hidden复选框。   四、实现分段控件的操作方法    在.m文件中找到toggleControls方法,添加操作,完成之后代码如下:

- (IBAction)toggleControls:(id)sender {
    //0 == switchs index 判断当前选择的分段控件是哪一部分
    if ([sender selectedSegmentIndex] == 0) {
        leftSwitch.hidden = NO;
        rightSwitch.hidden = NO;
        doSomethingButton.hidden = YES;
    }else{
        leftSwitch.hidden = YES;
        rightSwitch.hidden = YES;
        doSomethingButton.hidden = NO;
    }
}

这时候Run一下程序,如果能使用分段控件正确切换开关和按钮的话,那么你成功了。   五、实现操作表和警报(两者类似但是有区别,操作表需要用户做出选择,然后根据选择会得到不同的结果,而警报只是一个通知,可能只有一个按钮) 1、遵从操作表的委托方法:在.h文件中添加<UIActionSheetDelegate>,位置如下:

@interface BIDViewController : UIViewController <UIActionSheetDelegate>

2、显示操作表:在.m文件中找到buttonPressed方法。添加代码之后如下:

- (IBAction)buttonPressed:(id)sender {
    UIActionSheet *actionSheet = [[UIActionSheet alloc] //分配一个UIActionSheet对象并进行初始化
                                  initWithTitle:@"Are you sure?" //设置标题,将会显示在Action Sheet的顶部
                                  delegate:self //设置操作表的委托,该表被按下时收到通知。通过self传递。
                                  cancelButtonTitle:@"No Way" //设置取消按钮的标题,将会显示在Action Sheet的最下边
                                  destructiveButtonTitle:@"Yes,I'm Sure!" //设置第一个确定按钮的标题,“继续”按钮
                                  otherButtonTitles:nil];
                                  //otherButtonTitles: @"New Button 1", @"New Button 2", nil]; //可以设置任意多的确定按钮
    [actionSheet showInView:self.view]; //显示操作表
}

3、然后在下面添加这个方法,代码如下:

//actionSheet didDismissWithButtonIndex是UIActionSheetDelegate委托方法中的一个
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex{
    if (buttonIndex != [actionSheet cancelButtonIndex]) {//buttonIndex表示用户所轻触的按钮的编号,编号从上往下从0开始。actionSheet cancelButtonIndex表示取消按钮的编号。
        NSString *msg = nil;

        if (nameField.text.length > 0) 
            msg = [[NSString alloc] initWithFormat:
                   @"You can breathe easy, %@, everything went OK.",
                   nameField.text];
        else
            msg = @"You can breathe easy, everything went OK.";

        UIAlertView *alert = [[UIAlertView alloc]
                              initWithTitle:@"Something was done" //设置标题,将会显示在Alert的顶部
                              message:msg //设置提示消息内容
                              delegate:self //设置警告视图self委托
                              cancelButtonTitle:@"Phew" //设置取消按钮的标题
                              otherButtonTitles:nil];
                              //otherButtonTitles: @"New Button 1", @"New Button 2", nil]; //可以设置任意多的确定按钮
            [alert show];
    }
}

这时候Run一下我们的程序,点击分段控件,切换到Button,点击Do Something 按钮,会出现一个操作表,然后选择yes的时候除弹出一个警报。   六、美化我们的按钮。