CodeIgniter 2.0 の新機能、変更点など
[]

2011.02.05

このエントリーをはてなブックマークに追加
はてなブックマーク - CodeIgniter 2.0 の新機能、変更点など

CodeIgniter 2.0 のブランチ

  • http://d.hatena.ne.jp/Kenji_s/20110129/1296265837
  • CodeIgniter Core
    • CIの開発元であるEllisLab の商用製品( Such as ExpressionEngine and MojoMotor )で使用されるブランチ
  • CodeIgniter Reactor
    • これがオープンソースコミュニティのためのメインブランチ。
    • CI コミュニティで育てていくためのブランチ。
    • 新機能、バグフィックス、改良、ドキュメンテーションの整備はこちらで行なわれる。
    • EllisLabによる CodeIgniter Core の成果物もこちらにマージされていく。

大きな変更点、新機能

  • PHP 4 サポートの廃止。今後は PHP 5.1 以上が必須要件となる。
  • フォームヘルパーでのCSRFプロテクション
  • Drivers
    • CodeIgniter 2.0 In Progress – The Critical Changes, Implications, and What You Should Know
    • Guide to CodeIgniter Drivers
    • ドライバーとはライブラリーの一種。
    • コントローラにライブラリ使用のためのエレガントなシンタックスを提供する。
    • adapter パターン + decorator パターン
    • Caching
      • $this->load->driver('cache');
      • $this->cache->memcached->save('foo', 'bar', 10);
      • $this->cache->apc->save('foo', 'bar', 10);
      • Cache_memcachedクラスからその親クラスであるCacheクラスにアクセスすることはできるが、
      • Cache_memcachedからCache_apcにアクセスするこはできない => クラスの機能を明確に分離する。
    • Database
    • Javascript
  • Application Packages
    • コンフィグファイル、ヘルパー、言語ファイル、ライブラリ、モデルといった アプリケーションに必要なコードを単一ディレクトリで構成することができる機能。プラグインのような感じで配布することが容易になる。
    • $this->load->add_package_path(APPPATH.'third_party/foo_bar/');
    • $this->load->library('foo_bar');
    • http://codeigniter.com/user_guide/libraries/loader.html
  • Scaffoldingの廃止。
  • Validationクラスは削除されました。=> Form Validationクラスを使う。
  • 今までのPlugin機能の削除。ヘルパーを使ってね。
  • Added routing overrides to the main index.php file, enabling the normal routing to be overridden on a per “index” file basis.
    • メインのindex.phpファイルを上書きするルーティングが追加されたので、通常のルーティングを有効にするには各"index"ファイルを上書きする。(よくわかんね)
  • 404ページをコントローラで制御するために$route[‘404_override’]を追加しました。
  • 50以上のバグフィックス。

Reactor には上記のものすべてに加え、以下のナイスな独自変更を含んでいる(以下のものはCoreには含まれないという意味だろう):

  • GETクエリ文字列の完全なサポート。
  • base_urlがブランクなら自動的に探知する。
  • ファイルシステムによる新しいキャッシュドライバー、APCとmemcacheのサポート
  • 簡単なcronジョブのためのコマンドラインに対応する。
  • 20以上の調整と改善。

すべての変更点はchange logをご覧あれ

コアクラスの拡張

コアクラス(system/core 内の CI_Controller など)の拡張クラス(MY_Controller)は

  • application/core

に配置する必要がある。 つまり application/libraries/MY_Controller.php は、application/core/MY_Controller.php に移動する必要がある。

system/libraries 内のクラスの拡張は 今まで通り application/libraries に配置してOK

refs

追記 2012.02.11

  • php5.3からはCIではなく、fuelPHPを使わせてもらうとこにした。
  • CIのライセンス問題ではなく単に実装の好みの問題で。

CodeIgniterでアンケートフォーム
[]

2010.02.07

このエントリーをはてなブックマークに追加
はてなブックマーク - CodeIgniterでアンケートフォーム

環境

  • CodeIgniter 1.7.2

ファイルレイアウト

ci_form/
`-- system/
    `-- application/
        |-- config/
        |   |-- form/
        |   |   `-- enquete.php                 // (1) 独自のフォーム定義ファイル
        |   `-- form_validation.php             // (2) ciの標準バリデーションファイル
        |-- controllers/
        |   `-- enquete.php                     // (3) Enqueteコントローラー
        |-- libraries/
        |   |-- MY_Controller.php               // (4) 独自拡張の基底コントローラー
        |   |-- MY_Model.php                    // (5) 独自拡張の基底モデル
        |   |-- jphpmailer.php                  // (6) phpmailerの日本語拡張ライブラリ
        |   `-- phpmailer/                      // (7) phpmailer本体
        |-- models/
        |   `-- form_model.php                  // (8) Formモデル
        `-- views/
            `-- enquete/
                |-- confirm.php
                |-- finish.php
                `-- index.php

ソース

