【CakePHP】フォームを使ってレコードを編集したつもりが、レコードが増えてしまう現象

ドットインストールのレッスンを参考に
データベースのレコードを編集する機能を実装してみました。

コントローラ、ビューのコードはこんな感じです。

public function edit($id = null) {
        $this->Item->id = $id;
        if ($this->request->is('get')) {
            $this->autoLayout = false;
            $this->request->data = $this->Item->read();
        } else {
            if ($this->Item->save($this->request->data)) {
                $this->Flash->success(__('Your post has been saved.'));
                $this->redirect(array('action'=>'index'));
            } else {
                $this->Session->error(__('failed!'));
            }
        }
    }
<table>
    <tr>
        <?php echo $this->Form->create('Item', array('url' => 'edit'));?>
        <td><?php echo $this->Form->input('column_01', array('label' => false));?></td>
        <td><?php echo $this->Form->input('column_02', array('label' => false));?></td>
        <td><?php echo $this->Form->input('column_03', array('label' => false));?></td>
        <td><?php echo $this->Form->end('編集完了');?></td>
    </tr>
</table>

これをこのままテストしてみると、
「編集完了」を押すたびに新しい記事ができてしまう現象が起きてしまいました。
「編集 = 上書き」のつもりが新しい項目が作られてしまいました。

 

さっぱりわかんねえよ、と思いながら
CakePHPのチュートリアルをみていると、こんな記述を見つけました。

 

((ひとつ注意: CakePHP は、「id」フィールドがデータ配列の中に存在している場合は、 モデルを編集しているのだと判断します。もし、「id」がなければ、(add のビューを復習してください) save() が呼び出された時、CakePHP は新しいモデルの挿入だと判断します。))

 

というわけで、フォームの入力内容にidがあるか否かで
上書きか新規作成かが決まるとのことでした。これを踏まえてビューを修正します。

<?php
<table>
    <tr>
        <?php echo $this->Form->create('Item', array('url' => 'edit'));?>
        <td><?php echo $this->Form->input('id', array('type' => 'hidden'));?></td>
        <td><?php echo $this->Form->input('column_01', array('label' => false));?></td>
        <td><?php echo $this->Form->input('column_02', array('label' => false));?></td>
        <td><?php echo $this->Form->input('column_03', array('label' => false));?></td>
        <td><?php echo $this->Form->end('編集完了');?></td>
    </tr>
</table>
?>

idをフォームで入力するということはまずないでしょうから、
普通はhiddenを付けておくようです。

 

よーく考えずにコピペして、ちょこちょこ修正して…というやり方だと、
こういう所がおざなりになりがちですね。

【CakePHP】フォームの作り方

CakePHPを使って入力フォームを作る方法を説明します。

まずはコントローラでFromヘルパーを読み込んでおきます。

public $helpers = array('Form');

続いて次の3行をビューファイルに書きます。

<?php echo $this->Form->create('Item', array('url' => 'add'));?>
<?php echo $this->Form->input('column_01');?>
<?php echo $this->Form->input('column_02');?>
...
<?php echo $this->Form->input('column_n');?>
<?php echo $this->Form->end('送信');?>

基本はこれでOKです。
createとendというものがありますが、この2つの組で1つの<FORM>htmlが作られます。
入力項目を追加する際はcreateとendの間に上の例のinputみたいなものを
追加していきます。

 

createは第2引数にフォームの属性値を配列で与えることが出来ます。
今回使っている'url'ではsubmitした際のアクションや遷移先を指定できます。
何も指定しない場合はビューのファイル名と同じアクションが実行されます。

endの第1引数に文字列を与えることで、submitボタンのラベルを指定できます。

 

 

【XAMPP】データベースから読み込んだTEXT型データの文字化け解決

データベースから読み込んだ日本語のTEXT型データが文字化けしてしまったときの 解決法をまとめておきます。

1. カラムの文字コードをチェック

phpMyAdminでカラムの追加をする場合、照合順序という項目があると思います。
これが文字コードの設定になっています。
デフォルトの場合(何も選択していない)、文字コードが 「latin7_general_ci」に設定されているので、こちらを「utf-8_general_ci」など、 日本語に対応した文字コードに変更します。

