forecho 的独立博客

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

表单多radio jQuery 不为空验证

2014年01月24日

一、如果表单是 POST 或者 GET 提交的话,可以直接这样写 jQuery:

$("form").submit(function() {
    var submitme = true;
    $(':radio').each(function() { // loop through each radio button
        nam = $(this).attr('name'); // get the name of its set
        if (submitme && !$(':radio[name="'+nam+'"]:checked').length) {
        // see if any button in the set is checked
            alert(nam+' group not checked');
            submitme = false;
        }
    });
    return submitme; // cancel the form submit
});

二、如果表单用的 Ajax 提交的话,我们还需要修改一下:

  1. 把提交按钮 type 由 submit 改成 button 类型,然后加一个 id=”submit ”。

  2. jQuery 代码如下:

    $(“#button”).click(function(){ var submitme = true; $(‘:radio’).each(function() { nam = $(this).attr(‘name’); if (submitme && !$(‘:radio[name=”‘+nam+’”]:checked’).length) { alert(nam+’ group not checked’); submitme = false; } });

     if (submitme) {
         // 防止重复提交
         $(this).attr({
             disabled: 'disabled',
             value: '正在提交...'
         });
         $.post("/admin/saveUserData",$("#user-form").serialize(),function(data){
             #do something
             ....
         });
     };  })
    

参考文章:http://stackoverflow.com/questions/10706925/jquery-ensuring-all-radio-groups-are-checked

Yii 非主键关联

2014年01月24日

1
2
3
4
5
6
7
8
9
10
11
function relations()
    {
        return array(
            'last_experience' => array(
                self::HAS_ONE,
                'Experience',
                '',
                'on' => 'user_id=last_experience.user_id'
            ),
        );
    }

jQuery Ajax 点击修改

2014年01月23日

先来一张效果图: view HTML页面代码如下:

<td align="center" onclick="changeLike(<?php echo $id ?>,'<?php echo $like_count; ?>',this)">
    <?php echo $value['like']; ?>
</td>

JavaScript代码如下:

function changeLike (id, like, obj) {
    $(obj).html('<input type="num" name="" size="5" value="'+like+'">');
    $(obj).find('input').focus();
    // 键盘Enter键提交
    $(obj).find('input').keydown(function(event) {
        if(event.which==13){
            $(obj).find('input').blur();
        }
    });
    // 更新数据
    $(obj).find('input').blur(function(event) {
        $(obj).html(this.value);
        $.get('/admin/ajaxLike/'+id+'/'+this.value, function(data) {
            like = data;
        });
    });
}

至于控制器代码就很简单了,用获取到的参数,更新记录,返回新纪录。下面是我用CakePHP写的action,请结合自身情况写代码:

public function ajaxLike($id, $like)
{
    $this->layout = 'ajax';
    $this->Article->id = $id;
    $this->Article->saveField('like', $like);
    exit($like);
}

CakePHP Ajax分页

2014年01月23日

Controller文件头部调用CakePHP自带分页并且配置分页条数代码:

public $components = array('RequestHandler', 'Paginator');
public $paginate = array('limit' => 2 );  //2是为了方便测试

调用的action方法如下:

public function list()
{
    $this->Paginator->settings = $this->paginate;
    $data = $this->Paginator->paginate('Notice');
    $this->set('data', $data);
}

list.ctp文件,代码如下:

<?php echo $this->Js->writeBuffer(array('inline'=>false));?>
<div id="search_result">
    <?php foreach ($data as $key => $value): ?>
        <?php echo $value['Notice']['title'] ?>
    <?php endforeach ?>
    <?php $this->Paginator->options(array(
                'update' => '#search_result',
                'evalScripts' => true,
    ));?>
    <?php echo $this->Paginator->prev('上一页' . __('', true), array(), null, array('class'=>'disabled'));?>
    <?php echo $this->Paginator->numbers(array('class' => 'numbers', 'first' => false, 'last' => false));?>
    <?php echo $this->Paginator->next(__('下一页', true) . ' >>', array(), null, array('class' => 'disabled'));?>
    <?php echo $this->Js->writeBuffer(array('inline'=>true));?>
