CakePHP : beforeDelete() でちょっと幸せになる

CakePHP のコールバック関数たちは優秀ですね。
もちろん便利に活用させてもらってます。

今日は afterDelete() で後処理を色々する場合の、beforeDelete() を使ったちょっとしたTipsをご紹介します。

afterDelete() では $this->data は空

$this->id は格納されているのですが、$this->data は空なんです。
ま、afterDelete() でデータを利用しない方も多数でしょうから、無駄な処理は入れてないんでしょうね。


ただ関連するデータをアップデートしたりと、削除されるインスタンスが保持するデータを利用したいケースってのも結構あったりします。
これを beforeDelete() で楽して解決してしまおうという主旨です。

beforeDelete() で $this->data をセット

app_model.php に単純に以下のようなコードを書きます。
これで自動的に $this->data はセットされ、 afterDelete() などでデータを使いまわせます。

<?php
/**
 * Before delete callback.
 * The function is cakephp callback method.
 * 
 * @return boolean
 */
    function beforeDelete()
    {
        // 削除する前に保持するデータをオブジェクトに置いておく
        // こうすることで、afterDelete() で保持データを利用できる。
        // 通常では $this->id しか保持されない。
        $this->data = $this->find('first', array(
            'recursive' => 0,
            'conditions' => array($this->name . '.id' => $this->id)
        ));
        return true;
    }
?>

afterDelete() で $this->data を利用するサンプル

私は以下のような形でデータを利用しています。ご参考までに。

<?php
/**
 * After delete callback.
 * The function is cakephp callback method.
 * 
 * @return boolean
 */
    function afterDelete()
    {
    // Update association model
        if (!$this->_updateSummary($this->data['ModelName']['forign_key_id'])) {
            $this->log("Model->afterDelete() Update summary is failed.");
        }
        return true;
    }
?>

コストパフォーマンスを重視して、安く快適な賃貸生活を手に入れるための7つのTips

最近、久々の一人暮らしを開始し都内に引越したので、その時色々調べたり、感じたりしたことをまとめてみようと思います。
私は当時、何よりもコストパフォーマンスを重視していました。

Tips1 : 相場感をつかむ

まずは、引越し先の相場感を掴んでおきましょう。
よく言われることですが、相場感があれば下手に高い物件に掴まるようなことはありません。


オススメしたいのは、
http://www.homes.co.jp/にて「 新着物件メール 」にお好みの住宅条件(広さ、間取りなど)をに設定しておくことです。
自動で新着が届きますので、相場感を掴むのにはもってこいです。
1ヶ月程度ウォッチングすれば十分だと思います。

Tips2 : 礼金ゼロで物件を決める

世の流れか、礼金ゼロの物件も増えているようです。
そもそも、礼金を借主が払うのおかしいと自分は思っています。
礼金ゼロの物件をみつけると、お財布にやさしく、コストパフォーマンスも抜群にあがります。


ただ、場所の影響を受けるみたいなのでご注意を。
人気の高い地域は貸主が強気で、礼金2が普通だったりするそうです。
(業者談)

Tips2-1 : UR賃貸

すでにご紹介されている方も多数なので、説明は省略いたしますが、なんといっても魅力は

礼金、仲介手数料、更新料が全て0」


エクセルなどを作って比較すれば一目瞭然ですが、更新を考えると圧倒的なコストパフォーマンスを発揮します。
難を言えば、予約を取るのにわざわざURまで出向かないといけない事でしょうか。



※UR賃貸はエアコンが設置されていないなど、付帯設備の自己負担があったりもします。

Tips2-2 : 礼金0 の一般仲介業者

そんな世の時流を受け、いくつかの業者も特集的なものを用意しているみたいです。
この辺りで調べてみると、幸せな物件に出会えるかもしれません。
礼金に加え、敷金までゼロみたいですよ。

Tips3 : 買い取ってもらえるゴミは適材適所で

物によってはゴミがお金に換わったりしますよね。ただ、持ち込む場所によっては面倒だったりも・・・。そんな買い取り場所に関するTipsです。

Tips3-1 : 本、映像

