kohana開発日記(xajax前提のpagenation)

kohana付属のpagenationは、ページ選択して遷移するURLの部分でxajaxと相性が良くないことに気がつきました。そこで、少し機能を落として、自前で改造しました。

<?php defined('SYSPATH') or die('No direct script access.');
/**
 * Pagination Module の代替
 * 戻りURLを自由に設定できないので自作した
 */
class Pagenavi {

	protected $pagenavi_method = 'default_method';
	protected $auto_hide = TRUE;
	protected $total_items;
	protected $offset;
	protected $items_per_page = 20;
	protected $total_pages;
	protected $maximum_pages = 20;

    protected $previous_page;
	protected $current_page = 1;
	protected $next_page;

	/**
	 * Factory.
	 *
	 * @param   array   configuration
	 * @return  object  Pagelink
	 */
	public static function factory(array $config = array()) {
		return new Pagenavi($config);
	}

	/**
	 * Constructor.
	 *
	 * @param   array  configuration
	 * @return  void
	 */
	public function __construct(array $config = array()) {
        if(isset($config&#91;'pagenavi_method'&#93;))  
           $this->pagenavi_method = $config['pagenavi_method'];
        if(isset($config['auto_hide']))
           $this->auto_hide = $config['auto_hide'];
        if(isset($config['total_items']))
           $this->total_items = $config['total_items'];
        if(isset($config['items_per_page']))
           $this->items_per_page = $config['items_per_page'];
        if(isset($config['current_page']))
           $this->current_page = $config['current_page'];
        $this->recalc();
    }

    /**
	 * Recalcurate Property.
	 *
     * @param integer $current_page
	 */
	private function recalc($current_page = 1) {
        $this->total_items =  (int) max(0, $this->total_items);
        $this->items_per_page = (int) max(1, $this->items_per_page);
        $this->total_pages
            = (int) ceil($this->total_items / $this->items_per_page);
        $this->current_page 
            = (int) min(max(1, $this->current_page), 
                                           max(1, $this->total_pages));
        $this->offset
            = (int) (($this->current_page - 1) * $this->items_per_page);
        $this->previous_page
            = ($this->current_page > 1) ? $this->current_page - 1 : 1;
        $this->next_page
            = ($this->current_page < $this->total_pages) ?
                      $this->current_page + 1 : $this->total_pages;
        return $this;
	}

	/**
	 * アイテム数がゼロでなく、かつ最大ページ数に収まるか.
	 *
	 * @return  boolean   許可数以下ならTRUE
	 */
	public function pageable() {
		if($this->total_items <= 0) {
            return FALSE;
        } elseif($this->total_pages > $this->maximum_pages) {
            return FALSE;
        } else {
            return TRUE;
        }
	}

    /**
	 * 指定ページのURL.
	 *
	 * @param   integer  page number
	 * @return  string   URL
	 */
	public function page_url($page = 1) {
		$page = max(1, (int) $page);
        return "{$this->pagenavi_method}({$page})";
	}

	/**
	 * previous page.
	 *
	 * @return  string   page URL
	 */
	public function previous_url() {
        return "{$this->pagenavi_method}({$this->previous_page})";
	}

  	/**
	 * next page.
	 *
	 * @return  string   page URL
	 */
	public function next_url() {
        return "{$this->pagenavi_method}({$this->next_page})";
	}

  	/**
	 * offset.
	 *
	 * @return  integer   offset
	 */
	public function offset() {
        return $this->offset;
	}

  	/**
	 * total items.
	 *
	 * @return  integer   offset
	 */
	public function total_items() {
        return $this->total_items;
	}

  	/**
	 * items per page.
	 *
	 * @return  integer   offset
	 */
	public function items_per_page() {
        return $this->items_per_page;
	}

    /**
	 * total pages.
	 *
	 * @return  integer   offset
	 */
	public function total_pages() {
        return $this->total_pages;
	}

  	/**
	 * current page.
	 *
	 * @return  integer   offset
	 */
	public function current_page() {
        return $this->current_page;
	}

  	/**
	 * ページング表示を許す最大のアイテム数.
	 *
	 * @return  integer  アイテム数
	 */
	public function maximum_items() {
        return $this->items_per_page * $this->maximum_pages;
	}

    /**
	 * viewにあてはめてページングを出力.
	 * 上限ページ数に配慮してページングを出力.
	 *
	 * @param   string  view file
	 * @return  string  HTML
	 */
	public function render($view) {
		if($this->total_items <= 0) {
            return "該当件数がゼロです。";
        } elseif($this->total_pages > $this->maximum_pages) {
            return "{$this->total_items}件が該当します。"
              . "{$this->maximum_items()}件未満なら一覧表示できます。";
        } else {
            if ($this->auto_hide == TRUE AND $this->total_pages <= 1) {
                return NULL;
            } else {
                return View::factory($view)
                          ->set('page', $this)->render();
            }
        }
	}
}

kohana開発日記(xajaxでページから値を得る)

getElementIdを使う手もありますが、xajaxで統一してみました。
xajax.$()はmethodなので注意。

view側

<?php echo Form::input('search_name', isset($search_name) ? $search_name  : '', array('id' => 'search_name')); ?>
<a href="#" onclick="xajax_search(xajax.$('search_name').value);return false;">検索</a>

Controller側

    public function ajax_search($search_name) {
        $response = new xajaxResponse();
        $response->alert($search_name);
        return $response;
    }

kohana開発日記(xjaxをインストール:リベンジ編)

Unofficial Kohana 3.0 Wiki の指示に従います。

まずはsourceforgeからSVNでxajaxをチェックアウト。
TurtoiseSVNから、指定のリポジトリ(https://xajax.svn.sourceforge.net/svnroot/xajax)につなげば、チェックアウト可能です。

xajax\trunk\xajax下のフォルダを、フォルダ毎に下記に放り込みます。

application
  modules
      vendors
        xajax
          xajax_core
          xajax_controls
          xajax_plugins

www
    media
        js
          xajax_js

application/bootstrap.php

Kohana::modules(array(
      ...
      'vendors'     =>; MODPATH.'vendors',
      ...
      ));

Controllerの基底クラス

abstract class XXX {
    protected $ajax_functions = array();
     ...
    public function after() {
	if ($this->auto_render) {
            $this->_initialize_ajax_functions();
        }
        parent::after();
    }
     ...
    protected function add_ajax_function($function) {
      array_push($this->ajax_functions, $function);
    }
     ...
    private function _initialize_ajax_functions() {
      if( isset($this->ajax_functions)
      && count($this->ajax_functions) > 0 ) {
           require_once Kohana::find_file('xajax/xajax_core', 'xajax.inc');
           $xajax = new xajax();
           $xajax->configure('javascript URI', '/media/js');
           foreach($this->ajax_functions as $function) {
                  $xajax->register(XAJAX_FUNCTION, 
            array($function, &$this, 'ajax_'.$function));
           }
           $xajax->processRequest();
           $this->template->ajax_functions = View::factory('ajax')
            ->set('ajax_functions', $xajax->getJavascript());
       }
    }

application/views/ajax.php

  <?php
  echo $ajax_functions; 
  ?>

template

  <head>
      <?php echo isset($ajax_functions)?$ajax_functions:'' ?>   
  </head>

上記でテストがうまくいきました。

kohana開発日記(xajaxをインストール)=>失敗

Unofficial Kohana 3.0 Wiki の指示に従います。

まずはxjaxを解凍してできるフォルダを、フォルダ毎に下記に放り込みます。

application
  modules
    vendors 
      xajax
        xajax_core
        xajax_controls
        xajax_plugins

www
    media
        js
          xajax_js

application/bootstrap.php

Kohana::modules(array(
      ...
      'vendors'     =&gt;; MODPATH.'vendors',     // add vendors folder
      ...
      ));

Controllerの基底クラス

abstract class XXX {
    protected $ajax_functions = array();
     ...
    public function after() {
  	    if ($this-&gt;auto_render) {
            $this-&gt;_initialize_ajax_functions();
        }
        parent::after();
    }
     ...
    protected function add_ajax_function($function) {
      if( !is_array($this-&gt;ajax_functions) ) {
          $this-&gt;ajax_functions = array();
     }
      array_push($this-&gt;ajax_functions, $function);
    }
     ...
    private function _initialize_ajax_functions() {
      if( isset($this-&gt;ajax_functions) &amp;&amp; count($this-&gt;ajax_functions) &gt; 0 ) {
          require_once Kohana::find_file('xajax_core', 'xajax.inc');
          $xajax = new xajax(Request::instance()-&gt;uri());
          foreach($this-&gt;ajax_functions as $function) {
              $xajax-&gt;register(XAJAX_FUNCTION, array($function, &amp;$this, 'ajax_'.$function));
          }
          $xajax-&gt;processRequest();
          $xajax-&gt;configure('javascript URI', Url::base() . 'media/js');
          $this-&gt;template-&gt;ajax_functions = View::factory('ajax')-&gt;set('ajax_functions', $xajax-&gt;getJavascript());
      }
    }

application/views/ajax.php

  &lt;?php
  echo $ajax_functions; 
  ?&gt;

template

  &lt;head&gt;
      &lt;?php echo isset($ajax_functions)?$ajax_functions:'' ?&gt;   
  &lt;/head&gt;

上記では、_initialize_ajax_functions中のKohana::find_fileでエラー。
xajaxの位置を modules/vendors/xajax ではなく modules/xajax にして、bootstrap.php もそれに合わせたら、Kohana::find_file自体は通った。

しかし今度はPHP例外、
ErrorException [ Strict ]: Assigning the return value of new by reference is deprecated
これは上記ページに「そうなることがあるかも」と書いてあったのを発見。後日やり直し予定。

kohana開発日記(NetBeansでエラーや警告になる部分

  • modules/userguide/views/userguide/examples/hello_world_error.php
  • modules/userguide/views/userguide/api/class.php
    DTタグをDLタグに修正
  • modules/userguide/media/css/shCore.css
    .syntaxhighlighter.printing .line.highlighted.alt2 .content の後の余計な.を削除
  • modules/userguide/media/css/kodoc.css
    border-bottom の0.2を0.2emに修正
  • system/views/profiler/starts.php
    INCLUDEされるCSSの中身を直接コピペ
  • system/views/kohana/error.php

kohana開発日記(ファイル配置)

ファイル配置

自分ひとりでの開発であり、稼働後にいろいろいじることも多いので、下記の構成にします。
アプリケーション毎にApatch再起動という面倒はありますが、アプリケーション毎の独立を図れます。
下記ではwebapp(仮称)がアプリケーションフォルダ名です。

  • webapp/ (関係ファイル一式)
  • webapp/application (kohana利用のアプリケーション本体)
  • webapp/modules (kohanaモジュール群)
  • webapp/system (kohana本体)
  • webapp/www (公開フォルダ

httpd.confを修正

  • webapp/wwwを、DocumentRootとして指定
  • webapp/wwwに対して
    Options -Indexes FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all

www/.htaccessを修正

  • 基本的にはexample.htaccessのまま
  • RewriteBase /

www/index.phpを修正

  • $application = ‘../application’;
  • $modules = ‘../modules’;
  • $system = ‘../system’;