</div>

参考文章: http://endoyuta.com/2013/05/06/cakephp-2-3-ajax%E3%81%AApagination/ http://caky.de/en/core-libraries/helpers/js.html#ajax-pagination

Yii扩展自带的时间选择器插件CJuiDatePicker

2014年01月13日

事情大概是这样的:我数据库时间字段用的是 int 类型,存储的是时间戳。并且我写文章的时候,时间是需要可以修改的。

来一张最终效果图:

首先我用了 Yii 自带的 Zii CJuiDatePicker 扩展,非常的强大的把 jQuery UI 的 Datepicker 继承进去了,使用非常的简单,手册上有。但是这个有个缺陷,没有小时分钟,只能配置日期。这个有点坑爹了。然后没办法,去找了一个 yii 的扩展。我选了 ejuidatetimepicker,使用也很简单,基本就按照给的 Demo复制过去就可以了。

现在来说说这个功能的难点,首先我数据库是 int 时间戳格式的,但是我用的这个插件是日期格式的,那么现在我又不想改数据库时间的字段类型,我要如何解决? Google 了一下,找到了一篇文章,我按照这个来结果成功了。

首先根据插件的 Demo 我们在视图form的时间是这样写的:

<?php echo $form->labelEx($model,'create_time'); ?>
    <?php $this->widget('application.extensions.timepicker.EJuiDateTimePicker',array(
        'model'=>$model,
        'attribute'=>'create_time',
        'language'=>'zh-CN',
        'options'=>array(
            'hourGrid' => 4,
            'hourMin' => 9,
            'hourMax' => 17,
            'timeFormat' => 'hh:mm',
            'changeMonth' => true,
            'changeYear' => false,
            ),
        'htmlOptions'=>array(
            'readonly'=>true,
            'style'=>'width:180px;'
        ),
    )); ?>
<?php echo $form->error($model,'create_time'); ?>

控制器部分我们基本上不用修改。接下来我们去修改 Model 文件,添加两个 yii 的 function:

protected function beforeSave()
{
    $this->admin_id = Yii::app()->user->id;
    // $this->create_time = date('Y-m-d', CDateTimeParser::parse($this->create_time, 'yyyy-MM-dd hh:mm'));
    $this->create_time = strtotime($this->create_time);
    return parent::beforeSave();
}

protected function afterFind()
{
    $this->create_time = Yii::app()->dateFormatter->format('yyyy-MM-dd hh:mm', $this->create_time);
    return parent::afterFind();
}

beforeSave 就是数据保存之前我们要处理的事件。afterFind 就是数据显示之前我们要处理的事件。 非常巧妙的用法。

最后别忘记了把 Model 的 rules 的时间验证规则改一下,代码如下:

array('create_time', 'date', 'format'=>'yyyy-MM-dd hh:mm', 'message'=>'{attribute} have wrong format'),

**值得注意的是 rules 验证会在 beforeSave 之前执行。beforeSave 和 afterFind 都是 protected 属性。

** 参考文章:** - http://www.yiiframework.com/extension/ejuidatetimepicker/ - http://www.yiiframework.com/doc/api/1.1/CJuiDatePicker - http://www.volkomenjuist.nl/blog/2013/02/24/yii-cjuidatepicker-dateformat/   

最后感叹下自带 zii 的方便强大,再分享一个资源: http://www.bsourcecode.com/yii-framework/yii-extensions/

Comments

Jack Van: 怎么只能从9点到16点

ForEcho: 代码上面有参数。自己可以设置,hourMin 和 hourMax

CakePHP的小技巧用法

2014年01月03日

1、问:如果控制器有一个方法,不要视图怎么办?

答:使用:$this->autoRender = false

2、对于一直在开发的网站,在频繁更新的情况下,如何保证css文件、js文件和image文件不调用浏览器缓存文件问题?

