ブログ・エス技研

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

スポンサーサイト

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

CakePHP 2.3 Search Pluginで検索処理 その1設置方法

CakePHP 2.0系の Search Pluginで検索処理を作ります。

参考にしたのは下記のサイト。文面はふざけている部分もありますが、内容は至ってしっかりしたもので、非常に参考になります。
また、ページャーの処理やソート機能なども Bakeするのではなく、それぞれ解説をしながら作っていきますので非常に勉強になります。
http://torhamzedd.halteria.com/2012/01/cakephp20search-plugin22.html

上記のサイトを読みながら、プラグインをダウンロードして、所定の場所にインストールしてください。私の場合は、ダウンロードしたファイルは、最新版の 2.3でした。


ここで注意してほしいのは、Pluginを設置したら「/app/Config/bootstrap.php」にそのことを記述する必要があるということです。(上記のサイトには書かれていません。)

「/app/Config/bootstrap.php」の 65行目あたりから Pluginの設定についての記述がありますので、そのあたりに下記のコードを追加しましょう。

--------------(/app/Config/bootstrap.php)
CakePlugin::load(array('Search'));
--------------

もしくは、70行目あたりにある下記のものをコメントの外に出して、有効にする方法でも OKです。こちらは、Pluginフォルダにあるものはすべて有効にするという記述の方法ですので、すでに有効にしてある場合もあるでしょう。その場合は、上記の記述を書かなくても問題ありません。両方書いていても問題ありません。

--------------(/app/Config/bootstrap.php)
CakePlugin::loadAll(); // Loads all plugins at once
--------------


続いて、テーブルを作りましょう。
こちらも上記サイトにあるものをそのまま使いました。また、データもそのまま入れました。

さらに続けて、Model、Controller、Viewを作ります。
Viewは、上記のサイトにあるものをそのままで問題ありませんが、Model、Controllerは、PHPのファイルですのでファイルの先頭に「<?php」を記述するのを忘れないようにしておきましょう。

そして、一度表示させて、検索フォームを追加するあたりまでは特に問題ないかと思います。


ページャーの設定などは、bakeで出てくるものをそのまま使うこともできますので、bakeで作ったところに検索処理を追加する場合などは、ページャーの一覧を表示する「app/View/Elements/pager.ctp」の設定は不要となるでしょう。

また、「UserController.php」は、最終的には下記のようになります。

--------------(/app/Controller/UserController.php)
<?php
class UsersController extends AppController {  
  
  public $name = 'Users';  
  public $uses = array('User', 'Profile');  

  public function beforeFilter() {
    // ページャ設定  
    $pager_numbers = array(
      'before' => ' - ',
      'after'=>' - ',
      'modulus'=> 10,
      'separator'=> ' ',
      'class'=>'pagenumbers'
    );
    $this->set('pager_numbers', $pager_numbers);
  }

  public function index()  
  {  
    $this->paginate = array(  
      'limit' => 3  
    );  
    
    $this->set('users', $this->paginate('User'));  
  } 

}
--------------


ここで、その 1は終了。
ここまでは問題ないでしょうか?

そして、ここからはその 2が始まります。
http://torhamzedd.halteria.com/2012/01/cakephp20search-plugin2.html


paginatorの sortの説明や、その機能を使って並び替えをする処理も特に問題ないと思います。

そして、続けて「Searchプラグインの準備」とありますが、これは問題ないでしょう。
すでに最初の方で書きましたが、「/app/Config/bootstrap.php」にプラグインを読み込む設定を記述するという内容ですが、最初のタイミングで記述していないと、おそらく最初の表示確認でエラーが出てここまで進めていないはずですから。


続けて、Model、Controllerの設定を行いますが、最終的には以下のようになります。

--------------(/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' => 'User.username'),
    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'),
  );


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


--------------(/app/Controller/UsersController.php)
<?php
class UsersController extends AppController {  
  
  public $name = 'Users';  
  public $uses = array('User', 'Profile');  

  public $components = array('Search.Prg');  
  public $presetVars = array();  