王道の「本・家電を売るならBOOKOFF(ブックオフ)」は、買い取りも楽チンです。
まとまった量があれば引き取りにも応じてくれます。
一旦預けて、後日お金を受け取りなんてことも対応してもらえました。

Tips3-2 : PC関連

ネットで調べて店舗情報 | PCデポ」に持ち込みましたが、ココは最低。
何より自分たちの都合しか考えてない仕組みに思えました。
何度も同じ事を別の紙に書かせ、その上当たり前のように査定完了は後日。
二度と使いたくないですね〜。

Tips3-3 : 楽器その他

今回はココが大当たり。
地元そばの「千葉で不用品回収やリサイクル業者をお探しなら株式会社 アイアール」という業者に持ち込みました。

なんといっても特徴は、商品の確認が不要なこと。
楽器は音だし不要だし、PCパーツは稼動確認不要です。

スピード感抜群で買い取りを実施してくれます。


Tips4 : 粗大ゴミを一気に無くす

粗大ゴミは事前に受付センターに連絡して、料金も別納しなくてはならず、意外と面倒ですよね。
そして、引き取ってくれるのは所定の日。
「どんどんゴミを捨てたい」という引越し時のスピード感とは適合しないのです。

皆さんもゴミさえ無くなれば、だいぶ片付けも進展するのに・・・ と思ったりしませんか?


こんなミスマッチをビジネスと捉えているのが、隙間産業とも言うべき「不用品回収業者」。
どんなゴミでも引き取ってくれますが、かな〜り高いです。
以前、已む無く一度利用しましたが、数万円の費用を請求されました><


これを一気に解決するのが

「個人でのゴミの持ち込み」


市区町村によるようですが、持ち込みを許可している自治体も多く、ゴミさえ輸送できればその場で処理してくれます。
持ち込みによる割引はあまり無さそうですが、1〜2時間労働で、その日にゴミを無くせるというのは魅力的ではないでしょうか?


ゴミが無くなることで、片付けは大幅に進展するはずです。
ま、当たり前のことですねw

Tips5 : 引越し業者もコストパフォーマンス重視

評判どおり「引越し・引っ越し業者探しは赤井 英和でお馴染み【アリさんマークの引越社】公式サイト」凄すぎでした。
とにかく尋常じゃないサービスレベル。引越し業者としてのクオリティは、今まで利用した業者の中でぴか一です。
値段も決して高くなく、良心的な価格設定。もうこの引越し業者以外は使う気しないですね〜。


価格交渉を行いたい方は、参考値として「Cookie Error」で見積もりを多めに貰っておき、価格交渉に望むといいでしょうね。
私は数千円単位の値引き交渉をしました。


Tips6 : 電化製品を安く買う

電化製品購入時に、買ったもののポイントで別のものを安く購入するという手法は当たり前ですが、
さらに、ネット回線も同時契約して値引きを手に入れましょう。


私はビックカメラで、回線を同時契約することで買い物合計から3万円の値引きをGet。
どうせインターネットの回線は必要になるので、なかなか有効な手だと思いますよ。
電化製品は早い時期に購入しますので、「引越しとほぼ同時にネット回線が来る」なんていう素敵な事にもなるかもしれません。


Tips7 : 安く良質な家具を買う

これは好みの問題も大きいですが、二大巨頭は「IKEA」「ニトリ」です。
私はIKEAをメインに利用しましたが、ニトリもコストパフォーマンスでは負けてないように見えました。
実物を見る必要がなければ「Amazon」「楽天」なんかのネットショッピングも使えますね。

PHPの自動型変換は完璧ではない(小数系関数と型)

PHPに毒されすぎて、コーディングしていたら「アレ?」となった件です。
ま、当たり前ですが、自動型変換は完璧ではないんですね。
当然マニュアルにはちゃんと書いてありました・・・(恥)

<?php
$odd = 7;
$target = $odd / 2;

// 四捨五入
$numA = round($target);
echo is_int($numA) . "\n"; // false


// 切り上げ
$numB = ceil($target);
echo is_int($numB) . "\n"; // false

// 切り捨て
$numC = floor($target);
echo is_int($numC) . "\n"; // false

// 型を明示
$numD = (int)round($target);
echo is_int($numD) . "\n"; // true

