ラベル codeigniter の投稿を表示しています。 すべての投稿を表示
ラベル codeigniter の投稿を表示しています。 すべての投稿を表示

2013年1月16日

CodeIgniter + 超シンプルObject Relational Mapping(ORM)





■ はじめに

このページで紹介するORMはCodeIgniterのメソッドから極力外れないように作成した非常に簡素なものです。後述しますが、既にCodeIgniterで使えるORM用のライブラリが存在します。多機能なものを使いたい方はそちらをお勧めします。

■ Object Relational Mapping(ORM)とは

オブジェクト関係マッピング(英: Object-relational mapping、O/RM、ORM)とは、データベースとオブジェクト指向プログラミング言語の間の非互換なデータを変換するプログラミング技法である。オブジェクト関連マッピングとも呼ぶ。実際には、オブジェクト指向言語から使える「仮想」オブジェクトデータベースを構築する手法である。
(引用元:オブジェクト関係マッピング)



■ CodeIgniterで使えるORMライブラリ





■ コンセプト


  • シンプル、簡単、拡張可
  • CodeIgnierのメソッドを極力変更しない
  • モデルファイルを自動で作成。



■ 完成図


実際に作成するファイルは MY_Loader.php, MY_Model.php, orm_helper.php の3つです。
モデルファイルは自動で作成されます。
MY_Controllerはこちらのページを参照してください。


■ 開発環境

Windows + WAMP + CodeIgniter 2.1.3 を使用しました。
$config['base_url'] は http://localhost/CodeIgniter_2.1.3/ になります。


■ データテーブル作成

コードを始める前にサンプル用のテーブルを作成します。