メモ

  • フォームごとにフォーム定義ファイル(1)で一元管理(フォーム要素を)している。
  • バリデーションは、基本的に(2)に記述するが、例外的な処理は、コントローラのメソッドをコールバックとして呼ぶようにしている。
  • 個人的にphpのメーラーはphpmailerが最も安定していると思っている

(4) MY_Controller

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_Controller extends Controller {

  function __construct() {
    parent::__construct();
  }
 
  function get_controller_name(){
    global $RTR;                        // CI_Routerオブジェクト
    return $RTR->fetch_class();  // ルーティングのコントローラ名を返す
  }
 
  function get_action_name(){
    global $RTR;
    return $RTR->fetch_method();   // ルーティングのアクション名を返す
  }
 
  function get_namespace(){
    return $this->get_controller_name() .'.'. $this->get_action_name;
  }
 
  /**
   * トークンを生成する。
   */

  function create_token(){
    return date('YmdHis');
  }
 
  /**
   * jphpmailerを利用してメールを送信するメソッド
   *
   */

  function send_mail($t, $sbj='', $b='', $f='', $fn='', $atc = '') {
    log_message("debug", "------------ " . __METHOD__);
   
    if(! isset($t) ){
      show_error("送信先をしてしてください。");
    }
   
    $to; // 送信先
    $subject; // 題名
    $body; // 本文
    $from; // 送信元
    $fromname; // 送信元の名前
    $attachment; // 添付ファイルパス
   
    if(is_array($t) )
    {
      if(array_key_exists('to', $t) ){
        $to = $t['to'];
      }
      else{
        $err_msg = "送信先を指定してください。";
        log_message("error", $err_msg);
        show_error($err_msg);
      }
     
      if(array_key_exists('subject', $t) ){
        $subject = $t['subject'];
      }
      else{
        $err_msg = "タイトルを指定してください。";
        log_message("error", $err_msg);
        show_error($err_msg);
      }
     
      $body = $t['body'];
      $fromname = $t['fromname'];
     
      if(array_key_exists('from', $t) ){
        $from = $t['from'] = $t['from'];
      }
      if(array_key_exists('attachment', $t) ){
        $attachment = $t['attachment'];
      }
    }
    else
    {
      $to = $t;
      $subject = $sbj;
      $body = $b;
      $from = $f;
      $fromname = $fn;
      $attachment = $atc;
    }

    require_once APPPATH . "libraries/jphpmailer.php";
    $mailer = new JPHPMailer();
    $mailer->addTo($to);
    $mailer->setFrom($from, $fromname);
    $mailer->setSubject($subject);
    $mailer->setBody($body);
   
    //添付ファイル
    if( ! empty($attachfile) )
    {
      $mailer->addAttachment($attachment);
    }
   
    if( ! $mailer->send() )
    {
      log_message("debug", "メール送信失敗:".__METHOD__);
      return FALSE;
    }
   
    log_message("debug", "メール送信完了:".__METHOD__);
    return TRUE;
  }
}

?>

(3) Enqueteコントローラ

<?php

/**
 * アンケートコントローラ
 */

class Enquete extends MY_Controller
{
  function __construct() {
    parent::__construct();
   
    // モデルオブジェクトを作る.
    $this->load->model('form_model');
    // 本当はset_nameは、コンストラクタで処理したいところだが、
    // CIのロード処理をあんまり理解してないので、とりあえずここで注入してる。
    $this->form_model->set_name('enquete');
  }
 
  function index() {
    $data = $this->form_model->get_elements();
    $data['hiddens'] = array();
    $data['hiddens']['token'] = $this->create_token();
   
    if($this->input->post('token') ) {
      // トークンを検査。リロードや予期しない経路からのアクセスを禁止する。
      if( $this->form_model->check_token($this->input->post('token') ) == FALSE) {
        show_error('不正なトークンです。<input type="button" onclick="location.href=\'/index.php/enquete\'" value="戻る" />');
      }
     
      // validate inputs.
      if($this->form_model->validate() !== FALSE ) {
        // ビューに渡すデータを組み立てる。
        foreach($this->form_model->get_field_data() as $key => $val){
          $data['hiddens'][$key] = set_value($key);
        }
        $data['hiddens']['token'] = $this->form_model->get_token();
        $this->load->view('enquete/confirm', $data);
        return;
      }
    }
   
    // セッション領域にトークンを保存する。
    $this->form_model->set_token($data['hiddens']['token'] );
   
    // ビューに渡すデータを組み立てる。
    $field_data = $this->form_model->get_field_data();
    $data['username']['value'] = set_value('username');
    if( isset($field_data['job']) ) {
      $data['job'][$field_data['job']['postdata']]['checked'] = 'checked';
    }
    $data['jobother']['value'] = set_value('jobother');
    if( isset($field_data['hobby']['postdata']) ) {
      foreach( $field_data['hobby']['postdata'] as $v) {
        $data['hobby'][$v]['checked'] = 'checked';
      }
     
    }
    $this->load->view('enquete/index', $data);
  }
   
