またどこかでCTOっぽいことやってる人のブログ

フリーランスを経て、またどこかでCTOっぽいことをやってる人が書いてます。何か色々やってます。

FlashメッセージをBootStrap風味にしてみた。

2016年も早いもので8月になりました。
気が付いたら今年も半年以上終わってるんですね。

恐ろしい。

今日は小ネタです。
CakePHPを使っているとエラーメッセージにFlashを使う機会があると思います。
使い方は至って単純で、Controller側でメッセージをセットしてView側でレンダリングするだけです。
CakePHP3だとこんな風に書きます。

<?php
  // Controller側
  public function test() {
    $this->Flash->error('エラーですよ');
  }


例えばこんな感じでエラーメッセージをセットして

<?php
  <!-- ここにメッセージが出ます -->
  <?php echo $this->Flash->render(); ?>


View側でこのようにレンダリングします。
このエラーメッセージはCakePHP3が最初から準備しているテンプレートで、Elementの下にあります。
Element\Flashディレクトリの下ですね。
何もしていなければ「default.ctp」、「error.ctp」、「success.ctp」があると思います。

上の方で「エラーですよ」とメッセージをセットしたテンプレートは今回だと「error.ctp」です。
なので、「$this->Flash->success('成功ですよ');」と書けば「success.ctp」が呼び出されるわけです。

他のテンプレートを使いたかったら「error_special.ctp」なんてのを例えば作成して、メッセージをセットする時に

<?php
  // Controller側
  public function test() {
    $this->Flash->errorSpecial('すごいエラーですよ');
  }

なんて書けばOKです。


で。
個人的な趣味なんでしょうが、自分はBootStrapを使っている時はアラートコンポーネントを使う傾向にあります。
ですのでいつもこんな感じで書き換えています。

<?php
  // 元々のElement\Flash\error.ctp
  <div class="message error" onclick="this.classList.add('hidden');"><?= h($message) ?></div>

これを

  <div class="alert alert-warning" role="alert">
    <p class="text-danger">
      <?php echo h($message); ?>
    </p>
  </div>

例えばこんな風に変更すると、BootStrapのアラートコンポーネントを使ったエラーメッセージエリアができます。

もし、複数のエラーを改行コード入れつつ全部出力したい時は、Controller側で配列をセットしてループさせればいいと思います。
配列セットする時に改行コードを埋め込むか、View側で出力する時に改行コードを出すかはお好みで。
改行コードを埋め込んだ配列をセットした場合だと、error.ctpはこんな感じになると思います。

<?php
  <div class="alert alert-warning" role="alert">
    <p class="text-danger">
      <?php foreach($message as $msg): ?>
        <?php echo $msg; ?>
      <?php endforeach; ?>
    </p>
  </div>

hをつけたままだと改行されなくて頭を抱えるかもしれないので注意してください。
小ネタと冒頭に書きつつ、何でこんなネタを書いた理由は自分が頭を抱えた張本人だからです。

戒めというやつですね。

CakePHP3でbuildRuleに条件分岐を追加してみた。

2017/05/14 追記 ------------------------------------------

昔できていたはずなのに、過去の自分の記事を見ながら作ってみたらエラーに…。
下の方、修正しておきました。
2017/05/14 追記終わり -----------------------------------


2016年の夏はどうも天気がシャキっとしてません(7月現在)
きっと、まだ地球さんが本気出してないんでしょう。

さて、今回はこんなことをやりたくなりました。

「ユーザ登録時にメールアドレスは必須じゃないけど、入力された時は重複不可にしたい」

重複不可だけならbuildRule(saveメソッドコール時に実行されるバリデーション)に書けば終わりです。

<?php
 public function buildRules(RulesChecker $rules) {
   // カラム名はemailと仮定します
   $rules->add($rules->isUnique(['email'], 'メールアドレス重複エラー'));

   // 処理結果を返す
   return $rules;
}

