[CakePHP] Bakeコマンドの詳しい説明

CakePHP bakeによる高速開発
Bakeの流れを非常に詳しく解説しています。

基礎から学ぶ facebookアプリ開発


「基礎から学ぶ facebookアプリ開発」という本を買ってみた。
Facebookアプリに関する本は何冊か読んだが、どれも情報が古くて困った。
(というかFacebookは頻繁に仕様変更するようですね)

今回この本を選んだ理由は次の3つ。
・情報が新しい(開発ページの設定項目等が最新のレイアウトだった)
・php-SDKを使ったAPIの利用方法が書いてある。
・CakePHPとの連携例が多く載っていた。

FacebookAPIに関してほとんど知識がなくても、
自分のウォールに自動投稿するとか結構簡単にできた。

最初は他の本やサイトを参考にしてFacebookページを作成していたが、
掲載されている設定画面がどれも古くてかなり迷った。
この本なら最新の設定画面なので、全く困る事はなかった。(2011/11現在)


[javascript] エンターキー押下時にフォーム誤送信を防止するスクリプト

下記スクリプトで、エンターキーによるフォーム送信を無効にできる。

たまに使うこともあると思うので一応メモ。

layoutに追記※cakephpの場合

<?php echo $javascript->link('enter_block');?>

enter_block.js

	function BlockEnterEvent() {
		for(i = 0;i < 3;i++){
			if (document.forms[i] != null) {
				var elements = document.forms[i].elements;
				for (var j=0; j < elements.length; j++) {
					var e = elements[j];
					if (e.type == "text" || e.type == "file"){
						e.onkeypress=BlockEnter;
					}
				}
			}
		}
	}
	function BlockEnter(evt){
		evt = (evt) ? evt : event;
		var charCode=(evt.charCode) ? evt.charCode :
			((evt.which) ? evt.which : evt.keyCode);
		if ( Number(charCode) == 13 || Number(charCode) == 3) {
			return false;
		} else {
			return true;
		}
	}
	BlockEnterEvent();

手動によるカウンターキャッシュの更新

counterCacheは便利だが、どうやら1モデルにつき1つしか登録できないようだ。

たとえばUserモデルとFriendモデルがあるとする。
Userモデルにはfriend_countフィールドがあり、Friendの数がカウンターキャッシュで更新できるようにする場合、Friendモデルには下記のような記述をする

    var $belongsTo = array(
        'User' => array(
            'className'    => 'User',
            'foreignKey'   => 'user_id',
            'conditions'   => '',
            'fields'       => '',
            'order'        => '',
            'counterCache' => 'friend_count',
            'counterScope' => array('Friend.status' => 1),
        ),
    );

単純に友達の数をカウントするだけならこれでいいが、さらに「特に親しい友達の数もカウントしたい」というような要望がある場合は別処理でカウントする必要がある(と思う)。

試しに次のように配列で入れてみたが、結果は上手くうごかなかった。
(Friendモデルにis_favoriteというフィールドを設け、このis_favoriteが1の要素の合計数を、Userモデルのfriend_favorite_countというフィールドに入れたいとする)

    var $belongsTo = array(
        'User' => array(
            array(
                'className'    => 'User',
                'foreignKey'   => 'user_id',
                'conditions'   => '',
                'fields'       => '',
                'order'        => '',
                'counterCache' => 'friend_count',
                'counterScope' => array('Friend.status' => 1),
            ),
            array(
                'className'    => 'User',
                'foreignKey'   => 'user_id',
                'conditions'   => '',
                'fields'       => '',
                'order'        => '',
                'counterCache' => 'friend_favorite_count',
                'counterScope' => array('Friend.status' => 1, 'Friend.is_favorite' => 1),
            ),
        ),
    );

で、結局friend_favorite_countの方は、別に処理を書いて更新させることにする。