  public function beforeFilter() {

    // 検索対象のフィールド設定代入
    $this->presetVars = $this->User->presetVars;

    // ページャ設定  
    $pager_numbers = array(
      'before' => ' - ',
      'after'=>' - ',
      'modulus'=> 10,
      'separator'=> ' ',
      'class'=>'pagenumbers'
    );
    $this->set('pager_numbers', $pager_numbers);
  }

  public function index() {
    // 検索条件設定
    $this->Prg->commonProcess();
    // 検索条件取得
    $conditions = $this->User->parseCriteria($this->passedArgs);

    $this->paginate = array(
      'conditions' => $conditions,
      'limit' => 3,
    );
    $this->set('users', $this->paginate('User'));
  }
}
--------------


【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年07月30日 23:24 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

SyntaxHighlighterを導入してソースコードを見やすくしてみました

PHPのソースコードを始め、ソースコードの部分が見にくいなぁ、と以前から思っていましたが、ブログを再開後しばらくして便利なツールがあることを知りまして、今回、それを入れてみることにいたしました。

その便利なツールが「SyntaxHighlighter」です。

現在は、Ver 3.0になっているようで、機能的にも徐々にバージョンアップしてきているようですね。
設置の方法もブログなどを探していただくと、いろいろと情報提供をしてくれている方も増えてきていて、それほど苦労せずに設置できるんじゃないかなぁ。と思い....たいですね。


設置の方法としては、下記のサイトに分かりやすく説明がしてありました。
http://www.netyasun.com/syntaxhighlighter/

http://controlkey.blog.fc2.com/blog-entry-16.html

最初は上の方のサイトを見て「SyntaxHighlighter」の基本的な使い方を勉強して、2コ目のサイトで FC2ブログへの設置方法を勉強しました。

しかしっ!!
私は、2週間前の三連休の時に 2日間ほど設置に時間を費やしたあげくに「'SyntaxHighlighter'は宣言されていません。」という JavaScriptのエラーから脱出できずに断念。


http://www.872style.com/872/memo/web/SyntaxHighlighter.php

そして、今日、改めて上記のサイトを参考にしながらやり直してみました。
このサイトには、Headの部分に書くものと、bodyの最後に書くものと、その理由も含めて書いてありまして、非常に参考になりました。

まずは、ローカルに HTMLファイルを作成し、ローカルで動くことを確認しました。
そして、ブログ上に CSS、JSファイルをアップロードして、相対パスで書いていたソースの場所を URL形式の絶対パスに切り替えて動作を確認。

そして、動作することを確認した上で FC2ブログ上のテンプレートの修正と、記事の修正を実行。
そして、動作確認......

でも動かないっ!!!!!

2時間ほど悩んでみましたがよく分からず、仕方がないからと、違うテンプレートファイルに同じソースを貼り付けてみると...今度は動作しましたっ!!!

つまりは、テンプレートによっては CSSの設定なのか、JSの記述の仕方なのか分かりませんが、正しく動作しない場合があります!って言うことですね。
そこまで分析する気がありませんので、テンプレートを変えてよしとします。

もし、「SyntaxHighlighter」がブログでうまく動かない場合は、テンプレートを変えてみてください。
動くかもしれません。

そんなわけで、このサイトもテンプレートを変更しました。


ちなみに、最初に参考にしたサイトがありましたが、そのサイトは、トップページの画像のバージョンは、3.0.83となっていたものの、ダウンロードのファイルのバージョンは 1.5.1。
で、最初に参考にしたサイトだったこともあって、よく分からずにそのまま進めて行ってもうまくいかず、表示が崩れてそこでようやくバージョンが違っているということに気づきました。
みなさんもバージョン違いには気を付けましょうっ!!


また、IEではスクロールバーが出る際に最後の 1行が欠けてしまう不具合がありまして、こちらも参考にして対応しました。
http://blog.remora.cx/2010/07/new-function-of-syntaxhighlighter-3.html

でも、これを対応しても半分くらい欠けていたので、「margin-bottom: 1em !important;」の部分の「1em」を「2em」にしています。なので、スクロールバーがない場合や、IE以外の場合は、多少余白が多く見えますが、欠けてしまうよりいいでしょう。


ちなみに、ローカルで動作確認した際の HTMLは以下の通りです。
大したものではないですが。

-----------------------
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>SyntaxHighlighter Brushes Tests</title>