// 整数部分のみを取得
$numE = intval(round($target));
echo is_int($numE) . "\n"; // true
?>

「男は30(三十路)から」を論理的に説明してみる

「男は30(三十路)から」ってよく言いますよね。
まぁ、なんとなく「仕事」とか「経済性」などが原因かなって思ってました。
自分自身そんな三十路に突入しましたが、正直自分自身はあまり変わってないという実感です。


そんな日々の中ちょっとした気づきがあり、三十路男性から納得の声をたくさんもらったので
今日はそんな「男は30から」を論理的に説明してみようと思います。
(半分以上は推論なので、語弊はお許しください。←そんなんで書くな!とお叱りを受けそうではありますが・・・)


何が30からなのか?

やはり発言者によって、その意図が異なるように思えます。
まずはココから個別にみていきます。

発言者:目上の方(仕事上の上司など)

これは間違いなく仕事にフォーカスしてますね。
「ようやく仕事のイロハも分かってきたし、これから油も乗る時期だよ」といった意図でしょう。

発言者:後輩

そもそもあまり聞きませんね。除外します。

発言者:女性

女性から「男は30から」といった表現を多く聞く気がします。
この背景などを解明していけば、論理的に説明がつきそうだとあたりをつけました。

発言者:自分

これは単に周りが言っていることに乗っかりたいという希望ですね。
自分自身そうですしw


女性から見た30代男性とは?

上記あたりに沿って、まずは女性の視点から問題を解きほぐしていきます。


30男の魅力ってなんなんでしょう?
女性ではないので心の内は分かりませんが、客観的に見て次の点は正しいのではないかと思います。

  • 仕事
    • 知識・経験がついてきてる(はず)
  • 経済性
    • 20代よりは相対的に経済力がある
  • 包容力
    • 20代よりはあるように見える(のだと思います)
  • 性格
    • 各人の特性が強く出てきており、自分に合う/合わないが判断しやすい
  • 将来性
    • 出来る人/出来ない人 が別れ実績として現れてくるため、判断しやすい
  • 結婚への距離
    • 近いように見える


このように並べてみると、30代男性は
「結婚→子供」という観点では、女性にとってパートナーを探しやすい世代であると言えると思います。


このため、

女性から「男は30から」という発言を聞く機会が多く、
その背景には幸せな家庭というゴールがあるのではないでしょうか?


「男は30から」の本質は、色恋事にあるということになります。


実際の30代男性とは?

三十路に入り男性は大きく成長するのでしょうか?
人それぞれだとは思いますが、各人の実感としては

「特に何も変わっていない」

といった所ではないでしょうか。
勿論仕事上のスキルはあがってはいるのですが、
男性にとって、30代は20代の延長線上にあるんだと思います。


ただ、結婚については周りも半分程度が結婚していますし、かなり前向きに捉えるようになってきているでしょうね。


では結論を

ここまでの話は一般的な話を小難しく語っているだけでした。
自分でも書いてて、何をわざわざ・・・ という気分も。


ただ、ここからがポイントです!!
先日ヒラメキました。


その背景には色恋事があるという推論が前提ですが、
「男は30から」は、論理的に説明がつくのです。(はずです。)


私なりの結論から言いましょう。
それは

「単に需要と供給のバランスが偏っているだけ」

です。


これだけ書くと何の事やら意味不明なので、ひとつずつ解説します。

1. 30男の結婚適応者は既に多くが売れている

いい人ほど早く結婚していきますね

2. 30男は結婚相手として選びやすい

20代女性も同年代の女性も、30男には魅力を感じる(ような気がします)
ということは、魅力を感じる女性の世代は広い と言い換えられます。



こう考えていくと、

  • まともな30男には多くの女性が関心を示し
  • その絶対数は少ない

という事が浮かびあがってきます。


これはまさに

需要 > 供給

の図式ではないでしょうか?
正直ホントこれだけな気がします。



最後に、同士男性諸君へ

「なんか最近モテる」などと勘違いしないほうが良さそうです。
35を超えるとこの男何かしら問題があるのでは? と女性は勘ぐるそうです。
ま、ごもっともです。


というわけで

「ただ、今が売り時なだけ!」
なんだと思います。


結局最後に、
「一人の大切な人を見つけられるかどうか」

