ブログ・エス技研

当ブログは引越しをしました。10秒後に自動で転送しますが、転送されない場合は、http://blog.s-giken.net/ をご覧ください。
ブログ・エス技研 TOP  >  CakePHP 2.x

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
[ --年--月--日 --:-- ] カテゴリ:スポンサー広告 | TB(-) | CM(-)

CakePHP 2.3 Search Pluginで検索処理 その7queryを使って 日付の範囲検索

今回は、「'type' => 'query'」を使い、オリジナルの検索条件を記述して検索する方法を行います。
今回の処理は、その2(http://ssgiken.blog.fc2.com/blog-entry-31.html)をベースにしていますので、そちらもご覧ください。


本当は、「Group By句」による集計の処理をやろうかと思っていましたが、Group By + sumによる集計は、集計した項目をバーチャルフィールド(virtual fields)を使って値を取得する必要があるため(バーチャルフィールドを使わなくても値を取得できないわけではないですが)、長くなりそうなので、「'type' => 'query'」の方を先にやってみたいと思います。


「'type' => 'query'」を使うと、検索の条件を柔軟性を持って設定することができるため、もともと用意されている検索方法以外の検索方法を行いたい、と思った場合に利用できる方法です。

具体的な検索方法を考える際にあれこれ悩みましたが、あまりいいサンプルを思いつかず、今回の記事は、下記のサイトを参考にさせていただきました。
http://kamakurasoft.net/blog/?p=1479


まずは、Viewから。
Viewの Elementsに下記の項目を追加してください。

--------------(/app/View/Elements/searchForm.ctp)
    :
    :
    <dt><label>日付</label></dt>  
    <dd><?php echo $this->Form->input('start',array(
        'type'=>'date', 'dateFormat'=>'YMD', 'timeFormat'=>'NONE', 'monthNames'=>'false',
//        'label'=>'開始年月日(年-月-日)',
        'label'=>'',
        'minYear'=>2010, 'maxYear'=>date('Y') + 5,
        'selected'=>array('year'=>date('Y')-1,'month'=>date('m'),'day'=>date('d')), /*1年前*/ )) ?></dd>
    :
    :
--------------

「'label'=>'開始年月日(年-月-日)',」をコメントにしていますが、labelの設定があると入力エリアのすぐ上にラベル表示がされるためにコメントにしています。
ちなみに、labelの設定がない場合は、デフォルトの設定として項目名の「start」がラベル名として表示されます。そのため、labelを消すためには「'label'=>'',」の設定が必要なようです。


続けて、Modelです。
サンプルは開始日と終了日での設定がしてありますが、ここでは面倒なので開始日しか設定していません。

日付の項目に関して、今回の日付項目は、「start」という項目名で設定しています。その中から、日付の「年」の項目は「$data['start']['year']」として取得します。同じように「月」「日」は、「$data['start']['month']」「$data['start']['day']」として取得します。

私は、最初のうちはこのことがよく分からず、日付の項目の項目名は一つなのに、年月日のそれぞれの項目はどうやって取得したらいいのだろう、としばーらく悩んでいました。
分かってしまえば意外に簡単ではあるんですが...

--------------(/app/Model/User.php)
<?php
class User extends AppModel {
    :
    :
  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id',       'type' => 'value', 'field' => 'User.id'),
    array('name' => 'username', 'type' => 'like',  'field' => 'User.username'),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname'),
    array('name' => 'start',    'type' => 'query', 'method'=>'createSql'),
  );

  public function createSql ( $data = array () ) {
    $start = $data['start']['year'] . '-' . $data['start']['month'] . '-' . $data['start']['day'];
    $condition = array ( 'DATE(User.created) >= DATE(?)' => array($start) );
    return $condition;
  }
    :
    :
}
--------------


また、入力の値を再び設定する処理で、下記のように設定してみましたがうまくいかず、デフォルトの設定に戻ってしまいます。
こちらの設定方法については後日分かり次第改めて対応したいと思います。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {
    :
    :
  // 検索対象のフィールド設定
  public $presetVars = array(
    :
    :
    array('field' => 'start',    'type' => 'date'),
  );
    :
    :
}
--------------

どなたかわかる方、教えてくださいっ!!