<!-- /ここから/ -->
<link href="./styles/shCore.css" rel="stylesheet" type="text/css" />
<link href="./styles/shThemeDefault.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="./scripts/shCore.js"></script>
<script type="text/javascript" src="./scripts/shAutoloader.js"></script>
<script type="text/javascript" src="./scripts/shBrushXml.js"></script>
<!-- /ここまでは head内/ -->

</head>
<body>

<pre class="brush: php;">
<p> 表示したいソースを <em><pre> ~ </pre></em>でかこみ、HTMLの表示であれば、<br />
<em>class="brush: html;"</em> を記入します。</p>
</pre>

<pre class="brush: text;">
<p> 表示したいソースを <em><pre> ~ </pre></em>でかこみ、HTMLの表示であれば、<br />
<em>class="brush: html;"</em> を記入します。</p>
</pre>

<pre class="brush: css;">
<p> 表示したいソースを <em><pre> ~ </pre></em>でかこみ、HTMLの表示であれば、<br />
<em>class="brush: html;"</em> を記入します。</p>
</pre>


<!-- /ここから/ -->
<script type="text/javascript">
SyntaxHighlighter.autoloader(
      "css                      ./scripts/shBrushCss.js"
     ,"js jscript javascript    ./scripts/shBrushJScript.js"
     ,"perl pl                  ./scripts/shBrushPerl.js"
     ,"php                      ./scripts/shBrushPhp.js"
     ,"plain text               ./scripts/shBrushPlain.js"
     ,"sql                      ./scripts/shBrushSql.js"
     ,"html xml xhtml           ./scripts/shBrushXml.js"
);
SyntaxHighlighter.all();
</script>
<!-- /ここまでは bodyuの前/ -->

</body>
-----------------------
[ 2013年07月27日 19:50 ] カテゴリ:プログラミング関連技術 | TB(0) | CM(0)

CakePHP 2.3で確認画面付きのお問い合わせフォームの作り方