CREATE TABLE sample (
  id int(11) NOT NULL AUTO_INCREMENT,
  field1 varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  field2 varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

テーブル名がそのままモデルのファイル名、およびクラス名になるので、コントローラに利用する名称は避けるようにしてください。


■ モデル自動生成ヘルパの作成

たいていのORMだとデータベースに追加・変更・削除が発生した場合に自分でORM用のファイルを変更しなければならないですが、面倒なのでデータベースからモデルファイルを自動で作成する簡単なヘルパを作ります。

/application/helpers/orm_helper.php
<?php
/**
* Object-relational mapping (ORM) file generator
* 
* Generate folloing files 
* /modles/--database table name--.php
* /models/basemodels/base--database table name--.php
*/
function generate_models()
{
    $ci =& get_instance();
    $tables = $ci->db->list_tables();
    
    foreach($tables as $table)
    {
        $res = $ci->db->query('DESCRIBE `'.$table.'`');
        
        $primary = FALSE;
        $data = '<?php // '.$table.' table mapping'.PHP_EOL; 
        $data .= 'class Base'.ucfirst($table).' extends MY_Model'.PHP_EOL;
        $data .= '{'.PHP_EOL;
        foreach($res->result() as $row)
        {
            $data .= "\tvar $".$row->Field.";".PHP_EOL;
            if($row->Key == 'PRI')
                $primary = $row->Field;
        }
        
        if($primary)
            $data .= "\t"."var \$primary = '".$primary."';".PHP_EOL;
        else
            $data .= "\t"."var \$primary = FALSE;".PHP_EOL;

        $data .= "".PHP_EOL;
        $data .= "\tfunction __construct(\$table=null)".PHP_EOL;
        $data .= "\t{".PHP_EOL;
        $data .= "\t\tparent::__construct(\$table);".PHP_EOL;
        $data .= "\t}".PHP_EOL;
        
        $data .= '}';
        
        $base_model_path = CSTPATH.'models/BaseModels/';
        if( ! file_exists($base_model_path)) mkdir($base_model_path);
        // generate base model files
        file_put_contents($base_model_path.'Base'.ucfirst($table).EXT, $data);
        
        // check general model files
        if( ! file_exists(CSTPATH.'models/'.$table.EXT))
        {
            $data = '<?php'.PHP_EOL; 
            $data .= 'class '.ucfirst($table).' extends Base'.ucfirst($table).PHP_EOL;
            $data .= '{'.PHP_EOL;
            $data .= '}'.PHP_EOL;
            file_put_contents(CSTPATH.'models/'.$table.EXT, $data);
        }
    }
}

このヘルパは実行すると1つのデータテーブルから2つのファイルを作成します。


■ Modelの拡張


/application/core/MY_Model.php
<?php
class MY_Model extends CI_Model
{
    var $table;
    
    function __construct($table=null)
    {
        $this->table = ($table) ? $table : get_called_class();
        log_message('debug', ucfirst($this->table) . " Class Initialized");
    }
    
    
    /**
    * find by primary key
    * 
    * @param mixed $id
    * @return class object or FALSE
    */
    public function find($pk)
    {
        $ci =& get_instance();
        $ci->db->where($this->primary, $pk);
        $q = $ci->db->get($this->table);
        if($q->num_rows())
        {
            $array = $q->row_array();
            foreach($array as $key => $value)
            {
                $this->$key = $value;
            }
            // return object
            return $this;
        }
        else return FALSE;
    }
    
    
    public function save()
    {
        $ci =& get_instance();
        $primary = $this->primary;
        $table = $this->table;
        // temporary unset values to run query
        unset($this->primary);
        unset($this->table);
        if($where = $this->$primary)
        {   // update row
            $ci->db->where($primary, $where);
            $ci->db->update($table, $this);
        }
        else
        {   // insert new row
            $ci->db->set($this);
            $ci->db->insert($table);
        }
        
        // re-set value and return obj
        $this->primary = $primary;
        $this->table = $table;
        return $this;
    }    
}

$this->load->model('sample') でモデルをロードすると $this->sample が利用できるようになります。
$sample = new Sample(); でも良かったんですが、できるだけCodeIgniterの書式に沿った書き方をしたかったのでこうなりました。


■ Loaderの拡張

/application/models/BaseModels/Base--Data Table--.php が存在する場合に読み込む条件文を83-85行目に追加するだけです。

/application/core/MY_Loader.php
<?php
class MY_Loader extends CI_Loader
{
    /**
     * Model Loader
     *
     * This function lets users load and instantiate models.
     *
     * @access    public
     * @param    string    the name of the class
     * @param    string    name for the model
     * @param    bool    database connection
     * @return    void
     */
    function model($model, $name = '', $db_conn = FALSE)
    {
        if (is_array($model))
        {
            foreach ($model as $babe)
            {
                $this->model($babe);
            }
            return;
        }

        if ($model == '')
        {
            return;
        }

        $path = '';

        // Is the model in a sub-folder? If so, parse out the filename and path.
        if (($last_slash = strrpos($model, '/')) !== FALSE)
        {
            // The path is in front of the last slash
            $path = substr($model, 0, $last_slash + 1);

            // And the model name behind it
            $model = substr($model, $last_slash + 1);
        }

        if ($name == '')
        {
            $name = $model;
        }

        if (in_array($name, $this->_ci_models, TRUE))
        {
            return;
        }

        $CI =& get_instance();
        if (isset($CI->$name))
        {
            show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
        }

        $model = strtolower($model);

        foreach ($this->_ci_model_paths as $mod_path)
        {
            if ( ! file_exists($mod_path.'models/'.$path.$model.EXT))
            {
                continue;
            }

            if ($db_conn !== FALSE AND ! class_exists('DB'))
            {
                if ($db_conn === TRUE)
                {
                    $db_conn = '';
                }

                $CI->load->database($db_conn, FALSE, TRUE);
            }

            if ( ! class_exists('Model'))
            {
                load_class('Model', 'core');
            }
            
            if(file_exists($mod_path.'models/BaseModels/'.'Base'.ucfirst($model).EXT))
            {
                require_once($mod_path.'models/BaseModels/'.'Base'.ucfirst($model).EXT);
            }

            require_once($mod_path.'models/'.$path.$model.EXT);

            $class = ucfirst($model);

            $CI->$name = new $class($model);

            $this->_ci_models[] = $name;
            return;
        }

        // couldn't find the model
        show_error('Unable to locate the model you have specified: '.$model);
    }

}



■ サンプル

/application/controller/welcome.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Welcome extends MY_Controller {

 /**
  * Index Page for this controller.
  *
  * Maps to the following URL
  *   http://example.com/index.php/welcome
  * - or -  
  *   http://example.com/index.php/welcome/index
  * - or -
  * Since this controller is set as the default controller in 
  * config/routes.php, it's displayed at http://example.com/
  *
  * So any other public methods not prefixed with an underscore will
  * map to /index.php/welcome/<method_name>
  * @see http://codeigniter.com/user_guide/general/urls.html
  */
 public function index()
 {
  $this->load->view('welcome_message');
 }
    
    public function generate()
    {
        $this->load->database();
        $this->load->helper('orm');
        $this->load->helper('url');
        generate_models();
        
        redirect('/');
    }
    
    public function insert()
    {
        $this->load->database();
        $this->load->model('sample');
        
        $sample = $this->sample;
        // set data
        $sample->field1 = 'aaaaa';
        $sample->field2 = 'bbbb';
        // insert
        $sample->save();
    }
    
    public function update()
    {
        $this->load->database();
        $this->load->model('sample');
        
        // retrieve data by id = 1
        $sample = $this->sample->find(1);
        // set data
        $sample->field1 = 'cccc';
        $sample->field2 = 'bbbb';
        // update
        $sample->save();
    }
}

/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */

□ モデルファイル作成
http://localhost/CodeIgniter_2.1.3/index.php/welcome/generate

実行すると (1) /application/models/sample.php(2) /application/models/BaseModels/BaseSample.php のファイルが作成されます。

(1)は拡張用のモデルです。CodeIgniterからロードされるファイルはこちらのファイルです。
(2)がデータテーブルに対応した情報を持つ拡張用のモデル専用ファイルです。データテーブルが変更されると上書きされるのであまり手を入れないほうがいいでしょう。ファイル名やクラス名がCodeIgniterの形式に沿っていないのでCodeIgniterからは直接ロードできません。


□ insert
http://localhost/CodeIgniter_2.1.3/index.php/welcome/insert
実行するとsampleテーブルに一行データが追加されます。

□ update
http://localhost/CodeIgniter_2.1.3/index.php/welcome/update
実行すると上で追加したデータのidが1の行を変更します。


■ 最後に

ライブラリ化や機能の追加などは予定していません。
使う人が改善、拡張していって使いやすいようにしてください。(使う人が居れば、ですけど・・・)

俺自身、あまりサイズが大きくて多機能なORMは覚えるのが面倒な上、ほとんどの機能は必要なかったので簡単な拡張で済ませました。
普段使いそうな機能を追加すれば便利に使えると思います。

・・・だったらいいな(笑)

2012年11月28日

CodeIgniter + IDE

開発をする際にコード補完機能のあるIDEを使っている方もいるかと思います。
IDEにもよりますがコード補完機能がCodeIgniterを上手く補足してくれない場合には以下のようにするとコード補完機能が動くようになります。

*IDEによっては動かない場合もあります。

1. コントローラを拡張して以下のようにコメントを追加。
<?php
/**
 * @property DB_active_record $db
 * @property DB_forge $dbforge
 * @property Benchmark $benchmark
 * @property Calendar $calendar
 * @property Cart $cart
 * @property Config $config
 * @property Controller $controller
 * @property Email $email
 * @property Encrypt $encrypt
 * @property Exceptions $exceptions
 * @property Form_validation $form_validation
 * @property Ftp $ftp
 * @property Hooks $hooks
 * @property Image_lib $image_lib
 * @property Input $input
 * @property Language $language
 * @property Loader $load
 * @property Log $log
 * @property Model $model
 * @property Output $output
 * @property Pagination $pagination
 * @property Parser $parser
 * @property Profiler $profiler
 * @property Router $router
 * @property Session $session
 * @property Sha1 $sha1
 * @property Table $table
 * @property Trackback $trackback
 * @property Typography $typography
 * @property Unit_test $unit_test
 * @property Upload $upload
 * @property URI $uri
 * @property User_agent $agent
 * @property Validation $validation
 * @property Xmlrpc $xmlrpc
 * @property Xmlrpcs $xmlrpcs
 * @property Zip $zip
 * 
 * その他のライブラリ、モデルなどを以下に追加。
 * 
 */
class MY_Controller extends Controller
{
    function __construct()
    {
        parent::__construct();
    }
}

2. ページ用のコントローラは拡張したコントローラを使用する。
<?php
class Classname extends MY_Controller
{
    function __construct()
    {
        parent::__construct();
    }
}

2011年9月1日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 7

ショッピングカートだけでなく、ほとんどのサイトで設定が必要になります。
今回はその設定をファイルに保存するロジックを作ります。

設定はDBに保存して必要な時にだけ呼び出してもいいんですが、アプリケーションを作っていく過程、もしくはリリースしたアプリケーションをアップデートする時に新しい機能を付けるなど、後で設定が増えていくことも考慮するとメンテナンスを楽にするならファイルだろうとの結論に達しました。DBアクセスは極力減らした方がいいですしね。
(もちろん作る前に使うであろう全ての設定項目を考えて一切追加しないなら別ですが・・・)

コントローラ:admin/application/controllers/setting.php
<?php
class Setting extends Controller
{
    function __construct()
    {
        parent::__construct();
        if( ! _s('admin')) redirect();
    }
    
    function index()
    {
        $this->form_validation->set_error_delimiters('<span class="error">', '</span>');
        $this->form_validation->set_rules('name',_l('SHOP_NAME'),'required|trim|xss_clean');
        $this->form_validation->set_rules('url',_l('SHOP_URL'),'required|trim|xss_clean');
        $this->form_validation->set_rules('title',_l('PAGE_TITLE'),'trim|xss_clean');
        $this->form_validation->set_rules('keywords',_l('PAGE_KEYWORDS'),'trim|xss_clean');
        $this->form_validation->set_rules('desc',_l('PAGE_DESCRIPTION'),'trim|xss_clean');
        if($this->form_validation->run())
        {
            $data['i'] = $this->input->post();
            
            $config_data = $this->load->view('setting/config_template', $data, TRUE);
            file_put_contents(EXTPATH.'config/'.((defined('ENVIRONMENT'))?ENVIRONMENT:'').'/setting.php', $config_data);
            setMessage('success', _l('SUCCESS_UPDATE_SETTING'));
            redirect('setting');
        }
        
        $data['setting'] = $this->config->item('setting');
        $data['breadcrumbs'] = array(_l('HOME')=>'', _l('SETTINGS')=>'settings');
        $data['h1'] = _l('SETTINGS_SHOP');
        $this->layout->view('setting/shop', $data);
    }
}


コントローラ22行目で読み込む設定ファイルテンプレート: admin/application/views/setting/config_template.php
<?php echo '<?php'.PHP_EOL; ?>
/*
 *  Setting Updated: <?php echo date('Y-m-d H:i:s').PHP_EOL; ?>
 */
    $config['site_name']        = '<?php echo $i['name']; ?>';
    $config['site_url']         = '<?php echo $i['url']; ?>';
    $config['page_title']       = '<?php echo $i['title']; ?>';
    $config['page_keywords']    = '<?php echo $i['keywords']; ?>';
    $config['page_desc']        = '<?php echo $i['desc']; ?>';

これで設定をアップデートするたびにsetting.phpを再作成することになります。
最後にconfig/autoload.phpにsettingを追加しておけば毎回設定を読み込んでくれます。

ビューファイルは設定項目が増えたらスクリーンショットを載せたいと思います。
今回はロジックのみでご勘弁をΣ(; ̄□ ̄A

2011年8月25日

Codeigniter on fluxflex


日本人が起業したfluxflexはGithubと連動する安くて簡単なクラウド・ホスティング・サービスを目指す
http://jp.techcrunch.com/archives/20110817github-integrated-fluxflex-aims-at-making-cloud-hosting-easier-and-cheaper/
(だいぶ亀ですが・・・)現在作成中のショッピングカートをどこかでデモさせてもらえないかと探していたら、タイミングよくTechCrunchに記事が掲載されていたので試してみました。
記事が出た次の日には一時アクセスできなくなる、プライベートURLが動かないなど、まだまだ色々とこれからのサービスのようですが同じ日本人が起業したということで頑張って欲しいですね!

fluxflexの構成がApache+FastCGIの組み合わせで、index.phpをURLから削除して動作させるのに少し苦労したので、メモしておきます。

■ .htaccessを使ってindex.phpをURLから削除する on fluxflex
コンフィグのuri_protocolをREQUEST_URIに変更
code/config.php
$config['uri_protocol'] = 'REQUEST_URI';

.htaccessにRewriteBaseを追加(2行目)。
.htaccess
RewriteEngine on
RewriteBase /
RewriteCond $1 !^(index\.php|robots\.txt|favicon\.ico)
RewriteRule ^(.*)$ /index.php?/-- default controller --$1 [L]
そして最後にRewriteRuleにCodeigniterのdefault_controllerを指定して動作させることができました。
(一定の条件下では指定しなくても動作するようですが、指定した方が確実に動きます。)


fluxflexが安定稼動し、ショッピングカーとがもう少し見れるようになったらデモ用のURLをこのブログで公開します(^_^)

2011年8月19日

Codeigniter と オートロード(Autoload in PHP5)

※注:この記事はCodeigniter付属のautoloadに関するものではありません。

PHP5にはクラスのオートローディングという便利な関数(function __autoload())があります。
未定義のクラス/インターフェイスを使用しようとした時に 自動的にコールされる __autoload 関数を定義することができます。 この関数をコールすることにより、 スクリプトエンジンは、PHPがエラーで止まる前にクラスをロードする最後の チャンスを与えます。
引用元:php.net
これを使ってモデルを呼べれば楽なんですよね。そうすると
$this->load->model('model-name');
$this->model-name->function();
という書き方から以下のように普通のPHP5の書き方に変えられる。
$model = new Model-name;
$model->function();

そこで軽く調査してみたんですが、どうやら以下のサイトのような方法が多数散見されました。
6 CodeIgniter Hacks for the Masters
http://net.tutsplus.com/tutorials/php/6-codeigniter-hacks-for-the-masters/
ほうほう、config/config.phpの最後に__autoload()を入れるとな。

・・・いやいやいや、これダメだろ(゜Д゜) ??
config.phpの最後になんか入れたらログとかベンチマークとか全部こっちいっちゃうんじゃ?
ということで念のためテスト。config.phpの最後にコピーしてlog_messageで何をロードしようとしてるかチェック。

config/config.php
function __autoload($class)
{
    log_message('debug', 'Trying to load class: '.$class);
    if(file_exists(EXTPATH."models/".strtolower($class).EXT))
    {
        include_once(EXTPATH."models/".strtolower($class).EXT);  
    }
}


■ 結果

思った通り。load_class()で呼んでるものは全部オートロードに行っちゃう。この方法は採用しちゃダメな方法です。

それならどうすればいいのか?
正解はspl_autoload_registerを使う、です(断言しちゃったけど大丈夫かな?w)

オートローディングを追加するなら、ヘルパにしてautoload.phpに追加するのが一番簡単でいいんじゃないでしょうか。
(個人的にはファイルが増えるの嫌なのでLoader.phpにstaticメソッドを作ってcore/Controller.phpの最後に追加してますが)

■ spl_autoload_registerをコールするヘルパ
spl_autoload_register — 指定した関数を __autoload() の実装として登録する
http://nz.php.net/manual/ja/function.spl-autoload-register.php
引用元:php.net
サンプルヘルパ: spl_autoload_helper.php
<?php
/**
 * SAMPLE SPL Autoload Helper
 * ファイル名、メソッド名は適宜修正してください。
 */
 
function sample_loader($class) 
{
	if(file_exists(APPPATH."models/".strtolower($class).EXT))
	{
		log_message('debug', 'Load '.$class.' models in php5 style');
		include_once(APPPATH."models/".strtolower($class).EXT);  
	}
}
 
spl_autoload_register('sample_loader');
上記ではモデルだけ追加してますが、ライブラリもヘルパも追加することが可能です。
$this->load->model(~~~) とか面倒な人向けの方法でした。

2011年8月16日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 6

今回はユーザ管理です。
ユーザの一覧表示、新規作成(追加)、編集、最後に削除です。
苦手なjavascriptで手間取って時間かかりました( ̄Д ̄;;


■ File Tree


■ コントローラ:User
admin/application/controllers/user.php
<?php
class User extends Controller
{
    function __construct()
    {
        parent::__construct();
        if( ! _s('admin')) redirect();
        $this->load->model('users_model', 'usersdb');
    }
    
    function index()
    {
        $this->accounts();
    }
    
    function accounts($page=0)
    {
        $this->form_validation->set_rules('delete', '', 'isArray');
        if($this->form_validation->run())
        {
            $this->usersdb->delete_array($this->input->post('delete'));
        }
        
        $data['breadcrumbs'] = array(_l('HOME')=>'', _l('USERLIST')=>'user');
        $data['h1'] = _l('USERLIST');
        $data['all'] = $this->usersdb->all($page);
        $this->layout->view('user/accounts', $data);
    }
    
    function create()
    {
        $this->form_validation->set_error_delimiters('<span class="error">', '</span>');
        $this->form_validation->set_rules('email',_l('EMAIL'),'required|valid_email|email_exist');
        $this->form_validation->set_rules('firstname',_l('FIRSTNAME'),'required|min_length[2]');
        $this->form_validation->set_rules('lastname',_l('LASTNAME'),'required|min_length[2]');
        $this->form_validation->set_rules('passwd',_l('PASSWORD'),'required|min_length[6]|matches[passwdconf]');
        if($this->form_validation->run())
        {   // insert into db
            $data = array(
                'email'     => $this->input->post('email'),
                'password'  => $this->input->post('passwd'),
                'firstname' => $this->input->post('firstname'),
                'lastname'  => $this->input->post('lastname'),
                'status'    => $this->input->post('status')
            );
            
            $this->usersdb->newuser($data);
            
            redirect('user');
        }

        $data['breadcrumbs'] = array(_l('HOME')=>'', _l('USERLIST')=>'user', _l('CREATE_USER')=>'user/create');
        $data['h1'] = _l('CREATE_USER');
        $this->layout->view('user/create', $data);
    }
    
    function edit($id)
    {   // just in case
        if($user = $this->usersdb->byId($id))
        {
            $this->form_validation->set_error_delimiters('<span class="error">', '</span>');
            $this->form_validation->set_rules('email',_l('EMAIL'),'required|valid_email|email_exist['.$id.']');
            $this->form_validation->set_rules('firstname',_l('FIRSTNAME'),'required|min_length[2]');
            $this->form_validation->set_rules('lastname',_l('LASTNAME'),'required|min_length[2]');
            if($this->input->post('passwd')) $this->form_validation->set_rules('passwd',_l('PASSWORD'),'required|min_length[6]|matches[passwdconf]');

            if($this->form_validation->run())
            {   // update user info
                $data['email'] = $this->input->post('email');
                $data['firstname'] = $this->input->post('firstname');
                $data['lastname'] = $this->input->post('lastname');
                $data['status'] = $this->input->post('status');
                if($this->input->post('passwd')) $data['password'] = $this->input->post('password');
                
                $this->usersdb->update($user, $data);
                
                redirect('user');
            }

            $data['breadcrumbs'] = array(_l('HOME')=>'', _l('USERLIST')=>'user', _l('EDIT_USER')=>'user/edit');
            $data['h1'] = _l('EDIT_USER');
            $data['user'] = $user;
            $this->layout->view('user/edit', $data);
        }
        else redirect();
    }
}
□ メソッド
index ( accounts )で一覧表示と削除。
create で新規ユーザ作成
edit で編集しています。

■ モデル:Users_model.php
extension/models/users_model.php
function newuser($data)
    {
        $data['hash'] = $this->auth->_generate_hash();
        $data['password'] = $this->auth->_encode($data['password'], $data['hash']);
        $this->db->insert($this->table, $data);
        setMessage('success', _l('SUCCESS_CREATE_USER'));
    }
    
    function update($obj, $data)
    {
        if(array_key_exists('password', $data)) $data['password'] = $this->auth->_encode($data['password'], $obj->hash);
        $this->db->where('id', $obj->id);
        $this->db->update($this->table, $data);
        setMessage('success', _l('SUCCESS_UPDATE_USER'));
    }
ユーザ追加用とアップデート用のメソッドを追加。

■ Form_validationライブラリにルール追加
extension/libraries/MY_Form_validation.php
<?php
class MY_Form_validation extends Form_validation
{
    function __construct()
    {
        parent::__construct();
    }
    
    function email_exist($email, $id=FALSE)
    {
        $this->CI->form_validation->set_message('email_exist', $this->CI->lang->line('in_use'));
        $this->CI->load->model('users_model', 'usersdb');
        return ($this->CI->usersdb->exist($email, $id)) ? FALSE : TRUE;
    }
    
    function isArray($arr)
    {
        $this->CI->form_validation->set_message('isArray', $this->CI->lang->line('is_array'));
        return (is_array($arr) && count($arr) > 0) ? TRUE : FALSE;
    }
}

■ ビュー:一覧表示&削除
admin/application/views/user/accounts.php
<div class="buttons">
<button onclick="javascript:location.href = '<?php echo base_url('user/create'); ?>';"><?php echo _l('CREATE_USER'); ?></button>
<button onclick="confirmDelSelected();"><?php echo _l('DELETE_SELECTED'); ?></button>
</div>
<?php echo form_open(uri_string()); ?>
<?php if($all): ?>
<table class="list">
<tr>
    <th><input type="checkbox" onclick="applyToAll(this);" /></th>
    <th><?php echo _l('FULLNAME'); ?></th>
    <th><?php echo _l('EMAIL'); ?></th>
<?php /*    <th><?php echo _l('ROLE'); ?></th> */ ?>
    <th><?php echo _l('STATUS'); ?></th>
    <th><?php echo _l('ACTION'); ?></th>
</tr>
<?php foreach($all as $a): ?>
<tr>
    <td><input type="checkbox" name="delete[]" value="<?php echo $a->id; ?>"<?php if($a->id==1): ?> disabled="disabled"<?php endif; ?>></td>
    <td><?php echo $a->firstname.' '.$a->lastname; ?></td>
    <td><?php echo $a->email; ?></td>
<?php /*    <td><?php echo $a->role; ?></td> */ ?>
    <td><?php echo ($a->status) ? _l('ACTIVE') : _l('INACTIVE') ; ?></td>
    <td>
        <a href="<?php echo base_url('user/edit/'.$a->id); ?>"><?php echo _l('EDIT'); ?></a>
    </td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<?php echo form_close(); ?>

<script type="text/javascript">
function confirmDelSelected() {
    var c = 0;            
    $(":checkbox").each(function(){
        if($(this).attr('checked')) c++;
    })
    if(c > 0) { 
        if(confirm("<?php echo _l('CONFIRM_DELETE_SELECTED'); ?>")) $('form').submit();
    }
    else { alert("<?php echo _l('ALERT_PLZ_SELECT'); ?>"); }
}
</script>



全くスタイルしてない画面ですが(苦)
後でユーザレベル(タイプ)なんかを付け加えることになるでしょう。

削除する時には確認用のポップアップが表示されます。



■ ビュー:新規作成
admin/application/views/user/create.php
<?php echo form_open(uri_string()); ?>
<input type="button" value="<?php echo _l('CANCEL'); ?>" onclick="javascript:location.href = '<?php echo base_url('user'); ?>';" tabindex="9" />

<h2><?php echo _l('USER_DETAILS'); ?></h2>
<dl class="horizontal">
    <dt><?php echo _l('EMAIL'); ?></dt>
    <dd><input class="field" id="email" type="email" name="email" value="<?php echo set_value('email'); ?>" tabindex="1" /><?php echo form_error('email'); ?></dd>
    <dt><?php echo _l('LASTNAME'); ?></dt>
    <dd><input class="field" id="lastname" type="text" name="lastname" value="<?php echo set_value('lastname'); ?>" tabindex="2" /><?php echo form_error('lastname'); ?></dd>
    <dt><?php echo _l('FIRSTNAME'); ?></dt>
    <dd><input class="field" id="firstname" type="text" name="firstname" value="<?php echo set_value('firstname'); ?>" tabindex="3" /><?php echo form_error('firstname'); ?></dd>
    <dt><?php echo _l('PASSWORD'); ?></dt>
    <dd><input class="field" id="passwd" type="password" name="passwd" value="" tabindex="4" /><?php echo form_error('passwd'); ?></dd>
    <dt><?php echo _l('PASSWORDCONF'); ?></dt>
    <dd><input class="field" id="passwdconf" type="password" name="passwdconf" value="" tabindex="5" /></dd>
    <dt><?php echo _l('STATUS'); ?></dt>
    <dd>
        <select name="status" class="field" tabindex="6">
            <option value="1"><?php echo _l('ACTIVE'); ?></option>
            <option value="0"><?php echo _l('INACTIVE'); ?></option>
        </select>
    </dd>
    
    <dd><input type="submit" value="<?php echo _l('SAVE'); ?>" onclick="return check(['email','lastname','firstname','passwd','passwdconf']);" tabindex="7" /> <input type="reset" value="<?php echo _l('RESET'); ?>" tabindex="8" /></dd>
</dl>
<?php echo form_close(); ?>



javascriptは非常に簡単なチェックだけですが、javascriptとphpの両方で入力チェックしてます。
入力しないとこんな感じにハイライトされます。




■ ビュー:編集
admin/application/views/user/edit.php
<?php echo form_open(uri_string()); ?>
<input type="button" value="<?php echo _l('CANCEL'); ?>" onclick="javascript:location.href = '<?php echo base_url('user'); ?>';" tabindex="9" />

<h2><?php echo _l('USER_DETAILS'); ?></h2>
<dl class="horizontal">
    <dt><?php echo _l('EMAIL'); ?></dt>
    <dd><input class="field" id="email" type="email" name="email" value="<?php echo $user->email; ?>" tabindex="1" /><?php echo form_error('email'); ?></dd>
    <dt><?php echo _l('LASTNAME'); ?></dt>
    <dd><input class="field" id="lastname" type="text" name="lastname" value="<?php echo $user->lastname; ?>" tabindex="2" /><?php echo form_error('lastname'); ?></dd>
    <dt><?php echo _l('FIRSTNAME'); ?></dt>
    <dd><input class="field" id="firstname" type="text" name="firstname" value="<?php echo $user->firstname; ?>" tabindex="3" /><?php echo form_error('firstname'); ?></dd>
    <dt><?php echo _l('PASSWORD'); ?></dt>
    <dd><input class="field" id="passwd" type="password" name="passwd" value="" tabindex="4" /><?php echo form_error('passwd'); ?></dd>
    <dt><?php echo _l('PASSWORDCONF'); ?></dt>
    <dd><input class="field" id="passwdconf" type="password" name="passwdconf" value="" tabindex="5" /></dd>
    <dt><?php echo _l('STATUS'); ?></dt>
    <dd>
        <select name="status" class="field" tabindex="6">
            <option value="1"<?php if($user->status==1): ?> selected="selected"<?php endif; ?>><?php echo _l('ACTIVE'); ?></option>
            <option value="0"<?php if($user->status==0): ?> selected="selected"<?php endif; ?>><?php echo _l('INACTIVE'); ?></option>
        </select>
    </dd>
    
    <dd><input type="submit" value="<?php echo _l('SAVE'); ?>" onclick="return check(['email','lastname','firstname']);" tabindex="7" /> <input type="reset" value="<?php echo _l('RESET'); ?>" tabindex="8" /></dd>
</dl>
<?php echo form_close(); ?>



編集画面も似たようなものです。パスワードが入力されてない場合はスルーします。
パスワードのエラーはphpでのみ表示。javascriptは苦手・・・


だいぶ長くなってしまったので、今日はここまでにします。

2011年8月11日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 5

前回ユーザ登録やりますと言って実際作り始めたんですが①ユーザ一覧表示②ユーザ登録ボタンをクリックしたら登録画面という流れを考えると、ユーザ一覧表示した時にナビを表示する必要あるんじゃ・・・

ということでユーザ登録の前にナビ用のパンくずリストを作ります。


■ パンくずリスト( Breadcrumb )
まずパンくずHTMLを返すメソッドをヘルパーに作成。
extension/helpers/html_helpers.php
<?php
function breadcrumb($array)
{
    $count = count($array); $i = 1;
    $html = '<div id="breadcrumb"><ul>';
    foreach($array as $k=>$v)
    {
        $class = (empty($v)) ? ' class="home"' : '';
        if($i != $count)
            $html .= '<li><a href="'.base_url($v).'"'.$class.'>'.$k.'</a></li>';
        else    // no link for the last one
            $html .= '<li class="last"><span>'.$k.'</span></li>';
        $i++;
    }
    $html .= '</ul></div>';
    
    return $html;
}

コントローラーにパンくず用の配列を作成。
admin/application/controllers/users.php
<?php
class User extends Controller
{
    function __construct()
    {
        parent::__construct();
        if( ! _s('admin')) redirect();
    }
    
    function index()
    {
        $this->accounts();
    }
    
    function accounts($page=0)
    {
        $data['breadcrumbs'] = array(_l('HOME')=>'', _l('USERLIST')=>'admin/user');
        $this->layout->view('user/accounts', $data);
    }
}

レイアウトにパンくず表示ラインを追加
admin/application/views/_layouts/main.php
<?php if(isset($breadcrumbs) && is_array($breadcrumbs)) echo breadcrumb($breadcrumbs); ?>


見た目はAppleのようなパンくずリストにしてみました。




■ 最後に
この方法だとパンくずを表示するなら全てのメソッド内に$data['breadcrumbs']を追加しなければいけないんですよね。
他に良いやり方を思いつかなかったのですが、正直このパンくずリストあまりいい方法ではないと思います。
「こうしたほうが良いよ~」とアイデアのある方は是非アドバイスください。

2011年8月10日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 4

前回フロントエンドとバックエンドを分けたので、そこに認証機能をつけます。




■ ユーザに関する考察
ショッピングカートにはサイトの管理者と登録ユーザという2種類のユーザがいると思います。
サイトを運営するのは個人であったり会社であったりしますが、管理者が1人じゃないこともあるでしょう。そう考えると登録ユーザ(お客さん)と管理ユーザはわけたほうが良いかもしれません。

そこで登録ユーザをCustomer、管理ユーザをUserと位置づけ開発を続けていきたいと思います。


■ Usersテーブル作成
まず管理ユーザ用のDBテーブルを作成します。
(とりあえず現在のところは最低限必要な情報で構成しています。)

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `firstname` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `lastname` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `status` tinyint(4) NOT NULL,
  `role` int(11) NOT NULL,
  `hash` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
  `lastlogin` timestamp NULL DEFAULT NULL,
  `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;



■ Authライブラリ作成
Codeigniterでは有名(?)なDX Authなどのライブラリの使用も考慮しましたが、結局どれを使っても用途に合わせてカスタマイズしないといけないので自作します。
△要件△
- メールアドレスとパスワードで認証。ユーザ名は別途考慮。
- パスワード暗号化
- UserとCustomerの別認証

/extension/libraries/Auth.php
<?php
class Auth
{
    var $_error;

    public function __construct()
    {
        $this->ci =& get_instance();
    }
        
    function error()
    {
        return $this->_error;
    }
    
    function login($email, $passwd, $target='customer')
    {
        if($target === 'user')
        {   // load user model
            $this->ci->load->model('users_model','usersdb');
            // check if exists
            if($user = $this->ci->usersdb->exist($email))
            {   // retrieve user hash & matching up with entered password
                if($this->_encode($passwd, $user->hash) === $user->password)
                {   // update last login
                    $this->ci->usersdb->lastlogin($user->id);
                    // set admin session
                    $this->ci->session->set_userdata('admin',TRUE);
                    
                    return TRUE;
                }
                else $this->_error = _l('error_wrong_combination');
            }
            else $this->_error = _l('error_not_exist');
        }
        
        return FALSE;
    }
    
    private function _encode($passwd, $hash)
    {
        /* 暗号化スクリプト */
        
        return $passwd;
    }
}

/extension/models/users_model.php
<?php
class Users_model extends Model
{
    var $table = 'users';
    
    function __construct()
    {
        parent::__construct();
    }
    
    function exist($email)
    {
        $q = $this->db->get_where($this->table, array('email'=>$email));
        return ($q->num_rows() == 1) ? $q->row() : FALSE;
    }
    
    function lastlogin($id)
    {
        $this->db->where('id',$id);
        $this->db->update($this->table, array('lastlogin'=>date('Y-m-d H:i:s')));
    }
}



パスワードはユーザごとにハッシュを作成し、一定の法則で入力パスワードとマッチングさせてます。
法則は_encodeメソッド内に好きなように指定してください。
ユーザごとのハッシュは登録時に作成しないといけないので、それは次回に。

とりあえずのところ認証ライブラリ(Auth)はできたので、テストユーザを直接DBに作ってテストしてみます。

DBにテストユーザ追加
INSERT INTO `users` (`id`, `email`, `password`, `firstname`, `lastname`, `status`, `role`, `hash`, `lastlogin`, `updated`) VALUES
(1, 'test@test.com', '723e66f900dcb555d089050c80455331feb2b7ca', 'firstname', 'lastname', 0, 0, '5898e88516d636dbd3571c7d24550f67', '2011-08-04 10:49:04', '2011-08-04 10:49:04');


■ autoload変更
認証でデータベース、およびセッションを使うようになるのでconfig/autoload.phpを以下のように変更します。
$autoload['libraries'] = array('Auth','database','Form_validation','Session');


■ コントローラ
admin/application/controllers/login.php
<?php
class Login extends Controller
{
    function __construct()
    {
        parent::__construct();
        if(_s('admin')) redirect();
    }
    
    function index()
    {
        $this->form_validation->set_rules('email',_l('EMAIL'),'required|trim|valid_email');
        $this->form_validation->set_rules('password', _l('PASSWORD'), 'required|trim');
        if($this->form_validation->run())
        {
            $login = $this->auth->login($this->input->post('email'), $this->input->post('password'), 'user');
            if($login)  redirect();
            else $data['error'] = $this->auth->error();
        }
        else $data['error'] = validation_errors();
        
        $data['css'] = array('login');
        $data['page_title'] = _l('CONTROLPANEL');
        $this->layout->view('login', $data);
    }
}


■ ビュー
admin/application/view/login.php
<?php echo form_open(uri_string()); ?>
<div>
<h1><?php echo _l('CONTROLPANEL'); ?></h1>
<p><?php echo _l('MSG_LOGIN'); ?></p>
<dl>
    <dt><?php echo _l('EMAIL'); ?></dt>
    <dd><input type="email" name="email" value="<?php echo set_value('email'); ?>" /></dd>
    <dt><?php echo _l('PASSWORD'); ?></dt>
    <dd><input type="password" name="password" value="" /></dd>
    <dd><input type="submit" value="<?php echo _l('LOGIN'); ?>"></dd>
    <?php if(isset($error)): ?><dd><?php echo $error; ?></dd><?php endif; ?>
</dl>
</div>
<?php echo form_close(); ?>

これで準備は完了です。


■ログイン画面
どうせだったらと簡単にデザインしてみました。デザインは苦手なんですよねー(^_^;;



上で追加したユーザでログインしてみます。


うん、ちゃんと admin セッションが登録されていますね。
ログインした時に登録するべきセッションは admin だけではないですが、それは必要に応じて追加して行きたいと思います。


次回はユーザ登録をやります。

2011年7月28日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 3

テンプレート化の下地ができたので、調子に乗ってそのままバックエンドの分離に着手します。
テンプレート化はこちら


■フロントエンドとバックエンド(管理画面)の分離


一般的にフロントエンドとバックエンドはデザインが異なることが多いですし、機能的にも違ったものになります。そう考えると分離させるのはそれほど悪い考えでもないでしょう(であって欲しいw)

/admin/index.php./index.php をほぼコピーした感じです。

/admin/index.php
<?php
define('EXT', '.php');
define('FCPATH', __FILE__);
$pathinfo = pathinfo(FCPATH);
define('SELF', $pathinfo['basename']);
define('ROOT',realpath($pathinfo['dirname'].'/../').'/');
unset($pathinfo);

define('SYSPATH', ROOT.'system/');
define('EXTPATH', ROOT.'extension/');
define('APPPATH', ROOT.'admin/application/');

$f=pathinfo(__FILE__, PATHINFO_BASENAME);
if (!is_dir(SYSPATH))  exit("Your system folder path does not appear to be set correctly. Please open the following file and correct this: ".$f);
if (!is_dir(APPPATH))   exit("Your application folder path does not appear to be set correctly. Please open the following file and correct this: ".$f);
if (!is_dir(EXTPATH)) exit("Your extension folder path does not appear to be set correctly. Please open the following file and correct this: ".$f);

define('ENVIRONMENT', 'development');

if (defined('ENVIRONMENT'))
{
    switch (ENVIRONMENT)
    {
        case 'development':
            error_reporting(E_ALL);
        break;
    
        case 'testing':
        case 'production':
            error_reporting(0);
        break;

        default:
            exit('The application environment is not set correctly.');
    }
}

require(SYSPATH.'core/Bootstrap'.EXT);


ここで問題になってしまったのがLayoutライブラリです。
./index.phpTEMPATHを設定していたため$this->layout->view()が全てTEMPATHに向いてしまっていました。

そこで両方のindex.phpにADMIN定数を設定し、ADMIN=TRUEの場合にはTEMPATHに向かないように/extension/core/Layout.phpを変更しました。
(毎回コントローラで$this->layout->set('admin');とやるのは無駄ですからね…)

./indexphp
define('ENVIRONMENT', 'development')直前

define('ADMIN', FALSE);

/admin/indexphp
define('ENVIRONMENT', 'development')直前

define('ADMIN', TRUE);

/extension/core/Layout.php
18行目

if(! ADMIN) $load->set_view_path(TEMPATH.$template.'/');


■ コントローラの設定
admin/application/controllers/home.php
<?php
class Home extends Controller
{
    function index()
    {
        $this->layout->view('home');
    }
}


■ ビューの設定
admin/application/views/home.php
this is admin directory - <?php echo __FILE__; ?>


■ レイアウトの設定
admin/application/views/_layout/main.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Admin Template</title>
</head>
<body>

<?php echo $contents; ?>

<p><br />Page rendered in {elapsed_time} seconds</p>

</body>
</html>


■ てすと
http://localhost/lsc/admin/ にアクセスしてみます。


ちゃんとアクセスできてます。大丈夫そうです。
無事に分けられたところで、次はアクセス制御かな?

2011年7月25日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 2

さてインストールが終わったので目的に合わせて色々と変更していきます。
#1 インストールはこちらからどうぞ。



■ テンプレート化
デザインを拡張したり、変更したりできる機能は人に使ってもらうことを考えると外せないですよね。
もちろん、簡単に拡張できれば使ってくれる人も多くなるでしょうし。


そこで初期設定では application/views に設定されているview用のディレクトリを templates ディレクトリに移します。HTML/CSSなどのデザイン部分は1つにまとめられて楽になるんじゃないかな。(ダメそうなら後で変更しますw)



後で変更できるようにindex.phpTEMPATHを追加。

define('TEMPATH', ROOT.'templates/');


■ Layoutライブラリ
当然templatesディレクトリに移しただけでは使えないので、ライブラリを1つ追加します。

extension/core/Layout.php
<?php
class Layout 
{
    var $layout;
    
    function __construct()
    {
        $this->layout = config_item('layout_default_file');
        log_message('debug', 'Layout Class Initialized');
    }
    
    function set($layout) { $this->layout = $layout; }
    
    function view($view = '' , $data = array(), $template = 'default', $return = FALSE)
    {
        $load =& load_class('Loader','core');
        // set template path as view path if not admin
        if($template !== 'admin') $load->set_view_path(TEMPATH.$template.'/');
        // load contetns in side of the layout
        $view_data['contents'] = $load->view($view, $data, TRUE);
        // load layout directory config
        $this->layout = config_item('layout_directory').$this->layout;

        // then finaly load layout
        return $load->view($this->layout, $view_data, $return);
    }
}


ライブラリ内で使われている設定をconfig/config.phpに2つ追加。
$config['layout_default_file']  = 'main';
$config['layout_directory']     = '_layouts/';
1つ目はLayoutライブラリがロードされた時にレイアウトファイルが指定されなかった場合に自動的に読み込まれるファイル名を指定します。
2つ目はディレクトリを分けたい際に指定できます。空欄も可。


■ Loaderクラス拡張
ビューファイルのパスを指定するのにLoaderクラスを拡張します。

extension/core/MY_Loader.php
<?php
class MY_Loader extends Loader
{
    /**
     * set view file path
     *
     * This function sets the location of view file.
     *
     * @access    public
     */
    public function set_view_path($path, $absolute=FALSE)
    {
        $this->_ci_view_path = ($absolute) ? ROOT.$path : $path;
    }
}
これで_ci_view_pathはtemplatesディレクトリに向きます。


■ Layoutライブラリ読み込み
最後にライブラリを読み込みます。
普通にconfig/autoload.phpに追加でもいいんですが、Layoutライブラリは常に使うことになるし、1行だけなのでsystem/core/Controller.phpに書き込んじゃいました。

$this->layout =& load_class('Layout', 'core');

Codeigniterのアップデートの時に面倒とか、わからない人はconfig/autoload.phpに追加してくださいね。

$autoload['libraries'] = array('Layout');



■ てすと

コントローラ:application/controllers/home.php
<?php
class Home extends Controller
{
    function __construct()
    {
        parent::__construct();
    }
    
    function index()
    {
        $this->layout->view('home/index');
    }
}

ビュー:templates/default/home/index.php
<?php echo __FILE__; ?>


結果:


大丈夫そうです(^_^v
これでテンプレート化の下地ができまた。

2011年7月24日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 1

■ 環境設定&インストール

本来なら開発は本番環境と同じ状態でやるのが一番良いのですが、ネットがない環境でも作業ができるようにローカルに開発環境をセットアップします。

まずWampをダウンロードしてDドライブにインストール。インストールする場所はご自由に。
www.wampserver.com

D:\wamp\www
がlocalhost(以下、ローカル)になります。


次にCodeigniterをダウンロード。
www.codeigniter.com/downloads

ダウンロードしたファイルを解凍してローカル配下に設置。
同梱されているuser_guideは開発自体には必要ないので別の場所に保管します。

開発ディレクトリ:
D:\wamp\www\lsc

マニュアルディレクトリ:
D:\wamp\www\manual\ci


とりあえずは、これで環境設定とインストールできました。


■ 微調整

初期設定でCodeigniterはsystemとapplicationの2つのディレクトリに別れてます。
これを少しだけ以下のように変更しました。


変更の理由は後日記載します。

それに伴い、index.phpも多少変更。

<?php
/*
 *  Constants: Core Application Constants
 *  EXT - The file extension.  Typically ".php"
 *  FCPATH - The full server path to THIS file
 *  SELF - The name of THIS file (typically "index.php")
 *  ROOT - ROOT direcotry
 *  SYSPATH - The full server path to the "system" folder
 *  APPPATH         - The full server path to the "application" folder
 *  EXTPATH- The full server path to the "extension" folder
 */

define('EXT', '.php');
define('FCPATH', __FILE__);
$pathinfo = pathinfo(FCPATH);
define('SELF', $pathinfo['basename']);
define('ROOT',realpath($pathinfo['dirname'].'/').'/');
unset($pathinfo);
define('SYSPATH', ROOT.'system/');
define('EXTPATH', ROOT.'extension/');
define('APPPATH', ROOT.'application/');

$f=pathinfo(__FILE__, PATHINFO_BASENAME);
if (!is_dir(SYSPATH)) exit("Your system folder path does not appear to be set correctly. Please open the following file and correct this: ".$f);
if (!is_dir(APPPATH)) exit("Your application folder path does not appear to be set correctly. Please open the following file and correct this: ".$f);
if (!is_dir(EXTPATH)) exit("Your extension folder path does not appear to be set correctly. Please open the following file and correct this: ".$f);

define('ENVIRONMENT', 'development');

if (defined('ENVIRONMENT'))
{
    switch (ENVIRONMENT)
    {
        case 'development':
            error_reporting(E_ALL);
        break;
   
        case 'testing':
        case 'production':
            error_reporting(0);
        break;

        default:
            exit('The application environment is not set correctly.');
    }
}

require(SYSPATH.'core/Bootstrap'.EXT);


よく見たらほとんど全部変えてた(笑)
わからない人は触らないほうがいいかもしれませんねー。


変更がちゃんと動いてるかhttp://localhost/lsc/にアクセスして確認。




大丈夫そう。
それじゃあ次回からガリガリ開発です!

2011年7月22日

Codeigniterを使ってショッピングカートをゼロから作ってみよう。 # 0

仕事柄毎日コード書いてるけど、色々と思うこともあるので日記風に書き残しておこうかと思います。

とは言えだ、ただの日記じゃ芸がないし自分が飽きそうなので企画っぽくしようかと。
Google先生に聞いてみたけど見当たらなかったのと慣れていることもあるので企画内容決定。


Codeigniterを使ってショッピングカートをゼロから作ってみよう。


それじゃ企画の概要。
- CodeigniterとjQueryをメインにiscなみのショッピングカートを作る。
- 原則としてコードは恥も外聞もなく公開。まぁでも徹底入門よりはマシだと思います、はいw
- 既に企画内容が途方もなく大きいので、いつ終わるかは不明。
- 途中で投げ出すこともあるでしょう。・・・っつーか、投げ出す気満々なんであまり期待しないでください(苦)
- 投げ出さずにできたら商用化。(あくまでも予定)

以下、仕様。
コア部分:
- カート機能
- ユーザ機能
- 管理ページ
- 製品管理系

準コア部分:
- 決済系(Paypalとか色々)
- 税金系
- 配送系
- 在庫管理系
- 返品受付機能

デザイン部分:
- テンプレート(スキン)機能

余力があれば:
- B2B機能
- SEO系
- プロモーション機能
- API


6ヶ月~1年くらいあればある程度まともなのできるかな?
機能はこのブログを読んでくれる人がいて、要望出してくれたりアドバイスくれたりしたら追加されるかもしれません。

投げ出す気は満々ですが、投げ出さないように励ましつつ見守ってくれれば幸いです。

んじゃ、始めますか。