答:一个是在调用的文件名最后加变量后缀,如时间。示例代码如下:

<link rel="stylesheet" type="text/css" href="http://forecho.com/css/index.css?2014-01-03-1" media="all" />

二如果是CakePHP的话还可以修改core.php配置文件,代码如下:

/**
 * Apply timestamps with the last modified time to static assets (js, css, images).
 * Will append a querystring parameter containing the time the file was modified. This is
 * useful for invalidating browser caches.
 *
 * Set to `true` to apply timestamps when debug > 0. Set to 'force' to always enable
 * timestamping regardless of debug value.
 */
    Configure::write('Asset.timestamp', true);

这样的好处是你接下来可以直接用CakePHP自带的写法调用图片和文件了,如:

<?php
	echo $this->Html->css('main');
	echo $this->Html->image();
?>

3、点赞的时候需要+1,如何更新数据库?

代码如下:

$this->Widget->updateAll(
    array('Widget.numberfield' => 'Widget.numberfield + 1'),
    array('Widget.id' => 1)
);

4、如何通过主键最简单的方式获取到一条数据?

代码如下:

// 只获取name字段信息
$this->User->read("name", $id);
// 获取所有信息
$this->User->read(null, $id);

5、CakePHP控制器如何返回上一页?

$this->redirect($this->referer());

6、CakePHP A控制器调用B控制器

$this->requestAction(
    array('controller'=>'Wx','action'=>'aa'),
    array('data'=>
        array('xing'=>'A1','ming'=>'A2')
    )
);

这样可以在A控制器调用B控制器方法,而且在后面传参过去,用$this->request->data获取参数值。

7、输出单个页面执行的SQL语句

$log = $this->Model->getDataSource()->getLog(false, false);
debug($log);

Model要改一下名字才能用。

庆「元旦」读完《淘宝技术这十年》

2014年01月01日

元旦放假一天,天气不错无处可玩,想着去广场晒着太阳应该是件很不错的事情。于是吃完午饭抱着同事借来的《淘宝技术这十年》去广场找了个位置看书,在家对着电脑不管多安静,我是看不进去书的。 其实以前在博客园的这里已经看得差不多一半了,其实书的内容不怎么多的,除了讲技术的部分不明觉厉之外,其他的章节还是很有意思的。下面就摘抄一些有意义的笔记。内容主要为后面一章节,本书的前一半内容看的比较早了,当时忘记记录笔记了。

子柳:你对刚入行的技术人员有什么建议?
正明:找到自己感兴趣的,花时间投进去,通过实践后的知 识积累比只看书本有用得多。我看过一本操作系统方面的英文书,其中引用了一段中国人的格言:“I hear and I forget. I see and I remember. I do and I understand”,这句话给我留下非常深刻的 印象。是荀子说的“不闻不若闻之,闻之不若见之,见之不若知 之,知之不若行之。”

子柳:从你的经历来看,你对现在的技术人员的成长有什么建议?
正祥:很多人会说年轻人比较浮躁,其实我的身边有很多非常优秀的年轻人,他们聪明、刻苦、有闯劲、愿意接受新事物。 年轻的同事想赚钱,想提升自己的职称,这些都是十分正常的。 在这点上,我特别喜欢马总的理念——做公司要赚钱,但阿里从 不把赚钱作为第一目标,我们服务好了客户,客户赚了钱,我 们一定会得到自己应得的一份。在个人成长问题上也是类似的 道理,这就是,一个人如果把做事、做成事作为主要目标,该他 得到的东西,一定会顺理成章的、水到渠成地得到,但是,如果 把上升作为主要目标,做同样的事,结果就会完全不一样。一句 话,你的心态会最终决定你的成就。

