知り合いのお父上が亡くなってそのお通夜に行ってきました。

その知り合いの家には、この世のものとは思えないほど愛らしい可愛いヨークシャーテリアがいるんです。オトちゃんといいます。被災地で保護された女の子だと聞いています。

言っときますがね、写真ではオトちゃんの可愛さの12%くらいしか伝わりませんから。私は犬は大型の方が好きだったんです。オトちゃんを知るまでは。

のっけから関係ない話で驀進してますが、そう、cal_body()に問題あるよね、という話でしたね。

今のcal_body()のコードは、それはそれで完結しているので、そのままリネームして残して、再利用しようと思います。

private function make_calendar($year,$month){
    $cal_body = "";
    $date = mktime(0,0,0,$month,1,$year);
    
    for($i = 0 ; $i < date("t",$date); $i++){
        $week_number = date("w",mktime(0,0,0,$month,$i+1,$year));
        if($week_number == 0 && $i != 0){
            $cal_body .= "<tr>";
        } else if($i == 0){
            $cal_body .= $this->spacecell($week_number);
        }
        $cal_body .= "<td>" . ($i + 1) . "</td>";
        if($week_number == 6){
            $cal_body .= "</tr>";
        }
        if(($i + 1) == date("t",$date)){
            $cal_body .= $this->spacecell(6 - $week_number);
        }
    }
    return $cal_body;
}

make_calendar()という名前にしてしまいました。で、

private function cal_body($data){
        
}

cal_body()を新たに空の状態で作ります。ただし、受け取る引数は$dataです。これは連想配列を想定しています。とりあえずcal_body()はこのままにしておき、cal_body()を呼び出している側の引数を変更します。

private function disp_calendar($data){
    $this->template->title = "祝!フロイデさん31周期!!";
    $this->template->content = View::forge('calendar/index',$data);
    $this->template->content->set_safe('cal_head',$this->cal_header());
    $this->template->content->set_safe('cal_body',$this->cal_body($data));
    $this->template->content->set_safe('options',$this->makeOptions($data['month_num']));
}

そして、このdisp_calendar()を呼び出している部分で、$dataという連想配列にひとつ要素を加えます。まずはaction_index()から。

public function action_index()
{
    //$data["subnav"] = array('index'=> 'active' );
    $data["month"] = date("F");
    $data["today"] = date("Y/m/d");
    $data["year"] = date("Y");
    $data["month_num"] = date("n");
    $data["msg"] = "";
    
    $this->disp_calendar($data);
}

$data[“msg”] = “”;

を追加しました。中身が空文字です。ここには、もしValidationに引っかかったときのメッセージを格納しようと思います。つまり、ここに空文字でなく、何らか文字列が入っていたら、それはValidationチェックに引っかかったので、カレンダーが作れない、という判断基準になり得ます。

ボタンを押下したときのactionにも追加します。

public function action_putbutton(){
    
    $val = Validation::forge();
    $val->add("year","年")->add_rule("required")->add_rule("match_pattern","/^[1-9][0-9][0-9][0-9]$/","西暦");
    $val->set_message("required",":labelは必須項目です。");
    $val->set_message("match_pattern",":labelは数字4桁で入力してください。");
    if($val->run()){
        $data["month"] = date("F",mktime(0,0,0,$val->input("month"),1,$val->input("year")));
        $data["today"] = date("Y/m/d");
        $data["year"] = $val->input("year");
        $data["month_num"] = $val->input("month");
        $data["msg"] = "";
        
        $this->disp_calendar($data);
        
    } else {
        
    }
}

では再度作り直したcal_body()の中身を作っていきます。

private function cal_body($data){
    if($data["msg"] == ""){
        //きちんと入力されていて、カレンダーが作れる
        return $this->make_calendar($data["year"], $data["month_num"]);
    } else {
        //入力が不備でカレンダーが作れない
        
    }
}

ここまでで、少なくとも今までと同じ動きはしてほしいです。試します。

初期表示

大丈夫。ボタン押下、2000年4月にしてみます。私がプログラマになったとき。

大丈夫そうですね。ではいよいよ、Validationチェックに引っかかったケースを作っていきます。

まず、ボタンを押下したとき。

public function action_putbutton(){
    
    $val = Validation::forge();
    $val->add("year","年")->add_rule("required")->add_rule("match_pattern","/^[1-9][0-9][0-9][0-9]$/","西暦");
    $val->set_message("required",":labelは必須項目です。");
    $val->set_message("match_pattern",":labelは数字4桁で入力してください。");
    if($val->run()){
        $data["month"] = date("F",mktime(0,0,0,$val->input("month"),1,$val->input("year")));
        $data["today"] = date("Y/m/d");
        $data["year"] = $val->input("year");
        $data["month_num"] = $val->input("month");
        $data["msg"] = "";
        
        $this->disp_calendar($data);
        
    } else {
        $data["month"] = "";
        $data["today"] = date("Y/m/d");
        $data["year"] = $val->input("year");
        $data["month_num"] = $val->input("month");
        
        $msg = $val->error_message();
        $data["msg"] = $msg[0];
        
        $this->disp_calendar($data);
    }
}

