ファイルアップロード機能でハマった話 〜デバックスキルをアップせよ〜

  • このエントリーをはてなブックマークに追加

現在PHPで開発を行なっているのですが、
先日、ファイルのアップロード機能を実装していたときに
思わぬところでハマってしまいました。

「ファイルのアップロードなんて散々やってきたから楽勝だろ!」
と思っていたのに、まさかこんな落とし穴があるとは……

珍しいケースだったので、同じようなことでハマっている人はいないと思いますが、
これがきっかけで、少しだけデバックスキルが上がったと感じたので、
よろしければ参考にしてみてください。

こんな方にお勧めの記事です。

  • いつもデバックに時間がかかって、作業がなかなか進まない
  • ソースコードを読み解くのに時間がかかる

作ったもの

今回私が作った機能はこのようなものです。

See the Pen MMRLvJ by masashi kurashima (@masashikurashima) on CodePen.0

 

ざっくり説明すると、

HTML:inputタグの上にlabelタグを重ねてCSSでデザインを生成。formタグでcheck.phpにPOST送信する
JS  :ファイルが選択されるとstyleとtextを切り替えて、下に選択したファイル名を表示させる
CSS :JSで制御されて切り替わるスタイルを用意

という感じです。

ここまで作って試しにアップロードしてみたところ、
PHPで全くファイルを受け取ってくれませんでした。

調べてみたところ、PHP側には全く問題はなかったのですが、
このフロント側で致命的な間違いが2箇所ありました。

さて、お分かりになりますか?

 

間違えていた箇所

1.formタグに……

まず1箇所目は、フォームタグに

enctype="multipart/form-data"

の記述が足りませんでした。
これじゃあアップできないのも無理ありませんよね。
(enctypeについてはこちらに詳しく書かれていました。)

このミスは比較的早く気づきました。
問題は次のミスです。

2.JS側に謎の記述が……

1つ目のミスにはすぐ気づいたものの、それでもアップロードができない……
色々と試したけれど原因がわからず、現場のリーダーに相談して、
一緒にデバックをしたところ、やっと原因がわかりました。

原因はJSの4行目に書かれていたこの記述

$(this).val('');

なんだこりゃ!?
こんなの書いた覚えないぞ!

なんとこのjQueryの処理で、ファイルを選択する度にinputタグのvalueの値が初期化されていたのです。
そりゃアップロードできないはずです……

今回の原因と反省

上記2つの箇所を修正して、やっとファイルのアップロードができるようになりました。
それにしてもなんでこんなミスをしてしまったのか……
起こった原因とそこから得た教訓をまとめてみました。

原因①:ソースコードの読み解きが足りなかった

実はこのソース、私が全て書いたのではなく、別のコーディング会社に外注していたものでした。

フロント側の機能を外注で作ってもらい、私が作っていたPHP側の機能と組み合わせる作業をしていたときに起こった出来事だったのです。

外注していたフロント側のソースをもらったときに、どのような処理が書かれているのかちゃんと読み解く前に実装を始めてしまったため、
jsに書かれていた $(this).val(''); この処理を見落としてしまったのです。

教訓①:ソースコードを理解した上で開発を行うこと

今回のように外注した場合や、同じチームの別の人が作ったものだった場合、(もちろん自分で作った場合も)、
どのような処理をしているのか、理解した上で開発をすること。

「動いているからOK」という考え方はしないこと。

原因②:エラー原因を自分で決めつけてしまっていた

1つ目のエラー原因、enctype="multipart/form-data"
を書き忘れていたことを発見したまではよかったのですが、

それでも動かなかったときに私は「formタグの書き方がまだ間違っているはずだ」と考えてしまい、
先に進めなくなってしまいました。

エラーの原因を自分で決めつけてしまったことが、エラーを発見できない原因となってしまいました。

現場のリーダーに相談して、リーダーが実際に行ったデバックは以下の通り。

1、同じformタグの中に、別のinputタグを記述(label、classは記述せず、inputタグのみ)
→ファイルはアップロードできる→formタグに問題は無い

2、アップロードが成功したinputタグにlabelを重ねて、再度アップロード
→アップロード成功→labelタグの書き方は問題ない

3、ではinputタグを制御しているjs側に問題があるのではないかと仮定
→jsの処理を見直したところ、問題の記述を発見

必死にformタグを書き換えていた自分が恥ずかしい……

教訓②:目の前の事実を見て、原因を特定すること

たぶんここが間違っているんだろうな」という先入観を持ったままデバックを行わないこと。

1つ1つの処理・記述に対して細かくデバックを行うこと。

突き詰めれば、全ての処理は「期待通りに動く」か「期待通りに動かない」の2パターンしかない。

細かなデバックを繰り返し、「動くか動かないか」の事実を積み重ねていくことでしか、エラーは発見できない。

まとめ

いかがだったでしょうか。

今回ハマった箇所は、我ながらレアなケースだった……
というか、蓋を開けてみればただの恥ずかしいミスでしたね(笑)

けれど、このような変なミスに遭遇することは意外とたくさんあると思います。

「なんでこんなミスをしたんだろう?」ってなった時に、
「まあ、レアなケースだからしょうがないか」と言って終わらせるのではなく、
自分なりに「起こった原因」と「そこから得た教訓」をまとめてみることで、
エンジニアとしてのスキルが上がっていくのではないでしょうか。

それではまた!