Friend.php

    var $actsAs = array('CounterCache');
    var $_del_user_id;

    function afterSave ($created) {
        // 新規登録時
        if ($created) {
            $this->id = $this->getLastInsertId();
        }
        $user_id = $this->Field('user_id');
        $this->_updateFavoriteCount($user_id);
    }

    function beforeDelete () {
        $this->_del_user_id = $this->Field('user_id');
        return true;
    }

    function afterDelete () {
        if ($this->_del_user_id) {
            $this->_updateFavoriteCount($this->_del_user_id);
            return true;
        }
    }

    function _updateFavoriteCount($user_id = null) {
        if (is_null($user_id)) return false;
        $count = $this->find('count', array('conditions' => array('Friend.user_id' => $user_id, 'Friend.favorite' => 1, 'Friend.status' => 1)));
        App::import('Model', 'User');
        $User= new User();
        $User->id = $user_id;
        if ($User->saveField('friend_favorite_count', $count)) {
            return true;
        }
        return false;
    }

[jQuery] スムーズスクロール

$(document).ready(function(){
    $('a[href*=#]').click(function() {
        if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
            var $target = $(this.hash);
            $target = $target.length && $target || $('[name=' + this.hash.slice(1) +']');
            if ($target.length) {
                var targetOffset = $target.offset().top;
                $('html,body').animate({scrollTop: targetOffset}, 1000);
                return false;
            }
        }
    });
});

1ヶ月後の日時を取得する

	/**
	 *
	 * 1ヶ月後の日時を取得する
	 * @param integer $month
	 * @param date $start_date
	 * @return timestamp
	 */
	function endOfMonthPeriod($month, $start_date) {
		$ts1 = strtotime(sprintf('%dmonth -1day', $month), $start_date);
		$ts2 = mktime(0, 0, 0, date("m", $start_date) + (int)$month + 1, 0, date("y", $start_date));
		return min($ts1, $ts2);
	}

A5:SQL mk2の文字化けについて

データベースのER図を作成するのにA5:SQL mk-2というツールを利用している。

新しいPC環境でA5:SQLをダンロードして開き、データベースに接続して、テーブルを開いてみるとなぜか日本語部分のデータが全部「?」になっている。
完全に文字化けしているので調べたら下記サイトが見つかった。

http://d.hatena.ne.jp/THE_MIND/20080517

ばっちり治りました。感謝。

[CakePHP][jQuery] jQueryでフォームをリセットする

jQueryを使ってフォーム要素をリセットしてみた。

<?php $this->Html->scriptStart();?>
$(function(){
	// 検索フォームの入力値をリセット
    $("button.reset").click(function(){
        $('input[type="text"], input[type="radio"], input[type="checkbox"], select').
        val("").
        removeAttr('checked').
        removeAttr('selected')
    })
})
<?php echo $html->scriptEnd();?>

//form
echo $form->create();
echo $form->text('name');
echo $form->text('tel');
echo $form->button('reset', array('class' => 'reset'));
echo $form->end();
?>

※jQueryへのパスは適宜変更すること。

[CSS] Youtube動画のz-indexが効かない場合の対処法

それはjQueryプラグインのthickboxを利用して、lightboxのような表示方法でテキストウィンドウを表示させた時に問題が起きた。

lightbox特有の半透明の黒い背景の上にYoutube動画がクッキリ表示されているではないか。

cssのz-indexプロパティを利用して、レイヤの順番を下げようとしたがちっとも効果がない。

まるで目立ちたがり屋さんのように、何をやっても最前面に出てくるのだ。

で、参考にしたのがこちらのサイト。

http://blogs.yahoo.co.jp/alaya_wave/62726905.html

どうやらwmode=transparentという文字列を加えてあげないとだめみたいだ。

[PHP] 日付の扱い方

PHPで日付を扱う場合にDateTimeクラスってのがあったのね・・・。
便利すぎる。

<?php
$dt = new DateTime("2100/2/28");
//echo $dt->format("Y-m-d");

$tomorrow = new DateTime("tomorrow");
//echo $tomorrow->format('明日はY年n月j日です。');

$start_datetime = new DateTime("2100/1/31");
$end_datetime = clone $start_datetime;
$end_datetime->modify('+1month');
echo $start_datetime->format('契約期間はY年n月j日から');
echo $end_datetime->format('Y年n月j日までです。');