なんですが。
メールアドレスが必須ではないので、入力された時はいいとしても未入力の場合は最初の1件しかデータが入らず、メールアドレス未入力データ2件目以降の場合はしっかりエラーになってしまいます。
要するに「メールアドレスが空のデータはもうありますので!」というわけです。

困りました。
困りましたが、要は「メールアドレスが入力された時だけ、重複チェックすればいいじゃん」というのはわかります。
何か上手い方法はないものかと色々調べたのですが、どうもそれっぽい情報が見当たりません。
で、公式を見ながら実現できたコードが以下です。

<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\ORM\RulesChecker;
use Cake\ORM\Rule\isUnique; // これを宣言しておく必要があります

class UsersTable extends Table {

/**
 * POST時のバリデーション
 */
public function validationDefault(Validator $validator) {
  // 今回は省略しますが、何かバリデーションを色々
  // メールアドレスを必須にせずに形式だけチェック
  $validator
    ->allowEmpty('email')
    ->email('email', true, 'メールアドレス形式ではありません。');

  // 処理結果を返す
  return $validator;
}


/**
 * save実行時のバリデーション
 */
public function buildRules(RulesChecker $rules) {
  // カラム名はやっぱりemailと仮定します
  $rules->add(
    function ($entity, $options) {
      if (!empty($entity->email)) {
        // 2017/05/14 ここから修正
        $rule = new isUnique(['email'], $options);
        // 2017/05/14 ここまで修正
        return $rule($entity, $options);
      } else {
        // 未入力の場合はtrueで返す
        return true;
      }
    },
    ['errorField' => 'email', 'message' => 'メールアドレス重複エラー']
  );
  return $rules;
}

$entityからチェックしたいカラムを抜いてきて、その項目に対してemptyチェック。
入力されていたらisUniqueで重複チェックしてます。

isUniqueのコンストラクタ引数が配列指定なので上記のような形式で渡しています


未入力の場合はtrueを返してます。
どうもちゃんと明示的に書かないとダメみたいです。
エラーメッセージ設定は見たままです。

きっともう少しいい方法あるんじゃないかなとは思います。
が、今回emptyチェックしている部分を色々変えれば融通が利くbuildRuleが作れるかなと。

そもそもemailを必須にしない仕様自体がアレとかいう話もありますが。

CakePHP3で定数を使ってみた。

2017/06/27 追記
この記事、結構見られているようなので関連項目として「グローバル配列」の記事を書いてみました。
tsuralabo.hatenablog.com


もしよろしければこちらの記事もご覧くださいませ。




その昔、C#で開発していた頃はよく定数ファイルを使っていたのですが、PHPメインになってからあまり使わなくなりました。
定数使うのであればConfigファイルに書いてしまうタイプです。
とは言え、そんなことをやっているとConfigファイルが肥大化してしまいます。

定数ファイルを1つ作ってダーッと書くのもいいとは思うのですが、用途でファイルを分けた方が後々幸せになれるかもしれません。
「この定数ファイルは〇〇用」で「あっちの定数ファイルは□□用」みたいな。
好みの問題かもしれませんが。

今回書いている定数とは、グローバル定数の位置付けのつもりで書いてます。
パスワードとかをブチ込むと怖いですが、例えばViewに表示するメッセージとかdatatablesのパラメータとか。
そういうのを書くと便利じゃないかなと思います。
とは言え、定数ファイルを嫌う方もやはりいらっしゃいますので、その辺は柔和な対応をして下さい。

CakePHP3の定数ファイル、いわゆるdefine宣言は配列で返す必要があります。
要するにConfigファイルと同じです。
sample-const.phpなんて名前でconfigディレクトリ直下にファイルを作ります。
書き方はapp.phpと同じです。

<?php
  return [
      // datatables設定
      define('SAMPLE_NUMBER', 10),
      define('SAMPLE_STRING', 'test'),
  ];

ファイルを作った後はbootstrap.phpの方でロードしましょう。

<?php
try {
    Configure::config('default', new PhpConfig());
    Configure::load('app', 'default', false);
    
    /* 必要あればこの辺りに環境変数での切り分けなど */
    
    // 定数ファイル読み込み
    Configure::load('sample-const', 'default');
} catch (\Exception $e) {
    exit($e->getMessage() . "\n");
}

ここまでやればあとはViewでもControllerでも好きな場所で使えます。
echoで出力したり、パラメータに入れたりなどなど。

<?php
// testが表示されます。
echo SAMPLE_STRING;


必要あればどこかで使って下さい。

CakePHP3でカスタムバリデーション作ってみた。

2016/10/31 追記

カスタムバリデーションではないのですが、バリデーション関連の記事を追加してみました。
tsuralabo.hatenablog.com




チマチマ作ってるアレですが、管理画面の方に着手しています。
入力項目や登録するデータが出てくるので、どうしてもバリデーションが必要になってきます。

CakePHP3のバリデーションはCakePHP2までと少し変わっていまして、2パターンのバリデーションがあります。
1つ目はPOSTデータをチェックする際のバリデーション。
2つ目はsaveメソッド実行時のバリデーション。

ググるとわかりますが前者は「validationDefault」、後者は「buildRules」なんて言うらしいです。
コードで書くとこんな感じです。

<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator; // validationDefault使う時に必要です
use Cake\ORM\RulesChecker;     // buildRules使う時に必要です

class UsersTable extends Table {
  public function validationDefault(Validator $validator) {
    // POSTデータ受け取り時のバリデーション

    // 結果を返す
    return $validator;
  }