子柳:你来淘宝技术大学授课的时候,给学员说过“但行好 事,不问前程”,现在很多同学都因为晋升的问题很纠结,可否 解释一下自己是怎么看待晋升的?
毕玄:大家都说了,晋升是一个“水到渠成”的事情。大家 都会在意晋升,这个是正常的,除非你不在意级别,生活上也没 有压力,不过这样的人是很少的,呵呵。如果真的没有升上去, 这个也没有什么办法能够挽救了。我觉得重要的是在这个过程中 你回顾了你一年做了什么事情,对公司有什么贡献,技术上有哪些成长。 对于技术人员最常见的一种情况是晋升名单公布的时候,你 去看谁升上去了,然后对比一下自己,觉得他水平不如自己,为 什么是他得到了晋升,而不是你。我觉得最重要的是看那个人对 公司做了多少贡献,你可以说你的技术确实很强,但事实是你对 公司没有做出任何贡献。

子柳:你是技术晋升的评委,在评审的过程中,你比较看重什么样的特质?
毕玄:如果你是向技术方向发展的人员,我们要看技术方面的专业性;然后看你的技术对公司的业务发展有多少贡献。还有 一点,我比较看重的是,也许你不在其位,但能够跳出自己的范 围,想到公司未来到底会面临什么问题,用什么方法来解决。当 然,仅想是不够的,如果你能够落实就最好了,我们不管你落实 的技术含量有多高,关键是你解决了什么样的问题。如果你能够 做到这些,你这个人对公司就非常重要。

子柳:你经常出去招聘学生,你欣赏什么样的学生?
毕玄:其实在校招聘的时候,我比较欣赏的学生往往是那些很“不务正业”类型的。我经常会问他们,你有没有利用业余时间出于自己的技术兴趣做的一些小东西。这样的学生我们通常 会比较感兴趣,我认为这样的学生是真正喜欢技术。聪明程度一般就可以的,他能够进入这些不错的学校,智商是不会有什么问 题的。

子柳:你对新人的要求是什么样的?
放翁:第一个是做事要自己思考后再去问别人,而不是一遇到问题就找人求助。第二个是不断地打破自己的一些想法,你不要担心自己今天已经做了50%的工作,要是推倒重来,前面的事情都白干了。我现在带的两个新人成长很快,但是都有类似的经历,就是一个东西被我反复推翻重做,在这个过程中就是不断地成长,要思考我为什么让你推倒重做,若想不清楚,下次重做的概率会更大,这样慢慢地就会学会了思考。

子柳:你对工程师有什么忠告?
放翁:任何一个公司,不管用什么手段,都做不到绝对公 平,最终只会有小部分人得到机会。这个时候去抱怨、愤怒都没 有用的,只有自己不断地努力争取机会才行。

子柳:给技术刚起步的人员一些技术成长的建议吧。
云铮:兴趣是最好的老师,坚持是达到梦想的唯一途径,当然,在个人发展的不同阶段寻找到合适的导师很重要,看准方向 会事半功倍。在刚刚参加工作还没有形成自己的判断时,方向有 两个来源,一个是个人的兴趣,一个是找一个你非常佩服且能掌 握未来方向的人,当然,如果这两者正好重合,那么剩下的就是 脚踏实地坚持。

子柳:说说你个人的成长经验,给起步阶段的同事一些建议吧。
小马:现在回过头来看,其实成长最快的一段时间是刚进淘 宝的那几年,那个时候很单纯,就想着把工作做好,做完一个做 下一个,不管这个业务是不是重要,需求方是不是好打交道。有个“一万个小时理论”,我觉得很正确,说的就是一个人必须经 过不断地练习,不断地遇到问题才能成长起来。当然,做的时候 要不断总结,写博客是一个很好的途径。

子柳:现在有很多人出去创业,作为一个曾经创过业的技术 人员,你有什么看法?
小马:很多人创业是因为公司变得越来越大,有很多流程和 规章制度的限制,这样自己发挥的空间越来越小。但是真的到 社会中创业时会发现限制同样很多,你同样要面临税务局、工商 局、商标、公司注册、股东关系、员工管理、同行竞争等问题, 这跟你在公司中工作并没有本质的不同。所以说创业其实是一种 心态,你用旺盛的精力、饱满的斗志和坚定的信念去克服一个又 一个的困难,这就是创业。到外面去创业和在一个大公司里创 业,我个人觉得并没有本质的区别。 当然,如果你不认可公司整体的方向,或者你不认可这个行 业,你有一个理想去打造一个新的天地,公司也应该有这种胸怀 鼓励你去创业。