すでに追加してしまったデータはここを変更しても直らない場合があります。

2. XAMPPの設定ファイル変更

xampp/phpフォルダにあるphp.iniを設定します。
次の8行のコメントアウトを外し、値を以下のように変更します。

mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = auto
mbstring.http_output = UTF-8
mbstring.encoding_translation = On
mbstring.detect_order = auto
mbstring.substitute_character = none
mbstring.func_overload = 0


続いてxampp/mysqlフォルダを開き、my.iniファイルの変更をします。
「## UTF 8 Settings」とだけ書かれた行があるので、その下にある
次の4行コメントアウトを外します。

collation_server=utf8_unicode_ci
character_set_server=utf8
skip-character-set-client-handshake
character_sets-dir="C:/xampp/mysql/share/charsets


※init-connect=SET NAMES utf8のコメントアウトを外すと、自分の環境では
phpMyAdmminにアクセスした時MySQL server has gone awayエラーが出てしまいました。
あとセキュリティ的にも良くないらしいです。

続いて [client][mysqldump][mysql]という3つのセクションを探して
それぞれ以下のように変更します。

[client]
# password = your_password
port = 3306
socket = "C:/xampp/mysql/mysql.sock"
default-character-set = utf8


[mysqldump]
quick
max_allowed_packet = 16M
default-character-set = utf8