が僕らにとっても大切ですよね?



以上です。

P.S.
本当に論理的に説明がついたかが不安ではありますが・・・

PHPで日付(日時)差の計算(日数、週数、月数、年数)

必要になる機会が発生したので、「エイヤー!」ではありますが作りました。
ググってみましたが、同様の記事が無さそうだったので、せっかくなので晒します。


とはいえ、まだまだ若輩者のプログラマーが作成したルーチンです。
自分自身、速度的・論理的無駄を内包しかねない事を認識しています。
なので、ご指摘・ご教授大歓迎です。お気づきあれば、ぜひ一言よろしくお願いいたします。

ルーチンの説明

  • 「開始日」x「終了日」の差を算出するルーチンです。
    • 入力値は、「開始日」 < 「終了日」 となることを想定しています。
      • 開始日=2009/6/15, 終了日=2009/6/16 はOK
      • 開始日=2009/6/17, 終了日=2009/6/16 はNG
  • 指定した単位に基づいて差を返します。
    • 月を指定した場合、差の月数
    • 日を指定した場合、差の日数
    • デフォルトは日数です。
  • 指定した単位に満たない場合は、0を返します。
    • 例えば、2008/4/1 と 2009/3/30 との差の年数を求めた場合、0となります。

考え方・実装にあたって

  • 日数、週数
    • うるう年を考慮するのが面倒だったので、タイムスタンプの差から算出
  • 月数、年数
    • 年、月、日を個別に比較し、差を算出

PHPのソース

<?php

define('TERM_UNIT_YEAR', 'year');
define('TERM_UNIT_MONTH', 'month');
define('TERM_UNIT_WEEK', 'week');
define('TERM_UNIT_DAY', 'day');
define('TIMESTAMP_UNIT_DAY', 24 * 60 * 60);

/**
 * Calculation date distance between two date.
 * 
 * @param string $dateStart  Date of start point.
 * @param string $dateEnd  Date of end point.
 * @param string $termUnit  Unit string of terms (ex. day, month...)
 * @return integer  Distance between twon date depend on assigned term unit.
 */
    function _calcDateDistance($dateStart, $dateEnd, $termUnit = null)
    {
    // Check args
        if (empty($dateStart) || empty($dateEnd)) {
            return false;
        }
    // Change to timestamp
        $timestampStart = strtotime($dateStart);
        $timestampEnd = strtotime($dateEnd);
    // Check & Compare dates
        if (empty($timestampStart) || empty($timestampEnd)) {
                return false;
        } else {
                if ($timestampStart > $timestampEnd) {
                        $tmpTimestamp = $timestampStart;
                        $timestampStart = $timestampEnd;
                        $timestampEnd = $tmpTimestamp;
                }
        }
    // Set vars    
        $timestampDistance = $timestampEnd - $timestampStart;
        $datesStart = getdate($timestampStart);
        $datesEnd = getdate($timestampEnd);
    // Calc distance
        $distance = 0;
        switch ($termUnit) {
        case TERM_UNIT_YEAR:
        case TERM_UNIT_MONTH:
        // Set vars
            $lessThanTerm = false;
            $distanceYear = $datesEnd['year'] - $datesStart['year'];
            $distanceMonth = $datesEnd['mon'] - $datesStart['mon'];
            $distanceDay = $datesEnd['mday'] - $datesStart['mday'];
        // Check day & moving down
            if ($distanceDay < 0) {
                if ($distanceMonth > 0) {
                    $distanceMonth = $distanceMonth - 1;
                } else {
                        if ($distanceYear > 0) {
                                $distanceYear = $distanceYear - 1;
                                $distanceMonth = $distanceMonth + 12 - 1;
                        } else {
                                $lessThanTerm = true;
                        }
                }
            }
        // Check month & moving down
            if ($distanceMonth < 0) {
                if ($distanceYear > 0) {
                    $distanceYear = $distanceYear - 1;
                    $distanceMonth = $distanceMonth + 12;
                } else {
                        $lessThanTerm = true;
                }
            }
        // Check year
            //if ($distanceYear < 0) {}
        // Check calc result & sum result.
            switch ($termUnit) {
                case TERM_UNIT_YEAR:
                        if ($lessThanTerm) {
                                $distance = 0;
                        } else {
                                $distance = abs($distanceYear);
                        }
                    break;
                case TERM_UNIT_MONTH:
                        if ($lessThanTerm) {
                                $distance += abs($distanceMonth);
                        } else {
                        // Sum year & month
                            if (!empty($distanceYear)) {
                                $distance += abs($distanceYear) * 12;
                            }
                            if (!empty($distanceMonth)) {
                                $distance += abs($distanceMonth);
                            }
                        }
                break;
            }
            break;
        case TERM_UNIT_WEEK:
            $distance = $timestampDistance / (TIMESTAMP_UNIT_DAY * 7);
            $distance = abs(floor($distance));
            break;
        case TERM_UNIT_DAY:
        default:
                $distance = $timestampDistance / TIMESTAMP_UNIT_DAY;
                $distance = abs(floor($distance));
            break;
        }
        return $distance;
    }