Validationクラスのerror_message()は、チェックに引っかかった際のエラーメッセージを配列形式で返します。その最初のメッセージを$data[“msg”]に格納しています。

そのうえでdisp_calendar()を呼び出し、そこからcal_body()が呼び出されます。

cal_body()を作りこむ前に、ここで取得したエラーメッセージを表示できるようにしたいです。

views\calendar\index.phpに一行加えます。

<div class="row">
    <div class="col-md-3"></div>
    <div class="col-md-6">
    <form method="post" action="putbutton">
            <table>
                <tr>
                    <td style="width: 100px">
                        <input name="year" value="<?php echo $year;?>" size="6" maxlength="4"/>年
                    </td>
                    <td style="width: 90px">
                            <select name="month" style="height: 30px">
                                <?php echo $options;?>
                            </select>
                    </td>
                    <td><button type="submit" class="btn btn-primary">表示</button></td>
                    <td><?php echo $msg;?></td>
                </tr>
            </table>
            <h3><?php echo $month;?></h3>
            <label>Today:
                <?php echo $today; ?>
            </label>
            <div class="table-responsive">
            <table class="table table-bordered text-center">
                <?php echo $cal_head;?>
                <?php echo $cal_body;?>
            </table>
            </div>
    </form>
    </div>
  <div class="col-md-3"></div>
</div>

ボタンの横にもう1カラム、メッセージを表示する欄を追加しました。

こういう追加をすると、これを表示する部分をdisp_calendar()に追加します。

private function disp_calendar($data){
    $this->template->title = "祝!フロイデさん31周期!!";
    $this->template->content = View::forge('calendar/index',$data);
    $this->template->msg = $data["msg"];
    $this->template->content->set_safe('cal_head',$this->cal_header());
    $this->template->content->set_safe('cal_body',$this->cal_body($data));
    $this->template->content->set_safe('options',$this->makeOptions($data['month_num']));
}

カレンダーを表示する入り口となるこの部分を各アクションから切り出したので、ここ1か所を修正するだけで、どのアクションにも反映します。

ちょっと長くなりましたが、あと一息なので、頑張って作っちゃいましょう。

cal_body()で一工夫します。正常にカレンダーが作れるときはmake_calendar()を呼び出しますが、作れないとき用の別のfunctionを用意します。

private function disp_error(){
  
    $err_body = '<tr><td colspan="6">';
  
    $err_body .= Asset::img("dog_face01_d_12.png");
  
    $err_body .= "</td></tr>";
  
    return $err_body;
  
}

こんなのを用意。これをcal_body()の中で呼びます。

private function cal_body($data){
  
    if($data["msg"] == ""){
  
        //きちんと入力されていて、カレンダーが作れる
  
        return $this->make_calendar($data["year"], $data["month_num"]);
  
    } else {
  
        //入力が不備でカレンダーが作れない
  
        return $this->disp_error();
  
    }
  
}

ここまで一気に書いてしまったので、どうでしょ。動くかな。

やっぱりね。世の中そう甘くはありません。error_message()ってただの配列返すんじゃなかったっけかなー。。連想配列にしてみるか。。

$data[“msg”] = $msg[“year”];

に直してみました。

で、年を空白にしてボタンを押下します。

出た!

ボタンの横にエラーメッセージが出てますね。絵が、でかい。。少し調整します。

private function disp_error(){
    $err_body = ‘<tr><td colspan=”7″>’;
    $err_body .= Asset::img(“dog_face01_d_12.png”,array(‘width’=>’500’));
    $err_body .= “</td></tr>”;
    return $err_body;
}

col_spanも間違えてましたね。7です。

今度は、空白ではないが、西暦として不適切な入力をしてみます。予想としてはボタンの横のメッセージが変わるはずです。

出来たんじゃね?

この犬だか熊だか分からん絵は、フリー画像をダウンロードして、public\assets\imgフォルダの中に置いておき、Asset::img(“ファイル名”);でimsgタグが作成されてこのように表示されます。

まだ見てないんですけど、たぶん本書の日曜日編でも使うんじゃないですかね。

ということで、本書土曜日編を、拡張した番外編として、ご活用ください(笑)

今回はソース部分を見やすくするためにhtmlを調整しました。おいおい過去記事も見やすく直しますね。

とりあえず、カレンダーは完成です。ふ~~。

しかし、ブログ上で細かく説明するのは至難の技です。つまりは書籍でも同じですよね。限界を感じます。今までたくさんの未経験者を教えてきた感触から、このブログでももっとかみ砕いた解説が必要でしょう。しかし、それを記事にしていると膨大なことになってしまいますよね。。

私、近々、東京荻窪で、JIN PROGRAMING ACADEMYというプログラミング専門の塾を開講予定です。そこではもっとかみ砕いて、懇切丁寧にノウハウを伝授することができると思います。

ちと宣伝(^^;;;;

次回は、日曜日編に目を向けますよ。そこにもまだ見ていない美味しい技術がちりばめられていそうですからね。一冊の教科書を貪り尽くす。開講予定の塾での基本方針でもあります。

てなわけでお疲れ様でした。