【CakePHP2.3 Search Plugin検索処理 目次】
CakePHP2.3 Search Pluginで検索処理 その1設置方法
CakePHP2.3 Search Pluginで検索処理 その2表示件数を動的に変える方法
CakePHP2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHP2.3 Search Pluginで検索処理 その4前方一致検索、後方一致検索、不等号による検索、between句による範囲検索
CakePHP2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索
CakePHP2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能
CakePHP2.3 Search Pluginで検索処理 その7queryを使って 日付の範囲検索
[ 2013年09月09日 01:10 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能

今回は、検索をする際に、あらかじめソートキーを選択できるようにする処理を作っていきます。


ソートキー(ORDER BY)の設定は、その2(http://ssgiken.blog.fc2.com/blog-entry-31.html)の「limit」の設定ができさえすれば簡単に分かると思います。
また、今回の処理は、その2をベースにしていますので、そちらもご覧ください。


なぜなら、タイトルをクリックしてソートをさせた際に表示される URLを見れば「sort:User.username/direction:asc」表示されていますので、「sort」「direction」という項目名でソートをさせる項目を設定している、ということがなんとなく分かるでしょう。


まず、入力フォームです。
「表示件数」の次あたりに追加してもらえればいいと思います。
今回は、動作を検証するためのものですので、text形式で作っていますが、実際に運用する際には、プルダウンの選択式にする必要があるでしょうね。

--------------(/app/View/Elements/searchForm.ctp)
    :
    :
    <dt><label>ソート条件・キー</label></dt>  
    <dd><?php echo $this->Form->input('sort', array(  
      'type' => 'text', 'div' => false, 'label' => false ))?></dd>  
    <dt><label>ソート条件・降順昇順</label></dt>  
    <dd><?php echo $this->Form->input('direction', array(  
      'type' => 'text', 'div' => false, 'label' => false ))?></dd>  
    :
    :
--------------

続いて Modelを修正します。
こちらも「array('field' => 'sort', 'type' => 'value'),」を追加するだけです。
細かな説明は、その2の方を見てもらえると分かりやすいかと思います。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {
    :
    :
  // 検索対象のフィールド設定
  public $presetVars = array(
    array('field' => 'id',        'type' => 'value'),
    array('field' => 'username',  'type' => 'value'),
    array('field' => 'nickname',  'type' => 'value'),
    array('field' => 'limit',     'type' => 'value'),
    array('field' => 'sort',      'type' => 'value'),
    array('field' => 'direction', 'type' => 'value'),
  );
    :
    :
}
--------------

また、デフォルトでソートキーを設定したい場合は、Controllerに「'order' => array ( 'User.username' => 'desc', 'User.id' => 'desc' ),」の設定を追加しておきます。
limitの時と同じく、ここで設定してあってもソートキーの入力があった場合はそちらが優先されます。


--------------(/app/Controller/UsersController.php)
<?php
class UsersController extends AppController {  
    :
    :
    $this->paginate = array(
      'conditions' => $conditions,
      'order' => array ( 'User.username' => 'desc', 'User.id' => 'desc' ),
      'limit' => 3,
    );
    :
    :
}
--------------


【CakePHP2.3 Search Plugin検索処理 目次】
CakePHP2.3 Search Pluginで検索処理 その1設置方法
CakePHP2.3 Search Pluginで検索処理 その2表示件数を動的に変える方法
CakePHP2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHP2.3 Search Pluginで検索処理 その4前方一致検索、後方一致検索、不等号による検索、between句による範囲検索
CakePHP2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索
CakePHP2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能
CakePHP2.3 Search Pluginで検索処理 その7queryを使って 日付の範囲検索
[ 2013年09月02日 01:02 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索

今回の検索は、入力項目に複数のキーワードを入力した際に、AND検索したり、OR検索したりする検索方法です。
今回の処理は、その2(http://ssgiken.blog.fc2.com/blog-entry-31.html)をベースにしていますので、そちらもご覧ください。


CakePHPの Search Pluginでは、AND検索、OR検索の方法も簡単に実装できるように用意されています。
今回は、下記のように Modelの「nickname」に「'connectorAnd' => ' ', 'connectorOr' => ','」を追加することで、それぞれ AND検索、OR検索を実装しています。
AND検索の場合は「ー ン」の様に、OR検索の場合は「太郎,多恵子」の様に入力することでそれぞれ検索を行えます。

Googleの検索が半角スペースで区切ることで AND検索になりますので、「'connectorAnd' => ' '」としていますが、「' '(半角スペース)」と記述していある部分を好きな記号に変更することでオリジナルの区切り文字を設定することができます。

ただ、OR検索は、Googleの場合は「or」と入力することで OR検索になりますが、CakePHPのこの Search Pluginの場合は、区切り文字を 2文字以上のものを設定することができませんので、「'connectorOr' => ','」の方は「','(カンマ)」を設定しています。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
    :
    :
  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id',       'type' => 'value', 'field' => 'User.id'),
    array('name' => 'username', 'type' => 'like',  'field' => 'User.username'),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname', 'connectorAnd' => ' ', 'connectorOr' => ','),
  );
    :
    :
}
--------------


上記の方法は、検索対象が部分一致検索('type' => 'like')の場合のみ有効です。

完全一致検索('type' => 'value')の場合は、下記の様に「connectorAnd」「connectorOr」を設定してもエラーにはなりませんが、正しい検索結果は戻ってきません。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
    :
    :
    array('name' => 'id',       'type' => 'value', 'field' => 'User.id', 'connectorAnd' => ' ', 'connectorOr' => ','),
    :
    :
}
--------------

私は、このことが分からず、かなーりハマりました。エラーが起こらないために何が悪いのかが分かりにくいんですよね。

ではどうするか。
下記の様に「'type' => 'subquery'」を設定し、「searchIn」の関数を設定し、queryに編集する文字列を生成します。
subqueryを設定し、入力値を戻すだけで IN句を生成してくれるようです。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
    :
    :
  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id',       'type' => 'subquery', 'method' => 'searchIn', 'field' => 'User.id'),
    array('name' => 'username', 'type' => 'like',  'field' => 'User.username'),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname'),
  );

  function searchIn($data = array()) {
    $query = $data['id'];
    return $query;
  }
    :
    :
}
--------------