?>

実行サンプル

<?php
echo _calcDateDistance('2009-6-17', '2009-6-18', TERM_UNIT_DAY);
1

echo _calcDateDistance('2008-6-17', '2009-6-17', TERM_UNIT_DAY);
365

echo _calcDateDistance('2009-6-17', '2009-6-18', TERM_UNIT_WEEK);
0

echo _calcDateDistance('2008-6-17', '2009-6-17', TERM_UNIT_WEEK);
52

echo _calcDateDistance('2008-6-17', '2009-6-16', TERM_UNIT_MONTH);
11

echo _calcDateDistance('2008-6-17', '2009-6-17', TERM_UNIT_MONTH);
12

echo _calcDateDistance('2008-6-17', '2009-6-16', TERM_UNIT_YEAR);
0

echo _calcDateDistance('2008-6-17', '2009-6-17', TERM_UNIT_YEAR);
1
?>

日時の差は「??年?月?日」です。的な答えがほしい場合は

次の形で出来ると想像してます。(未検証)


1) 年の差分を計算
2) (1)の答え分を引数$dateStartに反映して、再帰的に呼ぶ
3) (2)の答え分を引数$dateStartに反映して、再帰的に呼ぶ
4) (1)と(2)と(3)の答えを合体


以上です。

更新履歴

  • 2009/06/22
    • 「開始日」 < 「終了日」というアホな仕様を取り除きました。最初からこうしとけば良かった。。。

世襲はアホな国民の問題

最近世を騒がせている「世襲問題」
これって、個人的にはやっぱり「アホな国民の問題」だと思う。(あくまで主観)

制度として制限する事自体はやぶさかではありませんが、本質を見失ってる世論が怖いな〜 って思いつつエントリー。


そもそも議員は国民が選ぶもので、

国民 = 雇用主
議員 = 社員

の関係ですよ。

そして、その社員が代々続くかどうかは、雇用主が決めてるじゃないですか。

だとしたら

そう、責任は国民にある! って論理になりませんかねぇ?


もちろん、我が日本国には、世襲により文化・芸能・政治 etc.... を動かしてきたという歴史がありますので、
国民が比較的世襲を受け入れやすい土壌があることは想像に難しくありません。



ただ、だからといって

能力があるか分からない2世を選ぶのでしょうか?
議員はその主義・主張と実績を評価されるべきものだと思います。


堀江さんは、「日本全国で芸能人が出馬したら面白い」とかおっしゃってましたが、

正直コレ笑えません。。。
ま、堀江さんにも特に意図はなく冗談だと思うので、発言に言及したいわけではないのであしからず。



芸能人って個人の価値をいかにして高めるか が仕事の人たち。

対して、議員は、日本(ないしは地方)総体を、いかにして高めていくか って商売なわけで
そもそも考えるべき対象が異なると思うんです。


彼らのアピール力はそれこそ賞賛に値しますが、今回それはどーでもいいとして。
彼らの主義・主張&実績は評価できるものですか?

僕には、最近の選挙はただの人気投票にしか思えません。



先日の千葉選挙も酷かった・・・

なぜ「森田健作」????