  public function buildRules(RulesChecker $rules) {
    // saveメソッド実行時のバリデーション

    // 結果を返す
    return $rules;
  }
}

見たらわかると思いますが、CakePHP3ではTableにバリデーションを書きます。
上のソースだとUsersTableに書いてます。

バリデーションの書き方はCakePHP2の頃と似ているようで違います。
Validator型(でいいのかな?)の$validatorに対して、「このフィールド」に対して「こういうバリデーション」します、という書き方です。
例えばusernameというフィールドに対して入力必須のバリデーションをチェックしたい時は

<?php
$validator->notEmpty('username', 'ユーザ名が入力されていません。');

こんな感じです。
さらに4文字以上、8文字以内というバリデーションをチェックしたい時は

<?php
$validator
  ->notEmpty('userid', 'ユーザIDが入力されていません。')
  ->lengthBetween('username', [4, 8], 'ユーザIDは4文字以上、8文字以内。');

このようになります。
他のフィールドもチェックしたい時はどんどん繋げていけばいいのですが、ソースが見難くなるかもしれません。
そんな時は

<?php
$validator
  ->notEmpty('username', 'ユーザ名が入力されていません。')
  ->lengthBetween('username', [4, 8], 'ログインIDは4文字以上、8文字以内。');

$validator
  ->notEmpty('password', 'パスワードが入力されていません。')
  ->lengthBetween('password', [8, 32], 'パスワードは8文字以上、32文字以内。');

と分けて書いても大丈夫です。
個人的にはこちらの書き方の方が好きです。
理由は何の項目に対して、どんなバリデーションをチェックしているか見やすいからです(個人的な意見です)
notEmptyが何とか、lengthBetweenって何? とかはグーグル先生に聞いてみて下さい。



さて。
今回はユーザIDに対して半角英数字のみというバリデーションをチェックすることにします。
CakePHP2の頃からある「alphaNumeric」を使えばよさそうなのですが、これ実は日本語を通してしまうんです。
なので少なくとも日本で展開するWebサービスだと使いものになりません(多分)
CakePHP3本体のValidationを書き換えればいけちゃうと思うんですが、あまり本体には手を入れたくない。

こんな時、CakePHP2だったらAppModelにサラっと書いて、それを呼び出せばよかったのですがCakePHP3にはありません。
ですので、本家のマニュアルを見ながらそれっぽいものを作ってみました。
それがやっと辿り着いた、カスタムバリデーションです。


本家の書き方を踏襲して、src\Model配下にValidationというディレクトリをとりあえず作ります。
作ったValidationディレクトリにCustomValidation.phpを作成します。
中身はこんな感じです。
ついでに半角英数字のバリデーション用のfunctionも書いてしまいます。
ただの正規表現なんですけどね。

<?php
namespace App\Model\Validation;
use Cake\Validation\Validation;

/**
 * カスタムバリデーションサンプル
 */
class CustomValidation extends Validation {
  