ただ、この場合、「1,2,3」の様に「,(カンマ)」で区切らないとエラーになります。
そのため、もし、入力値が数字のみと分かっている場合は、「searchIn」の関数の中身を下記の様にしてみるのもいいでしょう。
1行目で数字以外を「,」に変換し、2行目でカンマが連続している場合はカンマ一つに変換する処理を入れて、3行目、4行目で先頭と最後尾のカンマを削除しています。
これであれば、数値以外が入力されても問題はないでしょう。

--------------(/app/Model/User.php)
  function searchIn($data = array()) {
    $query = mb_ereg_replace ( '[^0-9]', ',', $data['id'] );
    $query = mb_ereg_replace ( ',+', ',', $query );
    $query = mb_ereg_replace ( '^,', '', $query );
    $query = mb_ereg_replace ( ',$', '', $query );
    return $query;
  }
--------------



その他、これを応用して、例えば、必ず表示させる情報がある場合の対応も可能です。

具体的なイメージとしては、会員サイトで会員ごとにお知らせを配信しているとします。
通常は、会員ごとに配信するので会員 IDを付与してお知らせを配信しますが、全会員に向けて一斉配信したいお知らせがあった場合に、特定の IDを付与したお知らせはすべての会員に配信したい、そんな状況を想定します。

処理の方法は、「$data['id'] .= ',20';」の行を追加するだけです。
今回は、サンプルとして「20」の IDは必ず表示させるようにしていますが、IDを 0にするといった方法でもいいと思います。(もっとスマートな書き方もありますが...)

--------------(/app/Model/User.php)
  function searchIn($data = array()) {
    $data['id'] .= ',20';
    $query = mb_ereg_replace ( '[^0-9]', ',', $data['id'] );
    $query = mb_ereg_replace ( ',+', ',', $query );
    $query = mb_ereg_replace ( '^,', '', $query );
    $query = mb_ereg_replace ( ',$', '', $query );
    return $query;
  }
--------------