ちゃんと主張を読んでみると、森田健作に投票する気なんて、これっぽっちもおきませんよ。
朝刊の折り込みに入ってる主義・主張の一覧をみんな読めばいいのに。。。 と愚痴らせてください。
ただ、いまどきはネット社会ですから新聞なんて時代遅れなんでしょうね。



ネット上で
議員の主義・主張をどうやって公平に伝達するかも議論が必要なところですが、
ネット上のコミュニケーションで、評価・批判がもっと噴出していいはずだと思います。


というわけで、一市民が主義・主張を書いてみました。

CakePHP Behaviorでモデルのメソッドキャッシュ with find() オーバーライド

元ネタは以下2つのエントリー。

http://www.exgear.jp/blog/2008/11/cakephp12-behavior%E3%81%A7%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%82%92%E8%A1%8C%E3%81%86/

http://blog.katsuma.tv/2009/04/cakephp_model_cache.html


車輪の再発明というわけではないですが、好みに併せて少し改変。
メモ代わりに残します。

目的

サイト全体の高速化
View cache を利用出来ない部分が主

メリット/デメリット

http://blog.katsuma.tv/2009/04/cakephp_model_cache.html
上記ページに分かり易く記載されているので、ここでは簡潔に。

最大のメリットは
キャッシュを意識することなく、クエリーキャッシュを利用することが出来る事。

逆にデメリットは
完全な最適化が行われるわけではないので、最も早くなるわけではない。
ま、これは個別に対応すればよいという整理。

導入手法

1)CacheBehavior を導入
ソースは以下から。
http://www.exgear.jp/blog/2008/11/cakephp12-behavior%E3%81%A7%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%82%92%E8%A1%8C%E3%81%86/

動作させるために、Model に Behavior 属性を記載。
怠慢な私は、app_model.php に記載しちゃってます。


2)find() をオーバーライド
app_model.php 上で find() をオーバーライド。
以下のような形で、キャッシュでフォルト設定から Duration(キャッシュ有効時間)を引き継いでます。
また、明示的に Duration を指定したい場合に備えて、 $options 内に属性を勝手に定義。まめにキャッシュをクリアしたいコンテンツなどで利用してます。

<?php
/**
 * Find over write.
 * モデルキャッシュを利用するために
 * 
 * @link http://blog.katsuma.tv/2009/04/cakephp_model_cache.html
 */
function find($type, $queryData = array())
{
     switch ($type) {
     case '任意のタイプ':
          return $this->find('all', Set::merge(array("conditions"=>array('任意の検索条件')), $queryData));

     default:
     // Set cache duration
          if (is_array($queryData) && isset($queryData['cacheDuration']) && !empty($queryData['cacheDuration'])) {
               $cacheDuration = $queryData['cacheDuration'];
               unset($queryData['cacheDuration']);
          } else {
               $cacheSetting = Cache::settings();
               $cacheDuration = $cacheSetting['duration'];
          }
          if (!is_numeric($cacheDuration)) {
               $cacheDuration = strtotime($cacheDuration) - time();
          }
          if ($cacheDuration < 1) {
               return false;
          }
     // Call cache method
          $args = array($type, $queryData);
          if ($this->Behaviors->attached('Cache')) {
               if($this->cacheEnabled()) {
                    return $this->cacheMethod($cacheDuration, __FUNCTION__, $args);
               }
          }
     // Case normal find. The model does not have cache behavior.
          return parent::find($type, $queryData);
     }
}
?>

3)Model->field() で Warning が。

検索条件を指定する部分は

<?php
$hoge_id = $this->field('hoge_id', array('id' => $id));
?>

では駄目でした。

<?php
$hoge_id = $this->field('hoge_id', array('Fuga.id' => $id));
?>

という形で、Model 名を明示的に指定すればOK
親クラスのメソッドを使ってるからだろと。

なぜ動かない?

実装の途中で不可解な事象に遭遇。何故だろう?

最終的に

<?php
return parent::find($type, $queryData);
?>

とした部分。

情報ソースのサイトでは

<?php
$parent = get_parent_class($this);
return call_user_func_array(array($parent, __FUNCTION__), $args);
?>

となっていた。
ソースを眺めた時点では、特に気にする事はなかったのだが。。。
いざ実行してみると、真っ白画面が。。。

インスタンス参照の問題?