forecho 的独立博客

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

Yii Ajax 表单验证

2013年07月30日

先在Views页面的表单开启这个功能:

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'signup-form',
    'enableAjaxValidation' => true,//开启Ajax验证
    'enableClientValidation'=>true,
    'clientOptions'=>array(
        'validateOnSubmit'=>true,
    ),
)); ?>

...

<?php $this->endWidget(); ?>

然后再对应的Controller的action中加入代码:

//注册
public function actionSignup()
{   
    $model = new LoginForm('signup');
    // 开启Ajax验证
    if(isset($_POST['ajax']) && $_POST['ajax']==='signup-form')
    {
        echo CActiveForm::validate($model);
        Yii::app()->end();
    }
    if (isset($_POST['LoginForm'])) {
        $model->attributes=$_POST['LoginForm'];
        if($model->validate()){
            if($model->signup()){ 
               $this->redirect(array('login'));
            }
        }
    }

    $this->render('signup', array('model'=>$model));
}

需要注意的是:表单的ID 名字 要跟控制器中的一样。(此处我的是signup-form ==============补充 2014年01月12日============= 如果想让 ajax 的字段唯一,只需要在 Model 文件的 Rules 方法里面加上下面这行就可以了:

array('name', 'unique'),

Yii Select下拉菜单

2013年07月30日

Yii给下拉菜单一个添加一条数据: 一、不需要默认值

<?php echo $form->dropdownlist(
                    $model,
                    'parent_id',
                    CHtml::listData(Cat::model()->findAll(), 'id', 'name'),
                    array('prompt'=>'根目录')
); ?>

‘prompt’可以换成’empty’ 结果是:

<select name="Cat[parent_id]" id="cat_parent_id">
    <option value="">根目录</option>
    <option value="1">手机</option>
    <option value="2">婚纱</option>
</select>

  二、如果自己的添加的一个Option需要给定Value的话,只能用‘empty’来实现,示例如下:

<?php echo $form->dropdownlist(
                    $model,
                    'parent_id',
                    CHtml::listData(Cat::model()->findAll(), 'id', 'name'),
                    array('empty'=>array('10'=>'根目录'))
); ?>

结果是:

<select name="Cat[parent_id]" id="cat_parent_id">
    <option value="10">根目录</option>
    <option value="1">手机</option>
    <option value="2">婚纱</option>
</select>

  参考资料: http://www.yiichina.com/api/CHtml#activeDropDownList-detail http://stackoverflow.com/questions/16057637/yii-dropdown-list-empty-value-as-default

PHP MySQL Yii更新数据库时 字段值自增

2013年07月30日

PHP MySQL的实现方法是:

update tablename set fieldname = fieldname*2 where ...

Yii基本上有三种实现方法: 一、用save()方法。

//登录一次加5点
$user=User::model()->findByPk(Yii::app()->user->id);
$user->reputation=$user->reputation+'5';
$user->save(); // 将更改保存到数据库

二、用saveCounters方法。(要实现自减,只需把数值改成负数即可)

$postRecord=User::model()->findByPk(Yii::app()->user->id);
$postRecord->saveCounters(array('reputation'=>5));

三、用updateCounters?这个还没有成功,报错貌似是编码问题,待解。   参考资料:http://www.yiiframework.com/wiki/282/using-counters-with-activerecord/

Yii 表添加字段后数据更新不成功

2013年07月28日

情况是这样的,我开始已经用Gii生成了Model文件了,后来又手动添加一个字段,这个字段是info,TEXT类型,不是必填项。 刚开始我是直接在已经生成的Model文件里的rules最后一行代码添加info的,添加之后的代码如下:

public function rules()
{
	// NOTE: you should only define rules for those attributes that
	// will receive user inputs.
	return array(
		array('email', 'required'),
		array('email', 'length', 'max'=>255),
		array('name', 'length', 'max'=>25),
		array('password', 'length', 'max'=>100),
		// The following rule is used by search().
		// Please remove those attributes that should not be searched.
		array('id, email, name, password, info', 'safe', 'on'=>'search'),
	);
}

后来调试了半天,数据就是添加不进去数据库,在Controller的actionUpade时打印数据$_POST[‘User’],能获取到更新后的数据,但是就是添加不了数据库。 最后Google和调试了几次,发现可能是我的info字段没有设置验证规则,虽然不是必填项。后来就试着添加了下面这行代码:

array('info','type','type'=>'string'),

感觉上面这行代码挺别扭的,但是最后结果是成功更新数据到数据库了,事实证明就是这个字段的验证有问题。 后来我又发现了这个rules的safe貌似只是针对search场景的,而我需要的更新数据。 于是代码改成下面这样的了:

public function rules()
{
	// NOTE: you should only define rules for those attributes that
	// will receive user inputs.
	return array(
		array('email', 'required'),
		array('email', 'length', 'max'=>255),
		array('name', 'length', 'max'=>25),
		array('password', 'length', 'max'=>100),
		array('info', 'safe'),
		// The following rule is used by search().
		// Please remove those attributes that should not be searched.
		array('id, email, name, password', 'safe', 'on'=>'search'),
	);
}

测试一下,果然成功了。 最后为了进一步确认一下,我去Gii又生成一个这个表的Model,只是预览一下代码,不生成。对比rules,果然就是改这里。早知道直接用这个方法了。 最后总结一下,yii的表每个字段在rules都要有个验证规则,如果没有验证规则,那就必须要写一个safe。

Ubuntu安装PHP Mongo扩展

2013年07月26日

如果你没有安装PHP的PECL,就先在终端执行下面命令:

sudo apt-get install php5-dev php5-cli php-pear

然后安装命令:

sudo pecl install mongo

找到你的php.ini配置文件,打开(下面是我系统的php.ini文件路径,你需要找到你的配置文件):

vim /etc/php5/fpm/php.ini

手动添加下面这行代码:

extension=mongo.so

重启一下PHP:

sudo service php5-fpm restart

然后查看你的info.php文件(查看PHP配置文件),如果你能搜索到“mongo”,那就说明你安装成功了。

解决Nginx无法识别PHP问题

2013年07月23日

这两天很蛋疼的在Linux下面配置LNMP环境。参考了比较多的资料,但是发现一个问题,就是安装好环境之后,Nginx无法识别PHP文件,HTML文件是没有问题的。

还要解决配置多个虚拟目录的问题。

后来就各种Google找资料,按照这篇文章的方法配置,还算比较成功。

这个可以成功的配置虚拟目录,但是还是无法识别PHP。

后来找到这篇文章,其中提到:Nginx 本身并没有PHP 解释器,所以,需要借助于 PHP 提供的 fastcgi,所以,需要运行 PHP 的 php-cgi 进程;

1
php-cgi -b 127.0.0.1:9000 # cmd 中运行 php-cgi,监听本地地址,9000端口;

我是比较头晕不知道自己是否安装了这个,但是发现自己Nginx配置目录下还是有fastcgi文件的。 我的9000端口法无监听?试了一下这个方法,无效。 其实这个地方监听是什么,你需要去看/etc/php5/fpm/pool.d/www.conf配置文件写的是什么,这个写成一致即可。 后来把:

1
2
3
4
5
6
7
8
9
10
11
12
13
location ~ \.php($|/) {
    set  $script     $uri;
    set  $path_info  "";
    if ($uri ~ "^(.+\.php)(/.+)") {
      set  $script     $1;
      set  $path_info  $2;
    }
    fastcgi_pass   127.0.0.1:9000;
    include        fastcgi_params;
    fastcgi_param  PATH_INFO                $path_info;
    fastcgi_param  SCRIPT_FILENAME          /usr/local/vhost/demo$script;
    fastcgi_param  SCRIPT_NAME              $script;
}

改成为:

1
2
3
4
5
6
7
location ~ \.php$ {
    root   /usr/local/vhost/demo;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

然后重启Nginx服务,访问你设置的server_name ,成功

补充一些参考文章:

用jQuery实现当前页面给菜单导航一个特定样式

2013年07月22日

以前一直困惑我的一个问题就是:怎么实现给当前页面导航菜单一个样式?

最最开始的时候用的是最笨的方法,就是每个导航页面都写得不一样。比方说index.html页面的时候,会在index导航的a标签一个.active样式,然后第二个Posts.html页面的时候会在Posts导航的a标签一个.active样式。这个虽然效果实现了,但是有个很大的缺点 - 导航不能调用一个,每个页面的导航写法不一样。

后来发现可以用PHP的GET变量来实现这个效果。这个效果比上一个好,可以调用同一个导航文件,但是现在想想,这个方法会让导航这个文件代码变得臃肿,每个a标签都要写个if语句判断语句。然后根据GET获得的变量来判断是否显示.active这个样式。

今天无意中看了下一个开源的后台模板。下载下来发现他这个是纯HTML也实现了这个功能,然后查看源代码,在charisma.js文件发现了下面这个关键的代码:

1
2
3
4
5
//highlight current / active link
$('ul.main-menu li a').each(function(){
	if($($(this))[0].href==String(window.location))
		$(this).parent().addClass('active');
});

然后根据这个,自己写了个Demo,果然实现了。这下省了不少代码,也解决了一个我一直以来比较困惑的问题,看来还是得多看看别人的代码,学习。

Demo下载


其实这样也有效果:

1
2
3
4
5
$('ul.nav li a').each(function(){
    if ($(this)[0].href == window.location.href) {
        $(this).parent().addClass('active');
    }
});

## Comments

风逐蓝天: Good. 学习了.

风逐蓝天: $($(this))[0].href 这个是什么意思? 为什么不能是 $(this)[0].href ?

ForEcho: 这个问题我也想过,但是没搞清楚,毕竟不是专业的前端。但是我试过$(this)[0].href,结果就是行不通。你可以试着alert($(this)[0].href) 查看结果。

gao: 优化后:

1
2
3
4
5
6
$(".nav li a").each(function(){
    $this = $(this);
    if($this[0].href==String(window.location)){
        $this.parent().addClass("current");
    }
});

ForEcho: Thx 这样写更美观了

PHP对象转成数组的函数

2013年07月16日

对象和数组的区别:

  • 数组表示有序数据的集合,而对象表示无序数据的集合。如果数据的顺序很重要,就用数组,否则就用对象。
  • 数组的数据没有”名称”(name),对象的数据有”名称”(name)。(例外:在Javascript语言中,关联数组就是对象,对象就是关联数组。)

    /** * 对象转数组 * @author 佚名 * @param object $obj * @return array */ function object_to_array($obj){ $_arr = is_object($obj) ? get_object_vars($obj) : $obj; foreach ($_arr as $key => $val){ $val = (is_array($val) || is_object($val)) ? $this->object_to_array($val) : $val; $arr[$key] = $val; } return $arr; }

[is_object ](http://www.php.net/manual/zh/function.is-object.php): 检测变量是否是一个对象。 [get_object_vars](http://php.net/manual/zh/function.get-object-vars.php) : 返回由对象属性组成的关联数组。 参考资料: http://www.ruanyifeng.com/blog/2009/05/data_types_and_json.html https://gist.github.com/suziewong/4316491

Vim编辑器使用(一)

2013年07月09日

默认是一般模式

按 i、I、o、O、a、A、r、R进入编辑模式

按:、/、?进入命令行模式

补充解释:

i, I 进入插入模式(Insert mode):
i为『从目前鼠标所在处插入』, I为『在目前所在行的第一个非空白字元处开始插入』。( 常用 )

a, A 进入插入模式(Insert mode):
a为『从目前鼠标所在的下一个字元处开始插入』, A为『从鼠标所在行的最后一个字元处开始插入』。( 常用 )

o, O 进入插入模式(Insert mode):
这是英文字母o的大小写。o为『在目前鼠标所在的下一行处插入新的一行』; O为在目前鼠所在处的上一行插入新的一行!( 常用 )

r, R 进入取代模式(Replace mode):
r只会取代鼠标所在的那一个字元一次;R会一直取代鼠标所在的文字,直到按下ESC为止;( 常用 )

Vim编辑器使用(二)——一般模式

2013年07月09日

一般模式:移动光标的方法(#表示常用)

  • h -> 光标向左移动一个字符#
  • j -> 光标向下移动一个字符#
  • k -> 光标向上移动一个字符#
  • l -> 光标向右移动一个字符#
  • n -> n表示数字,如果想进行多次移动的话还可以加上数字,例如10j。
  • [Ctrl]+[f] -> 屏幕向下移动一页,相当于[Page Down]按键#
  • [Ctrl]+[b] -> 屏幕向上移动一页,相当于[Page Up]按键#  
  • + -> 光标移动到非空格的下一行
  • - -> 光标移动到非空格的上一行
  • n -> n表示数字,光标向右移动到该行的n个字符
  • 0 -> 光标移动到这一行最前面的字符处#
  • $ -> 光标移动到这一行最后面的字符处#
  • H -> 光标移动到屏幕的最上方那一行
  • M -> 光标移动到屏幕的中央那一行
  • L -> 光标移动到屏幕的最下方那一行
  • G -> 光标移动到文件的最后一行#
  • nG -> n表示数字,移动到这个文件的n行#
  • gg -> 光标移动到文件的第一行#
  • n -> n表示数字,光标向下n行#

一般模式:搜索与替换(#表示常用)

  • /word -> 从光标位置开始,向下寻找一个名为 word的字符
  • ?word -> 从光标位置开始,向上寻找一个名为 word的字符
  • n -> n表示数字,表示重复前一个搜索动作
  • N -> N表示数字,表示反向重复前一个搜索动作
  • :%s/word1/word2/g -> 将文件中的word1字符串,并将该字符串替换成word2 #
  • :%s/word1/word2/gc -> 将文件中的word1字符串,并将该字符串替换成word2,在替换前会显示提示符给用户确认 #

一般模式:删除,复制与粘贴(#表示常用)

  • x、X -> 在一行中,x向后删除字符,X向前删除字符#
  • nx -> n表示数字,连续向后删除n个字符
  • dd -> 删除光标所在的一整行#
  • ndd -> n表示数字,从光标位置开始,删除向下的n行#
  • d1G -> 删除光标所在位置到第一行所有的数据#
  • dG -> 删除光标所在位置到最后一行所有的数据#
  • d$ -> 删除光标所在位置到改行的最后一个字符
  • d0 -> 删除光标所在位置到改行的最前一个字符
  • yy -> 复制光标所在的一整行#
  • nyy -> n表示数字,复制光标所在的向下n行#
  • y1G -> 复制光标所在位置到第一行所有的数据#
  • yG -> 复制光标所在位置到第一行所有的数据#
  • y0 -> 复制光标所在的那个字符到该行行首的所有数据
  • y$ -> 复制光标所在的那个字符到该行行尾的所有数据
  • p、P -> p将已复制的数据粘贴到光标下一行,P相反#
  • J -> 将光标所在的行与下一行结合在一起#
  • c -> 重复删除多个数据
  • u -> 复原前一个操作,撤销#
  • [Ctrl]+[r] -> 重复上一个操作,恢复#
  • . -> 重复前一个动作#