【CakePHP2.3 Search Plugin検索処理 目次】
CakePHP2.3 Search Pluginで検索処理 その1設置方法
CakePHP2.3 Search Pluginで検索処理 その2表示件数を動的に変える方法
CakePHP2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHP2.3 Search Pluginで検索処理 その4前方一致検索、後方一致検索、不等号による検索、between句による範囲検索
CakePHP2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索
CakePHP2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能
CakePHP2.3 Search Pluginで検索処理 その7queryを使って 日付の範囲検索
[ 2013年08月26日 00:55 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3 Search Pluginで検索処理 その4前方一致検索、後方一致検索、不等号による検索、between句による範囲検索

今回は、前方一致検索、後方一致検索、不等号による検索を行います。
今回の処理は、その2(http://ssgiken.blog.fc2.com/blog-entry-31.html)をベースにしていますので、そちらもご覧ください。

順番的にはもっと最初の方で提示するべき項目だと思いますが、これまでは「value」による完全一致検索、「like」による部分一致検索で処理を作ってきました。

ですが、この辺で改めて、完全一致検索、部分一致検索以外の検索の方法を書いておきます。

とはいえ、これについては、特に難しいものではありませんので、下記のサイトなどを見ていただくと分かるんじゃないかと思います。
http://mawatari.jp/archives/introduction-of-cakedc-search-plugin-for-cakephp



前方一致検索
「ユーザ名」の項目を前方一致検索する場合は、下記の通り「'before' => false, 'after' => true,」を追加します。Model以外の修正はありません。
--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
    :
    :
  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id',       'type' => 'value', 'field' => 'User.id'),
    array('name' => 'username', 'type' => 'like',  'before' => false, 'after' => true, 'field' => 'User.username'),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname'),
  );
    :
    :
}
--------------

後方一致検索
「ユーザ名」の項目を後方一致検索の場合は、下記の通り「'before' => true, 'after' => false,」を追加します。Model以外の修正はありません。
--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
    :
    :
  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id',       'type' => 'value', 'field' => 'User.id'),
    array('name' => 'username', 'type' => 'like',  'before' => true, 'after' => false, 'field' => 'User.username'),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname'),
  );
    :
    :
}
--------------


不等号による検索
「ユーザID」の項目を不等号によって検索をする場合は、下記の通り「id」を Modelと Viewのページにそれぞれ「id_from」「id_to」の項目変更しています。
不等号は「field」の項目の後ろに「>=」「<=」を記述します。

まぁ、今回は、すでにある項目を流用するため IDを不等号検索に使いましたが、実実装に関しては IDを from、toで検索することはないでしょうね。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
    :
    :
  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id_from',  'type' => 'value', 'field' => 'User.id >='),
    array('name' => 'id_to',    'type' => 'value', 'field' => 'User.id <='),
    array('name' => 'username', 'type' => 'like',  'field' => 'User.username'),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname'),
  );

  // 検索対象のフィールド設定
  public $presetVars = array(
    array('field' => 'id_from',  'type' => 'value'),
    array('field' => 'id_to',    'type' => 'value'),
    array('field' => 'username', 'type' => 'value'),
    array('field' => 'nickname', 'type' => 'value'),
    array('field' => 'limit',    'type' => 'value'),
  );
    :
    :
}
--------------

--------------(/app/View/Elements/searchForm.ctp)
    :
    :
    <dt><label>ユーザID</label></dt>  
    <dd><?php echo $this->Form->input('id_from', array(  
      'type' => 'text', 'div' => false, 'label' => false))?>  
        <?php echo $this->Form->input('id_to', array(  
      'type' => 'text', 'div' => false, 'label' => false))?></dd>  
    :
    :
--------------


続けて、between句による範囲指定の方法です。

不等号による範囲指定での検索は、betweenによる範囲検索より検索スピードが劣るとされています。
そのため、betweenによる範囲指定も探してみましたが、うまく実装することができませんでした...

現時点では、「/app/View/Elements/searchForm.ctp」は同じものを使います。
そして、Modelは、以下のように設定します。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
    :
    :
  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id_from',  'type' => 'expression', 'method' => 'idBetween', 'field' => 'User.id BETWEEN ? AND ?' ),
    array('name' => 'username', 'type' => 'like',  'field' => 'User.username'),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname'),
  );

  function idBetween($data = array()) {
    $query[] = $data['id_from'];
    if ( $data['id_to'] ) {
      $query[] = $data['id_to'];
    } else {
      $query[] = 999999;
    }
    return $query;
  }
    :
    :
}
--------------