前回、XAMPP環境からメールの送信ができるように設定を変更しましたので(http://ssgiken.blog.fc2.com/blog-entry-26.html)、今日はいよいよメールフォームを作っていきます。
(XAMPP環境などローカル環境からメールを送信する設定が分からない方は先週の記事も読んでいただくと参考になるかと思います。)


CakePHPのお問い合わせフォーム製造は bakeで一括処理ができない部分もありますので、作成作業が必要にはなりますが、それほど難しい作業ではありませんので、私でも難しいものではありませんでした。
ただ、CakePHPは、基本的に入力確認画面が存在していないため、それを良しとするかどうかで難易度が大きく違ってきます。

日本においては「フォームと言えば入力確認画面があるもの」として認識されていますので、お問い合わせフォームで入力確認画面がないとユーザから不親切と思われてしまうことでしょう。
ということで、入力確認画面があるフォームを生成する方法を探してみたところ、便利なプラグインがありました。

ヘルパー機能を使って、入力画面と共通の画面を利用して入力確認画面を生成するというプラグインです。非常に便利です。

Xformヘルパーのインストールに関しては、下記のページにありましたが、これだけではその利用方法がよく分からなかったのですが、
http://d.hatena.ne.jp/cakephper/20120222/1329874432

下記のサイトに使い方も含めてまとめられていましたので、こちらが非常に参考になりました。
http://drawxcode.com/2012/12/cakephp-2%E3%81%A7fom%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/

また、CakePHPを使う際に非常に便利な CakePHP Plusというプラグインも設定することになります。
 http://d.hatena.ne.jp/cakephper/20120209/1328776671


ただ、この解説ページでは、実際のメール送信、入力情報の保存までは書かれていませんので、それについては下記のページを参考にしました。
http://log.noiretaya.com/151

また、上記ページでは入力内容を保存していませんが、問い合わせ内容を管理するために DBに登録する必要がありましたので、登録する処理を入れました。


では、まずテーブルと作ります。
ちなみに、今回私は「inquiries(inquiry)」で今回のお問い合わせフォームを作りました。

--------------(テーブル)
CREATE TABLE IF NOT EXISTS `inquiries` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  `body` text CHARACTER SET utf8,
  `mail` varchar(256) CHARACTER SET utf8 NOT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
--------------


続いて、CakePHPからメール送信処理が行えるよう「/config/email.php」ファイルを作成します。
「/config/email.php.default」のファイル名を「email.php」に変更し、下記の部分を追加します。
from、toの値はここで設定をしておかないと動きませんが、controllerの中で設定することもできますので、適当な値を入れておいても問題ありません。

--------------(/config/email.php)
public $inquiry = array(
  'transport' => 'Mail',
  'from' => array ( 'hogehoge@xxxxxx.com' => 'お問い合わせ' ),
  'to'   => array ( 'hogehoge@yyyyyyy.jp' ),
);
--------------


続いて、入力フォームの Viewを作りましょう。

--------------(/View/Inquiries/form.ctp)

お問い合せフォーム

<?php echo $this->Form->create('Inquiry'); ?> <?php echo $this->Xformjp->input('Inquiry.title', array ( 'rows' => '2', 'label' => 'タイトル' ) );?> <?php echo $this->Xformjp->input('Inquiry.body', array ( 'rows' => '2', 'label' => '本文' ) );?> <?php echo $this->Xformjp->input('Inquiry.mail', array ( 'label' => 'メール' ) );?> <?php if ($this->params['xformHelperConfirmFlag']) { echo $this->Formhidden->hiddenVars(); echo $this->Xformjp->submit('修正する', array( 'name' => 'back', 'div' => false)); echo $this->Xformjp->submit('送信する', array( 'name' => 'submit', 'div' => false)); } else { echo $this->Xformjp->submit('入力内容を確認する', array( 'name' => 'confirm')); } ?> <?php echo $this->Form->end() ;?>
--------------


Modelは、バリデーションの設定を記述します。
今回は、入力チェックのみしかしていませんが、メールチェックや、文字数チェックなど必要に応じて追加してください。
また、今回は、入力された情報をテーブルに保存するように作成しますので下記のようになりますが、テーブルを使用しない場合は、「public $useTable = false;」の 1行を追加してください。

--------------(/Model/Inquiry.php)
<?php
class Inquiry extends AppModel {
  public $validate = array(
    'title' => array ( 'rule' => 'notEmpty' ),
    'body'  => array ( 'rule' => 'notEmpty' ),
    'mail'  => array ( 'rule' => 'notEmpty' )
  );
}
?>
--------------



続いて、controllerを作ります。
メール送信処理を使う場合は 3行目の「App::uses('CakeEmail', 'Network/Email' );」が必要になってきます。

--------------(/Controller/InquiriesController.php)
<?php
App::uses('AppController', 'Controller');
App::uses('CakeEmail', 'Network/Email' );

class InquiriesController extends AppController {

  public $helpers = array ( 'form', 'Xform.Xformjp', 'Cakeplus.Formhidden' );

  public function form() {

    if ($this->request->is('post')) {
      if (!empty($this->request->data)) {

        //valideteチェック
        $this->Inquiry->set($this->request->data);
        if($this->Inquiry->validates()){
          //submitのタイプの判定
          if (isset($_POST['confirm'])) {
            $type = 'confirm';
          } elseif (isset($_POST['submit'])) {
            $type = 'submit';
          } elseif (isset($_POST['back'])) {
            $type = 'back';
          }
          //sbumit tyep ごとに処理を分ける
          switch ($type) {
            case 'back': //修正などがあった時のback処理
              break;

            case 'confirm': //確認画面の処理
              //これを宣言するとフォームがフリーズしてくれる
              $this->params['xformHelperConfirmFlag'] = true;

              break;
            case 'submit': //送信する

              $vars = $this -> request -> data['Inquiry'];
              $vars['update_date_set'] = date ( 'Y-m-d H:i:s', time() );

              $email = new CakeEmail ();

              $email  -> config ( 'inquiry' )
                  // 送信元
                  //->from(array($this->request->data['Contact']['email'] => '○○お問い合わせ'))
                  // 送信先
                  // ->to()
                  // BCC, お問い合わせした人にもコピーを送りたい時とか
                  // ->bcc($this->request->data['Contact']['email'])
                  // テンプレート変数設定
                  -> viewVars( $vars )
                  // 使用するテンプレートの設定, 本文の方 contact, レイアウト contact
                  -> template('inquiry', 'inquiry')
                  // メール件名
                  -> subject('お問い合わせ')
                  ;

              if ($this->Inquiry->save($this->request->data)) {

                if ( $email -> send () ) {
                  $this -> Session -> setFlash ( '問合せ完了' );
                  $this -> redirect ( array ( 'action' => 'index' ) );
                } else {
                  $this -> Session -> setFlash ( 'お問い合わせに失敗しました' );
                }

              } else {
                $this->Session->setFlash( 'データの保存に失敗しました' );
              }
              break;
          }
        }
      }
    }
  }
}
--------------


入力項目とは別に項目を設定する場合などは、「$vars['update_date_set'] = date ( 'Y-m-d H:i:s', time() );」のような感じで $varsに入れていきましょう。
確認メールの中で値を受け取るときは、配列のキーで設定した項目名がそのまま変数名として受け取れます。

また、確認メールで「<pre class="cake-error"><a href="javascript:void(0);" onclick="document.getElementById('cakeErr51dd21afcee1f-trace')........」のように、メール本文に何か入力した覚えがない文字列が出てきている場合は、おそらく、その変数が設定されていません、というエラーメッセージです。
HTMLのタグの部分を、HTMLファイルにコピペして表示させたりすると書かれている内容が分かると思います。


続いて、確認メールのテンプレートです。
ここでは、変数は、入力項目として設定されている変数名をそのまま記述すれば OKです。

--------------(/View/Emails/text/inquiry.ctp)
お問い合わせがありました。

【タイトル】
<?php echo $title; ?>

【本文】
<?php echo $body; ?>

【メール】
<?php echo $mail; ?>

【送信日】
<?php echo $created; ?>
--------------


署名のファイルを設置します。
こちらは、テキスト情報のため、中身はなんでも問題ありませんが、本番運用する場合はしっかり凝った方がいいファイルでしょうね。

--------------(/View/Layouts/Emails/text/inquiry.ctp)
<?php echo $content_for_layout;?>

hogehoge@xxxxxx.com
株式会社あいうえお
署名のファイルですよ
--------------

これでメールの送信が行えます。
[ 2013年07月22日 13:55 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

ローカル環境の XAMPPからメールを送信できるように設定する

ローカル環境の XAMPP環境で開発を行っており、メールフォームを作成する必要が出てきたのですが、デフォルトのローカルの XAMPP環境からはメールが送信できません。
そのため、私は下記のサイトを参考にして構築を行いました。

http://log.noiretaya.com/139

XAMPP環境を含め、ローカル環境からメール送信ができるようにするための解説サイトは多々ありましたが、ここを参考にした理由は、設定した後のデバッグ方法や、テスト送信するサンプルスクリプトまで載せてあったからです。

ちなみに、この仕組みは、ローカルからメールを送信できるようにしているわけではなく、ローカルPCにある sendmailのプログラムからメール送信の SMTPサーバ(ここでは、Gmailの SMTPサーバ)に接続し、そのサーバ経由でメールを送信している、ということになります。
そのために、ローカル環境に sendmailの設定をして...といったところまで勉強を含めて作ってみたいという方はほかのサイトを探してください!


で、上記の参考サイトをもとに構築していく際に 2点ほど間違いやすい点がありましたので説明しておきます。

5行目の「sendmail_path = "\"\xampp\sendmail\sendmail.exe\" -t"」のコメントを外すのに合わせて、その下にある「;sendmail_path = "C:\xampp\mailtodisk\mailtodisk.exe"」はコメントにする必要があります。

そうしないと、せっかく設定した「sendmail_path」の値が元の設定に上書きされてしまいまして、「\Device\Harddisk2\DR2ディスクがありません」のようなエラーが出てくるようになると思います。

また、記事の中でも説明してありますが、「『force_sender』は指定しても意味がないように思うんですが」とありますが、指定しないと勿論動きませんが、適当なメールアドレスにしても動きません。
私の場合は、「auth_username」で設定したものと同じ Gmailのメールアドレスを設定することで送信ができるようになりました。

もしかしたら、これはプログラム上のエラーがあるというのではなく、Gmail側のスパムフィルタなんかに引っかかっているのではないか、とも考えています。


また、デバッグする際に「debug_logfile=debug.log」のコメントを外した場合は、問題なく動くようになったタイミングで元に戻しておく方がいいと思います。
メールを送るたびにログが出力されていきますので、気付いたらすごいファイル容量になっていたり...ということもあるかもしれません。

なお、php.iniファイルの修正をした際には、PHPの再起動をしてくださいね。
[ 2013年07月16日 08:05 ] カテゴリ:システム開発関連技術 | TB(0) | CM(0)

MySQLの「tinyint(1)」の悲劇 Boolean型になるとは...

CakePHPのプログラムを作っていて、登録された値が想定していた値にならず困っていました。
まだまだ CakePHPの初心者の私はプログラムの記述が間違ってるのだとさんざん悩んでいました。

登録する項目は下記の「authority」の項目に「1:システム管理者」「2:マネージャー」「3:オペレーター」「4:一般ユーザ」といった 4種類の権限を保存するというものでした。

------------------------
CREATE TABLE IF NOT EXISTS `users` (


`authority` tinyint(1) NOT NULL DEFAULT '1',


) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ;
------------------------

何度も何度もプログラムを見直しましたが、2、3、4のフラグを保存しようとしても、「1」としか保存されないのです。
Bakeしたものをベースに、フラグのコードをテキストに変換するために、「authority」の項目の日本語の配列を呼び込んでいるだけで、特に大きな変更はしておらず、間違えようがありませんでした。

それでも何度も見直し、変数を書き換えてみたりしながら数時間悩むことになりました...


結論!
MySQLの「tinyint(1)」は、Boolean型と同じです!

「tinyint(1)」の「(1)」は、「1桁」という意味ではなく、「1bit」という意味になります。
そのため、この項目に入るのは「0」「1」で、Boolean型と同じになります。
この辺が、例えば「varchar(255)」の「(255)」と違うために間違える原因になります。

また、詳しくは MySQLの型を調べてもらえばわかると思いますが、「tinyint」は 1バイトで「-128~127」。「int」は 8バイトで「-2147483648~2147483647」が入ります。

「tinyint(2)」や「int(6)」といった設定をしてもその桁数の数値が保存されるわけではないため、tinyint、intの場合は「(n)」の設定をする必要がありません。(意図して設定する場合は別ですが。)

逆に、桁数を指定して設定をしたい場合は、DECIMAL型(NUMERIC型も同じ意味)を使い、「DECIMAL(5,2)」のように指定すべきでしょう。
「DECIMAL(5,2)」は、総桁数 5桁で、小数点以下 2桁(整数 3桁、小数点以下 2桁)という意味になります。

また、下記のサイトなども参考になりますので、併せて読んでいただければ理解が深まると思います。

MySQLの型で気になった(tinyint,int) (3)
http://plaza.rakuten.co.jp/hknopage/diary/200903240000/
MySQL 5.1 の boolean 型を検証
http://1000g.5qk.jp/2010/11/15/mysql5-1%E3%81%AEboolean%E5%9E%8B%E3%82%92%E6%A4%9C%E8%A8%BC/
[ 2013年07月11日 20:21 ] カテゴリ:MySQL | TB(0) | CM(2)

CakePHP 2.3でファイルをアップロード・その2 ファイル名を乱数で設定

先週、CakePHP2.3でファイルのアップロード処理を作る(http://ssgiken.blog.fc2.com/blog-entry-24.html)という記事を書きましたが、今日はその続きです。

前記事のファイルアップロード処理を作る際に、ファイル名をもとのファイル名ではなく、乱数による自動生成されたファイル名を付けるという方法も試してみました。

今回は乱数を元にファイル名を付けていますが、シリアルナンバーを付けたい、といった場合などもこの方法を元にすれば対応は可能ですね。


ベースにしたのは、前回も書いた下記のサイトです。
http://www.almondlab.jp/labs/1043

そのため、View、Model、および、DBの構造は、上記のページと同じですので割愛します。


--------------(/Controller/UploadsController.php)
<?php
App::uses('AppController', 'Controller');
/**
 * Uploads Controller
 *
 * @property Upload $Upload
 */
class UploadsController extends AppController {

  public $helpers = array('Html', 'Form');

  public function index() {
    $this->Upload->recursive = 0;
    $this->set('uploads', $this->paginate());
  }

  public function add() {
    if ($this->request->is('post')) {

      // 2013.07.19 add 乱数を発生させる処理
      $rand = 'abcdefghijklmlopqrstuvwxyzABCDEFGHIJKLMLOPQRSTUVWXYZ0123456789';
      $ary_rand = str_split ( $rand );

      // array_rand はランダムに配列のキーを取得
      for ( $i = 1, $str = ""; $i <= 32; $i++ ) {
        $rand_key = array_rand ( $ary_rand, 1 );
        $str .= $ary_rand[$rand_key];
      }

      $tmp = $this->request->data['Upload']['file']['tmp_name'];
      if(is_uploaded_file($tmp)) {
        $file_name = $str;
        $file = WWW_ROOT.'files'.DS.$file_name;

        if (move_uploaded_file($tmp, $file)) {
          $this->Upload->create();
          $this->request->data['Upload']['file_name'] = $file_name;

          if ($this->Upload->save($this->request->data)) {
            $this->Session->setFlash(__('The upload has been saved'));
            $this->redirect(array('action' => 'index'));
          } else {
            $this->Session->setFlash(__('The upload could not be saved. Please, try again.'));
          }
        }
      }
    }
  }

}
--------------

途中に乱数を発生させる処理を追加し、ファイル名をそれに置き換える処理になっています。
この処理の要は「move_uploaded_file」でしょうね。それ以外は特に難しいことはないと思います。

途中のコメントの「array_rand はランダムに配列のキーを取得」の次の行にある「32」がランダムで生成する文字列の文字数になりますので、ファイル名の長さを調整したい場合はその数字を変えてもらえればいいでしょう。

また、ファイル名をランダムで取得するには「md5」などが使われていたりもしますが、正確には乱数を取得する関数ではありませんので、それを理解したうえで使った方がいいでしょうね。
[ 2013年07月08日 07:27 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)

CakePHP 2.3でファイルのアップロード処理を作る

CakePHP2.3でプログラム開発を行っていますが、ファイルのアップロード処理についてググっていたら、下記のサイトに行き当りました。
ほほー。ファイルアップロードにも Pluginがあるのか、と思ったものの、このページではプラグインに頼らない、と書いてありましたので、私も頼らずに実際に作ってみることにしました。(記事が書かれたのが 2011年2月ですので、その後のバージョンアップなどでどうなったかは分かりませんが。)
http://lambdagroove.blogspot.jp/2011/02/cakephp.html

簡単なファイルのアップロードであれば下記のページに従って作っていけば、簡単に出来上がります。
http://www.almondlab.jp/labs/1043

上記の方法では、実運用に際してファイルの削除処理などが必要になってくると思います。

また、ファイルの管理を煩雑にしないために、画像などのファイル情報を DBに保存したい、という場合もあるかと思います。
その場合は、下記のページが参考になりました。
http://c-brains.jp/blog/wsg/10/06/05-074544.php

ですが、このページの通りに作っていくと、「Viewファイルの記述がおかしい」というエラーになってしまいましたので、その前に作った簡易フォームのスクリプトを借りることにしました。
(CakePHP 2.0では echoのエイリアスである e()が使えなくなっていますので、そのほかの不具合もバージョンの違いによるものと思われます。)

また、ファイルが jpeg固定でしたので、それを可変にし、ついでに元ファイルのファイル名、ファイルサイズといった情報も取得するために、テーブルを拡張したり、そのままではうまく画像が呼び出せなかったために、画像の確認するためのファイルなどを作りましたので、あわせてそちらも紹介いたします。


--------------(テーブル)
CREATE TABLE `images` ( 
  `id`            int(11)     NOT NULL AUTO_INCREMENT, 
  `filename`      varchar(60) NOT NULL, 
  `contents`      mediumblob  NOT NULL, 
  `moto_filename` text        NOT NULL, 
  `filetype`      text        NOT NULL, 
  `filesize`      int(11)     NOT NULL, 
  PRIMARY KEY (`id`) 
); 
--------------


--------------(/View/Images/index.ctp)
<?php echo $this->Form->create('Image', array('action' => 'add', 'type' => 'file')); ?>
<?php echo __('Add Image'); ?> <?php echo $this->Form->file('image'); ?>
<?php echo $this->Form->end(__('画像を追加'));?>

<?php echo __('Images'); ?>

<?php foreach ($images as $image) : ?> <?php endforeach; ?>
<?php echo __('id'); ?> <?php echo __('file_name'); ?> <?php echo __('contents'); ?>
<?php echo h($image['Image']['id']); ?> <?php echo h($image['Image']['filename']); ?> <?php echo $this -> Html->link(__("/images/contents/{$image['Image']['filename']}"), array('action' => "/contents/{$image['Image']['filename']}" ), array ( 'target' => '_blank' ) ); ?>
--------------


/View/Images/contents.ctp は、ないとエラーになりますので作成する必要がありますが、中身は空のファイルになります。

--------------(/View/Images/contents.ctp)
--------------


/Controller/ImagesController.php は、以下のようになります。
それぞれの処理の解説は、参考にしたバシャログさんのサイトを見ていただく方が分かりいいかと思います。

--------------(/Controller/ImagesController.php)
<?php
class ImagesController extends AppController {

  public $helpers    = array ( 'Html', 'Form', 'Session' );
  public $components = array ( 'Session' );


  var $uses = array('Image');
  function index(){
    $images = $this->Image->find('all');
    $this->set(compact('images'));
  }

  /**
   * 画像を登録する
   */
  function add(){
    $limit = 1024 * 1024;
    debug($this->data);

    // 画像の容量チェック
    if ($this->data['Image']['image']['size'] > $limit){
      $this->Session->setFlash('1MB以内の画像が登録可能です。');
      $this->redirect('index');
    }
    // アップロードされた画像か
    if (!is_uploaded_file($this->data['Image']['image']['tmp_name'])){
      $this->Session->setFlash('アップロードされた画像ではありません。');
      $this->redirect('index');
    }
    // 保存
    $image = array(
      'Image' => array(
        'filename' => md5(microtime()) . '.' . $extension = end(explode('.', $this->data['Image']['image']['name'])),
        'contents'      => file_get_contents($this->data['Image']['image']['tmp_name']),
        'moto_filename' => $this->data['Image']['image']['name'],
        'filetype'      => $this->data['Image']['image']['type'],
        'filesize'      => $this->data['Image']['image']['size'],
      )
    );
    $this->Image->save($image);
    $this->Session->setFlash('画像をアップロードしました。');
    $this->redirect('index');
  }


  function contents($filename) {
    $this->layout = false;
    $image = $this->Image->findByFilename($filename);
    if (empty($image)) {
      $this->cakeError('error404');
    }
    header('Content-type: ' . $image['Image']['filetype'] );
    echo $image['Image']['contents'];
  }
}
--------------

また、今回追加した MIMEタイプなどの情報は、下記サイトを参考にして作成しました。
http://vitafacio.sakura.ne.jp/wordpress/?p=35


また、http://localhost/cake/images/contents/xxxxxxxx.jpg のような形式では文字化けしたような文字が表示され、なぜかうまく表示されずさんざん悩んだのですが、それを改善させる方法を見つけることはできませんでした。
PDFや、csvファイルは問題なく表示されますが、jpeg、gifなどの画像ファイルが正しく表示されないという不具合でしたので、おそらく「header('Content-type:.......」の出力部分がうまく処理されていないのだろうと思うのですが...


ただ、実際の使用方法に近い記述の方法で確認したところ、正しく表示されましたので、それで良しとしたところもあります。

--------------(/webroot/test.php)
<img src="./images/contents/xxxxxxxx.jpg">
--------------

上記のファイルを作成し、webrootにおいてアクセスすると画像ファイルも無事に表示されましたので、画像も正しくアップロードされていることが確認できました。
[ 2013年07月01日 07:18 ] カテゴリ:CakePHP 2.x | TB(0) | CM(0)
プロフィール

エス技研

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

FC2ブログランキング
FC2カウンター
FC2拍手ランキング
GoogleAdWords
カレンダー
06 | 2013/07 | 08
- 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 31 - - -
検索フォーム
ブロとも申請フォーム
QRコード
QR
フリーエリア


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