总结一下去年真正看完的书只有可怜的《Getting Real – 37signals》、《不许联想》、《打造 Facebook》、《把时间当作朋友》4本。太少了,争取今年能至少读完10本书。

CakePHP saveAll用法

2013年12月26日

视图表单代码如下:

<tr id="research-items">
	<td>
		<select name="type[]">
			<option value="text">单行文字</option>
			<option value="textarea">多行文字</option>
			<option value="radio">单项选择</option>
			<option value="checkbox">多项选择</option>
		</select>
	</td>
	<td><input type="text" name="question[]" value="" placeholder="这里是问题"></td>
	<td><input type="text" name="items[]" value="" placeholder="答案1|答案2"></td>
	<td>
		<input type="checkbox" name="is_answer[]" value="1" <?php echo (isset($data) && $data['ResearchSetting']['is_answer']==1) ? "checked" : '' ; ?>>是否必填
	</td>
	<td><a class="btn_delete" title="删除" href="javascript:;">删除</a></td>
</tr>

控制器的写法如下:

for ($i=0; $i < count($_POST['type']) ; $i++) {
     $post[$i]['ResearchOption']['type']                = $_POST['type'][$i];
     $post[$i]['ResearchOption']['question']            = $_POST['question'][$i];
     $post[$i]['ResearchOption']['items']               = $_POST['items'][$i];
     $post[$i]['ResearchOption']['is_answer']           = ($_POST['is_answer'][$i])?$_POST['is_answer'][$i]:0;
     $post[$i]['ResearchOption']['research_setting_id'] = $this->ResearchSetting->id;
}
$this->ResearchOption->saveAll($post);

参考链接:http://book.cakephp.org/2.0/en/models/saving-your-data.html

CakePHP hanMany用法

2013年12月18日

hanMany就是一对多的关系,比方说我们现在一篇文章有多条评论,那么这个就是一对多的关系。 我们在文章的模型里面写hasMany就可以关联评论了。使用方法如下:

var $hasMany = array('ProductsSku' =>
		array('className'     => 'ProductsSku',//关联对象类名
				'conditions'    => '',//关联对象限定条件
				'order'         => '',//关联对象排序子句
				'limit'         => '',//检索的关联对象数量
				'foreignKey'    => 'prod_id',//外键字段名
				'dependent'     => true,//是否级联删除
				'exclusive'     => false,//:如果设为true,所有的关联对象将在一句sql中删除,model的beforeDelete回调函数不会被执行。但是如果没有复杂的逻辑在级联删除中,这样的设定会带来性能上的优势。(译注:Cake的确方便,但是使用时一定要记住控制sql语句发送数量)
				'finderQuery'   => ''//定义一句完整的sql语句来检索关联对象,能够对关联规则进行最大程度上的控制。当关联关系特别复杂的时候,比如one table - many model one model - many table的情况下,Cake无法准确的替你完成映射动作,需要你自己来完成这个艰巨的任务。
		)
);

在CakePHP命名规范里面规定每一张表都有ID为主键的字段,作为外键foreignKey的字段命名:其默认值为当前模型的单数模型名缀以 ‘_id’。如果你遵守这个使用起来将非常简单。 下面我们来说个实例。 文章的表名为Articles,文章评论表名为Comments。那么文章的模型文件为Article.php,文章评论的模型文件为Comment.php。(单复数命名规则) 那么在Article.php文件中这样写就可以实现简单的关联评论表了。

class Article extends AppModel
{
    public $name = 'Article';

    public $hasMany = array(
        'Comment' => array(
            'className'  => 'Comment',
        )
    );
}

参考资料: http://www.cnblogs.com/matchless/archive/2013/02/01/2889134.html http://www.21haolou.com/articles/show/88