「'type' => 'expression'」を設定し、「method」で配列を渡す関数を通すことで、自動的に「between句」を生成してくれます。
この方法でも、「id_from」に値が入力されれば正しく betweenで検索されます。

ですが、「id_from」の値が入っていない場合(「id_to」のみの入力の場合)は、入力がないものとして処理されません。


「id_to」のみの入力の場合も検索の処理をさせる方法については、分かりませんでした!!!
分かる方、どなたか教えてくださいっ!!


【CakePHP2.3 Search Plugin検索処理 目次】
CakePHP2.3 Search Pluginで検索処理 その1設置方法
CakePHP2.3 Search Pluginで検索処理 その2表示件数を動的に変える方法
CakePHP2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHP2.3 Search Pluginで検索処理 その4前方一致検索、後方一致検索、不等号による検索、between句による範囲検索
CakePHP2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索
CakePHP2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能
CakePHP2.3 Search Pluginで検索処理 その7queryを使って 日付の範囲検索
[ 2013年08月19日 00:45 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法

今回の検索は、入力エリアは 1つですが、複数の項目にわたって検索を行いたい、という場合の検索方法です。

例えば、ニュースなどの記事の検索で、タイトルと本文を検索したいが、入力は分けずに 1つの入力で両方を検索したい、という場合などの対応です。


具体的には、「ユーザ名」の検索項目で入力したものを、ユーザ名、ニックネームのいずれかにマッチする情報を取得してくるように変更してみましょう。
今回の処理は、その2(http://ssgiken.blog.fc2.com/blog-entry-31.html)をベースにしていますので、そちらもご覧ください。


これは、非常に簡単です。

13行目の fieldの値を「'User.username'」一つだったものを「array ( 'User.username', 'Profile.nickname' )」という形式で検索するフィールドを配列に入れて指定してあげるだけです。
これで、検索する対象となる項目を追加することができました。

もっと項目を増やしたい場合は、配列に項目名を追加するだけで OKです。

--------------(/app/Model/User.php)
<?php
class User extends AppModel {  
  public $name = 'User';  
  
  // 検索プラグイン  
  public $actsAs = array('Search.Searchable');  

  // 検索対象のフィルタ設定
  public $filterArgs = array(
    array('name' => 'id',       'type' => 'value', 'field' => 'User.id'),
    array('name' => 'username', 'type' => 'like',  'field' => array ( 'User.username', 'Profile.nickname' ) ),
    array('name' => 'nickname', 'type' => 'like',  'field' => 'Profile.nickname'),
  );

  // 検索対象のフィールド設定
  public $presetVars = array(
    array('field' => 'id',       'type' => 'value'),
    array('field' => 'username', 'type' => 'value'),
    array('field' => 'nickname', 'type' => 'value'),
    array('field' => 'limit',    'type' => 'value'),
  );


  // アソシエーション  
  public $hasOne = array(  
    'Profile' => array(  
      'className'  => 'Profile',  
      'foreignKey' => 'user_id',  
      'conditions' => null,  
      'fields'     => null,  
      'dependent'  => true,  
    ),  
  );  
}  
--------------


【CakePHP2.3 Search Plugin検索処理 目次】
CakePHP2.3 Search Pluginで検索処理 その1設置方法
CakePHP2.3 Search Pluginで検索処理 その2表示件数を動的に変える方法
CakePHP2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHP2.3 Search Pluginで検索処理 その4前方一致検索、後方一致検索、不等号による検索、between句による範囲検索
CakePHP2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索
CakePHP2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能
CakePHP2.3 Search Pluginで検索処理 その7queryを使って 日付の範囲検索
[ 2013年08月12日 00:39 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)
プロフィール

エス技研

Author:エス技研
性別:男性
職業:Web系エンジニア
エンジニアになって 15年ほど経ちますが、その途中で 5年ほどディレクタ、マネジメントを中心とした業務を行っていたためにやや現場を離れていましたが、転職をきっかけに 2012年に現場に復帰し、新たな技術を楽しみながら勉強しています。
メインの環境は LAMP環境です。

FC2ブログランキング
FC2カウンター
FC2拍手ランキング
GoogleAdWords
カレンダー
10 | 2017/11 | 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
検索フォーム
ブロとも申請フォーム
QRコード
QR
フリーエリア


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。