  /**
   * 半角英数字バリデーション
   * @param type $check
   * @return type
   */
  public static function alphaNumericCustom($check) {
    return (bool) preg_match('/^[a-zA-Z0-9]+$/', $check);
  }
}

名前はもちろん、CustomValidationじゃなくて構いません。
RururuValidationだろうが、SpecialValidationだろうが何でもOKです。
ただ、注意する必要があるのは以下の2点。


その1 作成するfunctionは「static」にすること
その2 作成したfunctionの戻り値はbool型にすること


この2点です。
試しにstatic取ってみると、staticで書けとエラーが出ます。
これさえ守ればあとはただの正規表現的な何かでしかありません。
とりあえずカスタムバリデーションとかいう偉そうな名前の正規表現ができたので、先程のバリデーションに組み込みます。

<?php
/**
 * POST処理時のバリデーション
 * @param Validator $validator
 * @return Validator
 */
public function validationDefault(Validator $validator) {
    
  // カスタムバリデーション設定
  // 書き方は「$validator->provider('プロバイダのキー', 'カスタムバリデーションのパス');」です。
  $validator->provider('ProviderKey', 'App\Model\Validation\CustomValidation');
    
  $validator
    ->notEmpty('username', 'ユーザ名が入力されていません。')
    // ここからカスタムバリデーション
    ->add('username', 'ruleName', [
          'rule' => ['alphaNumericCustom'], 
          'provider' => 'ProviderKey',   // カスタムバリデーション設定で書いたプロバイダのキーを入れます。
          'message' => 'ログインIDは半角英数字で入力してください。'])
    // ここまでカスタムバリデーション
    ->lengthBetween('username', [4, 8], 'ログインIDは4文字以上、8文字以内。');
    
  // 結果を返す
  return $validator;
}

※2016/07/11にここから修正しました ----------

カスタムバリデーション設定と書いている部分は、CakePHP3的に言うとプロバイダ設定です。
呼び出しというか、バリデータに対して「このプロバイダ使いますよ」追加してるわけです。
「add」メソッドでカスタムバリデーションに作ったfunctionを追加すると、無事にカスタムバリデーションが使えるようになります。
ruleNameと書いてある箇所はバリデーションのルール名です。適当に入力しておいて下さい(ダメかもしれませんが)

試したみた感じ、プロバイダのキーは何でもOKでした。
上の例だと「ProviderKey」と書いてますが、RururuでもSpecialでも何でも大丈夫です。

※ここまで修正しました-----------------------

バリデーションチェックでエラーが発生した場合、設定したメッセージが返ってきます。
それを呼び元でごにょごにょしてViewにメッセージ表示すればいいんじゃないかなと思います。
一応、思い出したかのようにController側からの呼び出し方も書いておきます。

<?php
/**
 * ユーザ追加functionということにします
 */
public function add() {
  // POSTデータを渡す
  $user = $this->Users->newEntity($this->request->data);

  if (!$user->errors()) {
    // バリデーションエラーがなかった場合
  } else {
    // バリデーションエラーの場合
  }
}

エラー時はerrorsという中にエラーメッセージが入ってるので、Flashなどでメッセージを表示するといいです。
エラーメッセージを1つずつまとめて表示したい!という場合は、イケてない書き方ですが

<?php
/**
 * ユーザ追加functionということにします
 */
public function add() {
  // POSTデータを渡す
  $user = $this->Users->newEntity($this->request->data);

  if (!$user->errors()) {
    // バリデーションエラーがなかった場合
  } else {
    // バリデーションエラーの場合
    foreach ($user->errors() as $error) {
      foreach ($error as $message) {
        pr($message);
      }
    }
  }
}


$message辺りを配列にブチ込んでView側で出力しながら改行コード入れると、それっぽくなります。
もう少しいい書き方できればいいんですが、模索中ということで。

ちなみにbuildRulesの方も書き方は同じです。
多分。

CakePHP3とMAMPとバーチャルホスト設定。

コツコツと余暇時間を使って作っている某Webサービスですが、何となくある程度できました。
とは言っても、特にデータもありませんし画像もありません。
中に処理は書いているものの、見た目はモックです。

とりあえずクライアント側は置いといて、管理画面を作ることにしました。
個人的な意見なんですが、管理画面を疎かにするサービスは高確率でポシャります。
「データ修正すればできるんだから、管理画面は後回しでいいじゃん」というのはよろしくありません。
サービスの管理画面は超大事です。

で。
ローカルでしか開発していないこのサービスですが、管理画面のプロジェクトも作っておこうかと。
というわけなので、今回はMac + MAMP + CakePHP3でのバーチャルホスト設定です。

まずはMAMPでバーチャルホストを有効にしましょう。
これは以下のディレクトリにあります。

/MAMPインストールディレクトリ/conf/httpd.conf

この中にこんな箇所があります。

# Virtual hosts
#Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf ←このコメントをはずす

コメントをはずすと「httpd.confを読み込んだ時に、このパスのファイルも読み込みますよ」ということになります。
このコメントをはずしたhttpd-vhosts.confにはバーチャルホスト設定のテンプレートが書いてあります。
「バーチャルホスト設定はここに書くと都合がよろしいですよ」ということなんでしょう、多分。

それでは次にコメントをはずしたhttpd-vhosts.confファイルの修正です。
このファイルは以下のディレクトリにあります。

/MAMPインストールディレクトリ/conf/apache/extra/httpd-vhosts.conf

コメントはずしたファイルパスですね。
これをとりあえず開きましょう。

ローカル環境なので細かい説明はしませんが、ここでバーチャルホストが設定できます。
とりあえず以下の設定を書けばOKです。

NameVirtualHost *:80

<VirtualHost *:80>
  DocumentRoot "/Applications/MAMP/htdocs/sample-site-1/webroot/"
  ServerName localhost.sample-site-1
</VirtualHost>

<VirtualHost *:80>
  DocumentRoot "/Applications/MAMP/htdocs/sample-site-2/webroot/"
  ServerName localhost.sample-site-2
</VirtualHost>

面倒なのでバーチャルホストは80番ポートのままにします。
sample-site-1というプロジェクトと、sample-site-2というプロジェクトを動かす設定です。
DocumentRootはそのプロジェクトのwebrootが存在するディレクトリ。
CakePHP3の場合はwebroot/index.phpですので、このようなパスを設定しています。
ダブルクォーテーションで囲むのを忘れないようにして下さい。

今回の件とは別なんですが、このバーチャルホスト設定に環境変数を入れることもできます。
.htaccessなんかに書く方もいらっしゃいますが、個人的にはこっちに書いた方が好きです。
設定する時はこんな風に書きます。

<VirtualHost *:80>
  DocumentRoot "/Applications/MAMP/htdocs/sample-site-3/webroot/"
  ServerName localhost.sample-site-3
  #SetEnv 環境変数名 値 の形で以下のように書く
  SetEnv EnvType test
</VirtualHost>

設定した環境変数PHP側で参照できます。
ので、これを使ってプロジェクトのデプロイに応じてDB接続先の変更なんかもできますね。
脱線してますが、ここまで書いたので書いておきます。
編集するのはbootstrap.phpです。
configファイルの読み込み部分がありますので、その下辺りにでも追加するといいです。

try {
  Configure::config('default', new PhpConfig());
  Configure::load('app', 'default', false);

  // 環境変数で使用するconfigファイルを切り替え
  switch (getenv('EnvType')) {
      case "test":
         Configure::load('env/app-test-config', 'default');
         break;
      case "production":
         Configure::load('env/app-production-config', 'default');
         break
  }

  // 環境に関わらず別のconfigファイルを使いたい時は以下を追加(configディレクトリ直下にファイルを作成する)
  Configure::load('app-common', 'default');
} catch (\Exception $e) {
  die($e->getMessage() . "\n");
}

上の例だと、まずconfigディレクトリの直下に「env」ファイルを作成。
CakePHP3をインストールした時にできている「app.php」をコピーして、
envディレクトリに貼り付けつつ、ファイル名を変更。
あとは各ファイルの中身を編集すればOKです。


脱線しましたが、ここまででとりあえず設定の大部分が終わったので、次はMac自体の設定をします。
Windowsにもありますが、hosts設定というやつですね。

Macのhostsファイルは以下のディレクトリにありますので、rootユーザで編集します。
rootユーザのパスワードが何かわかりませんという方もあまり気にせず。
Macを起動する時にパスワード入力しますよね? アレです。

sudo vim /private/etc/hosts

viでもvimでも構いませんが、自分はvim派です。
これを開くと既に何か書いてあると思います。
ここのlocalhostにバーチャルホストで設定したServerNameを追加してあげます。
簡単に言うと「このURLにアクセスしたらローカルホスト!」という設定です。

追加する時は横にスペースを入れて記載すればOKです。
こんな風になると思います。

127.0.0.1       localhost sample-site-1 sample-site-2

127.0.0.1というのは使っているPC自体のことです。
「このPCのアドレスは127.0.0.1です」というような意味です。

ここまで設定が終わったらMAMPを再起動しましょう。
再起動したら以下のURLにアクセスすると、きっとサイトがそれぞれ表示されると思います。

http://localhost.sample-site-1/
http://localhost.sample-site-2/

余談なんですが。
以前バーチャルホストの設定をした際に、以下の設定をしてハマったことがあります。

http://localhost/sample-site-1/

何故かCakeさんがしきりにエラーを出してきます。
よく見たら「sample-site-1」部分をコントローラと判断されて、そんなコントローラないから作りやがれと怒っていました。
言われたら確かにその通りなんですが、しばらく頭を抱えてました。

お気づきかもしれませんが、インフラ周りも苦手です。

MVCとメイドシステム。

Webアプリを作っている人であれば、何回も聞いたことがあるはずの「MVC」という言葉。

Model・View・Controllerの頭文字ですね。

何となくわかる方、完璧にわかる方。

よくわからないけど、とりあえず知ってる素振りの方など色々いらっしゃると思います。

今回はこれをメイドシステム(仮)に例えて書いてみます。

 

登場人物は以下の通り。

 

・View:ご主人さま

・Controller:メイド長

・Model:メイド

 

何か大きな屋敷でも想像してもらえれば。

ちなみに自分にはメイド属性ありません。

 

まず、モデルというのは別にDB操作のために存在しているわけではありません。

この子は「雑用でしたらお任せくださいませ」という役割です。

まぁ何でもやるわけです。DB操作もやりますし、それ以外のバリデーションもやります。

 

このメイドを束ねるのがメイド長であるControllerですね。

この人はメイドに指示を出して、アレコレとViewであるご主人さまのためにせっせと働くわけです。

 

で、ご主人さまであるViewがTV見たりゲームしたり、何してるのか知りませんが色々と命令するわけです。

 

View「この画面でこの検索結果が見たい」

Controller「かしこまりました、ご主人さま」

Controller「メイド達、お仕事よ。このデータを取っていらっしゃい」

Model「かしこまりました、メイド長さま」

 

こんな感じです。

なんですが、ご主人様はメイド長をカッ飛ばしてメイドにお願いすることもあるかもしれません。

これ、別にいいんです。ご主人さまなので呼んでいいんです。偉いのです。

CakePHPだとヘルパーを使いますね。まぁ直通電話みたいなもんです。

 

View「あのさ、メイド長に内緒でこんなデータ取ってきてくれない?」

Model「かしこまりました、ご主人さま」

 

まぁ別に内緒にする必要はないのですが、多分こんな具合です。

 

よくある「作ってたらControllerが肥大化した!」という状況は、Modelに仕事を振ればいいのにメイド長が自分で色々やってしまっている状況です。

責任感が強すぎですね。そんなに背負いこむ必要って本来はないのです。

 

となると、メイドは結構暇ですね。

メイドは働き者なのですが、暇だと仕事後にどこに行こうとか、あそこのケーキが美味しいらしいみたいな話をしているかもしれません。

まぁ、これもどうだか知りませんが。

 

MVCのキモはControllerです。

日々やってくる仕事をテキパキ片付けなければいけません。なので、メイド長がその仕事を担うのです。

とは言え、メイド長にも限界がありますのでメイドに仕事を振らざるを得ない。

でもそれでいいのです。メイドは働き者ですから。

 

このメイドシステム(仮)が上手く機能すると、Controllerは用件をお伺いした後でModelに仕事を指示して報告を受け取るだけのコードが出来上がります。

 

これできっと、メイド長もティータイムを満喫できることでしょう。

 

BootStrap3とselect2を組み合わせてみた。

実はデザインセンスが全くありません。
「お。このサイトいいな!」とは思うことはもちろんありますが、そこまでです。
自分で作れません。白状すると、CSS大嫌いです。
なので、とりあえず組み合わせると使えるBootStrapは大好きです。


とは言え。
BootStrapを使うと、いわゆる「BootStrap臭」が漂うサイトになってしまいます。
管理画面なんかであれば別にいいと思うんですけどね。
公開するようなサイトだとちょっとカッコつきません。
なんですが、大事なことは機能を作って動作して、公開することなのでいつもいつもデザインを後回しにしてしまいます。


さておき。
2016年現在、こつこつ作っている個人サイトはCakePHP3 + mySQL + BootStrap3で作成しているのですが、どこかの凄い人が作ったJQueryも使っています。


今回使ってみたのは「select2」というJQueryライブラリ。
Select2 - The jQuery replacement for select boxes


これ、セレクトボックスでサジェスト検索ができちゃう素敵なライブラリです。
セレクトボックスの下にテキストボックスが出てきて入力するとサジェスト。
実装もサーバサイドでデータ取ってきてセットするだけ。お手軽です。


実装自体はマニュアルやサンプルがあるのですぐなんですが、今回はこのselect2をBootStrap3のモーダルウィンドウで表示したかったんですね。


でも、表示はできてもテキスト入力が効かない。
これだとただのセレクトボックスです。残念な結果です。


そんな時はモーダルウィンドウを表示しているトコから「z-index:-1」を取ってしまいましょう。
よくよく考えたら確かにそうなんですけどね。
辿り着くまでに時間がかかったので、覚書しつつどこかの誰かの役に立てばいいなと思いつつ書いておきました。


select2絡みでもうひとつ。
マニュアルに書いてあるプレースホルダが、自分の環境ではどうしてもできなくて。
プレースホルダ代わりに文字列を埋め込むのもアレだなと思っていたのですが、これは結局セレクトボックスの方を対応して解決しました。
結果としてこんなコードになりましたので、載せておきます。

<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 padding-top-5">
  <select id="selectSample" class="form-control" style="width: 100%" onChange="なんか処理();">
    <option value='' disabled selected style='display:none;'>ここにプレースホルダ</option>
    <?php echo $ここにセレクトボックスに表示するリスト; ?>
  </select>
</div>


そうそう。
「selectSample」にwidthを100%指定しているのはBootStrapのグリッドを合わせるためです。
普通に書いた感じだと上手くグリッドが適用されなかったので、こんな処理入れてます。
これだと上手くいくので、現状こんな形にしてます。


まぁ雑ですね。