  function execute() {
    if($this->form_model->check_token($this->input->post('token') ) == FALSE ){
      show_error('不正なトークンです。<input type="button" onclick="location.href=\'/index.php/enquete\'" value="戻る" />');
    }
    $data = array();
    foreach( array_keys( $this->form_model->get_field_data() ) as $key ) {
      $data[$key] = $this->input->post($key);
    }
   
    $this->_send_mail($data);
   
    // TODO: セッションのクリア
   
    redirect('enquete/finish');
  }
 
  function finish() {
    $this->load->view('enquete/finish');
  }
 
  private function _send_mail($data) {
    log_message("debug", "------------ ". __METHOD__);
   
    // @TODO: 管理者にメールを送信する。
    // $dataを加工する
    //$this->send_mail($data);
  }
 
  public function jobother_check($val) {
    log_message('debug', 'jobother_check $val: ' . $val);
    $data = $this->form_validation->_field_data;
    //log_message('debug', 'jobother_check $data: ' . print_r($data, TRUE));
    if($data['job']['postdata'] == 4) {
      //log_message('debug', 'その他です。');
      if($val == '') {
        $this->form_validation->set_message('jobother_check', '%s: 入力必須項目です。');
        return FALSE;
      }
    }
    return TRUE;
  }
}

(8) Formモデル

モデルというよりはライブラリに近い。

<?php

class Form_model extends MY_Model {
 
  function __construct() {
    parent::__construct();
    $this->load->helper('url', 'form');
    $this->load->library('form_validation');   // 入力値検査はform_validationにデリゲートする。
    $this->load->library('session');              // CI_Sessionにトークンなどのデータを管理してもらう。
  }
 
  function set_token($token) {
    $this->session->set_userdata('token', $token);
  }
 
  function get_token() {
    return $this->session->userdata('token');
  }
 
  function check_token($token) {
    if($token == $this->get_token() ){
      return TRUE;
    }
    return FALSE;
  }
 
  function get_config($name = null) {
    if( isset($name) ){
      $this->set_name($name);
    }
    $this->load->config('form/' . $this->get_name() );
    return $this->config->item('form');
  }
 
  function get_elements($name = null) {
    $conf = $this->get_config($name);
    return $conf[$this->get_name()]['elements'];
  }
 
  function get_field_data() {
    $this->form_validation->run($this->get_name() );
    return $this->form_validation->_field_data;
  }
 
  function has_errors(){
    return count($this->form_validation->_error_array)? TRUE : FALSE;
  }
 
  function get_errors(){
    return $this->form_validation->_error_array;
  }
 
  function validate() {
    return $this->form_validation->run($this->get_name() );
  }
}

CIEX チートメモ
[]

2009.12.12

このエントリーをはてなブックマークに追加
はてなブックマーク - CIEX チートメモ

環境

  • CIEX:0.9.2
  • URL:http://example.com/

デフォルトモジュールを指定する

例えばhttp://example.com/にアクセスした時に defaultモジュールのindexコントローラーにアクセスさせたいとき。

htaccessファイル

public_html/.htaccess

RewriteEngine on
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^(.*)$ index.php/default [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

ルーティングの設定

code/config/routes.php

$route['default'] = 'default/index';

レイアウトを使う

<?php
/**
 * Layout
 */

class CIEX_Layout extends Layout
{
  function view($view = '' , $view_data = array(), $template = false, $module = true, $return = FALSE)
  {
    //// レイアウト内でbase_urlメソッドを使っているので
    //// urlヘルパーを先読みしておく。
    $this->CI =& get_instance();
    $this->CI->load->helper('url');
   
    parent::view($view, $view_data, $template, $module, $return);
  }
}

コントローラー内。

function index(){
  $this->layout->view('index');
}

xmlhttprequestによるリクエストであることを判別する
[]

2009.09.05

このエントリーをはてなブックマークに追加
はてなブックマーク - xmlhttprequestによるリクエストであることを判別する

<?php
  function _is_xmlhttprequest() {
    if($this->input->server('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' ){
      return true;
    }
    return false;
  }

Auth(認証)ライブラリ
[]

2009.08.28

このエントリーをはてなブックマークに追加
はてなブックマーク - Auth(認証)ライブラリ

CodeIgniterのHMVC拡張であるCIEXで動作するAuthライブラリ。


> 続きを読む

アプリケーションフロー図
[]

2009.07.20

このエントリーをはてなブックマークに追加
はてなブックマーク - アプリケーションフロー図

/index.php/welcome/indexをリクエストした場合のフロー

ci_app_flow

CodeIgniterでメールフォーム作成
[]

2009.04.09

このエントリーをはてなブックマークに追加
はてなブックマーク - CodeIgniterでメールフォーム作成

CIってどんなんかなと気になってたのでとりあえず メールフォームを作ってみた。足りないものは自分で拡張・実装するのがCIの流儀みたい。 入力データをPOSTで持ち回す場合。


> 続きを読む