[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
default-character-set = utf8


最後にmysqlを再起動すれば 文字化けが直っていると思います。

参考にしたサイト

qiita.com

【CakePHP】ドットインストールのレッスンを理解する

先日ドットインストールのレッスン「CakePHP2入門」を一通りやってみたのですが、
感想としては「なるほど、わからん。」といった感じでした。

 

ドットインストールのレッスンは非常にわかりやすく、私もここ最近大変お世話になっていたのですが、
今回のレッスンは「ざっくり流れを学ぶ」ような側面が強く、ソースコード
「今はここの意味がよくわからないかもしれませんが、とりあえず書いてみてください」と天下り的に教えられることが多かったように思います。
頭の悪い人な私は最後まで数多くの疑問点が残ったままだったので(笑)、CakePHP公式のチュートリアルを見ながらもう少し詳細に学んでみることにしました。
内容は「記事の投稿・編集・削除ができるブログサイトを作ってみよう!」というものでした。

なんとまあ、ドットインストールのレッスンはここを参考に作られてたみたいですね。
けっこー長い文章ですが、語り口が妙に軽快なのもあって割りと楽しく読めました。

 

今回は、命名規則に関することをまとめていきます。

 

命名規則の謎
レッスンの中で何箇所か「ファイルや変数の名前をこうしてね!」と指示される場面があったと思います。
CakePHPでは命名規則が超大事な要素となっていて、
ちゃんとした名前をつけているかどうかが動作に直接関わってきます。

嫌でも命名規則の大切さを仕込まれるわけですね。

    1. モデルのファイル名とコントローラのファイル名
      Post.php』というモデルファイルを作った場合、
      CakePHPは「これはPostsController.phpってコントローラで操作するんやろなあ」と解釈します。
      『PostsController.php』の中では
      $this->Post->find('all')
      みたいな形でモデルを参照します。

    2. ビューのファイル名
      『PostsController.php』は『Posts.php』というモデルと、『app/view/Posts』というディレクトリの橋渡しの役割を担います。
      基本的にはこのディレクトリの中にページの表示内容を『index.ctp』とか『add.ctp』などといった形で書いていきます。
      ユーザーが行きたいであろうページ(indexとか)やアクション(addとか)にアクセスしたときの動作は『PostsController.php』内に

      public function index() {
      $this->set('posts', $this->Post->find('all'));
      }
      といった同名の関数を定義して書いていきます。


    3. データベースのテーブル名
      テーブル名を『posts』としておくと、モデル『Post.php』が
      勝手にテーブルを配列として認識してくれます。
      テーブルに’modified’ と ‘created’ というフィールドを用意しておくと、CakePHPがレコードの作成日時、最終更新日時を勝手に管理してくれるようになります。

 

XAMPP + cakePHPの導入

cakePHPを動かせる環境を作りたいな~~ということで
vagrantの導入を試みたのですが、初回起動が10時間たっても終わりません(# ゚Д゚)

 

というわけで、会社の先輩に教えてもらったXAMPPというやつを導入してみることにしました。
結果として導入成功したわけですが、所々で詰まってしまいました。
そのへんの対処法を含め、備忘録としてまとめておこうと思います。

 

そもそもXAMPPとは?

webアプリの開発に必要なソフトウェアやツールを一括でインストールしたり、
一元的に管理できるというとっても便利なパッケージです、

windowsmacの環境にそのままインストールできるので、
vagrantのように仮想マシンを立ち上げなくても利用できるというメリットがあります。

ただし、動作や設定に関するファイルが自分のPCのストレージにそのまんま作られるので、windowsのシステムと微妙に競合してしまいそうな怖さはあります。
(自分は今のところなんともなっていませんが)

XAMPPの導入

こちらのページを参考にしました。

techacademy.jp

とくに気をつけるところはないかと思います。
今回自分がインストールしたのはバージョン5.6.31です。
トップページ上部のメニューから「ダウンロード」ページに行くと
色々とバージョンが選べます。


ところでXAMPPはどうもFTPツールとしてfilezaillaを推奨してるみたいですが、
個人的にはwinSCPのほうが好きですね。
(ファイルを保存するときに逐一聞かれないので)

 

Windows起動時に自動でApacheを起動させる方法

 こちらを参考にしました。

www.adminweb.jp

cakePHPの導入

今回自分はcakephp2系を使いたかったのですが

公式サイト https://cakephp.org/jp/ だと2系のダウロードリンクを見つけられませんでした。
なので公式のgithubから 2.10.3をダウンロードしました。

github.com

cakePHP初回起動時の色々出てくるエラーを消す方法

「Debugkitがインストールされてないよ」といったエラーが出てきますので、
こちらを参考に対処しました。

blog.livedoor.jp

 Debugkitは↓のリンクからダウンロードするのですが、
masterのものはcakephp3系用になってます。
今回はcakephp2系をダウンロードしたので、branchから2.2のバージョンをダウンロードします。

またDebugkitを置くディレクトリは
プロジェクトのディレクトリ/app/pluginsが正しいのですが、
プロジェクトのディレクトリ直下にもpluginsというディレクトリがあります。
ややこしいですが間違えないようにしてください(私は間違えました)

【PHP】$_GETや$_POSTは何者なのか

以前webアプリを開発した際
『$_GET』とか『$_POST』とかいった変数をプログラムの中で使っていました。

これまでの所、これらの正体やら挙動やらはあまり気にせず
「なんか知らんけどフォームの送信内容が入ってくれてる便利なやつ」くらいに思っていました。

しかしながら、今後PHPに習熟しようと思えば
やはりこれらについてできるだけ正確に理解しておいたほうが良いかと思います。

 

というわけで今回は、『$_GET』や『$_POST』について、
簡単にですが調べたことをまとめていきます。

 

  • こいつらは何なのか

『$_GET』や『$_POST』は『スーパーグローバル(変数)』と呼ばれるものに属しています。

スーパーグローバルには『$_GET』や『$_POST』の他にも、
『$_REQUEST』とか『$_PUT』『$_DELETE』なんかがありますが、今回は触れないでおきます。

 

  • 『$_GET』や『$_POST』の役割は?

『$_GET』や『$_POST』には
「ユーザーが入力フォームを使ってサーバーに送信した内容」が配列として保持されています。

クライアント(ここではユーザーが使っているPCやスマホ)がサーバーにデータを送信する方法(メソッド)は色々あります。
代表的なものがGETメソッドやPOSTメソッドです。

 

GETメソッドで送られたデータをphp側で参照する際に$_GETを使い、
POSTメソッドで送られたデータを参照する際には$_POSTを使います。

 

  • GETメソッドとPOSTメソッドの使い分けは?

送信内容を公開したいならGET、
秘密にしたいならPOSTを使います。

フォームの送信先が「localhost/sample.php」だったとしましょう。
このフォームに「id」という項目があり、そこに「2」を入力したとします。

GETメソッドでデータを送信した場合、当然ですが「localhost/sample.php」がサーバーから送られきます。
このときブラウザに表示されるURLを見ると
localhost/sample.php?id = 2」のように、URLの末尾にGETの送信内容が表示されます。

この性質を利用して、GETメソッドは
送信内容とその結果を共有させたい時」に使います。
検索結果やブログの記事などに使います。

 

続いてPOSTの例を見てみましょう。

フォームの送信先は先程と同じく「localhost/sample.php」で、送信内容は「id = 2」だったとします。

この場合もlocalhost/sample.phpがサーバーから送られてきますが、GETと違い、URLはそのままです。
つまりURLを見ても送信内容はわかりません。

というわけで、POSTメソッドは送信内容を秘密にしたいときに使用します。
入力フォームにIDとパスワードを入れてマイページにアクセスする、といったことはよくありますが
マイページのURLにIDとパスワードが含まれているとどうなるでしょう?
もしもこのURLが流出してしまったら、どこの誰でもマイページにアクセスできるようになってしまいます。

 

 

まとめ

  • PHPにはスーパーグローバルという変数がある。
    $_GETや$_POSTはその一部。
  • $_GETや$_POSTには、呼び出し元のhtmlにあるformの
    送信内容が配列として保持されている
  • 送信内容を共有したい時にGET,
    秘密にしたい時POSTを使う

 

参考にしたサイト

gray-code.com

 

Chromeデベロッパーツールの便利な使いかた

私はwebページを開発する際主にchromeで動作テストを行っています。
デバックの際もChromeデベロッパーツールを使うことが多いのですが、
やってることはエラーログやCSSのプロパティを確認することぐらいでした。

せっかくなので、知っておくと開発が捗りそうな機能を知っておきたいと思い
勉強してみました。

今後も便利な機能を見つけたら随時更新していこうと思います。

 

起動してすぐ要素選択モードを使う

ctrl + shift + cを押すと、
要素選択モードに入った状態でデベロッパーツールが起動します。

マウスホバーした時の状態を確認する

 f:id:kento0824jp:20170923155854p:plain
stylesタブの:hov(赤で囲った所)を押すと、hoverやvisitedの際のスタイルを確認できます。

色を直感的に選択する

stylesタブにあるcolorの左の「□」をクリックするとカラーピッカーが出てきます。
そのままwebページの画面にカーソルを動かすと、スポイトのようにwebページ内の好きな色を選択して、そのカラーコードを確認できます。

f:id:kento0824jp:20170923160511p:plain

console.logなどを使わずJavaScriptの変数を確認する

sourceタブを開き、変数を確認したいjsファイルをsourcesから選択します。
行番号を押すとその行にブレークポイントを設定できます。
変数を確認する方法は2つあります。

変数が多すぎるときはscopeを隣のwatchに切り替えて、探したい変数名を入力するといいです。

f:id:kento0824jp:20170923161847p:plain

こんな感じのボタンが表示されていますが、停止ボタンの一つ右から順に
ステップイン・ステップオーバー・ステップアウトという3つの操作になっています。
いずれも停止位置の次の処理に進むことが出来るのですが、微妙にやり方が違います。

  • ステップイン
    次の処理に進む。次の処理が関数ならその中に(外部ファイルであろうと)進む
    1処理ずつ馬鹿丁寧に追っていくイメージ
  • ステップオーバー
    ステップインと違って関数の中には入らない。停止位置の関数の処理を終わらせて次の処理に進む。
  • ステップアウト
    停止位置が関数なら、その関数の処理を一通り終わらせて関数の呼び出し元(外部ファイルであろうと)に移動する。

 

プロパティの値を微調整する

CSSのプロパティの値を選択時、矢印キーを押すと
値の微調整が出来ます。

もちろん手入力でも良いのですが、そこまで精度の求められない調整をするなら、
この方が早いと思います。

 

  • 参考にさせていただいたサイト

commte.net

ics.media

dackdive.hateblo.jp