todoアプリの頭の文字しか表示されない不具合
こちらのサイトでtodoアプリを作りながらjsについて勉強していたときのこと。
写真のように、todoを投稿すると頭の1文字しか表示されない不具合が発生しました。
デベロッパーツールで追って行ったところ、中のデータはちゃんと「今日の予定」と入っているのに、画面に出力される部分で「今」だけになってしまっていることが判明。
原因となっていたコードがこちら。
×誤りバージョン
○正解バージョン
何が違うのか?
はい、第二引数のvaluesですね!
入力するtodoの文字数が毎回異なるため、毎回引数に入ってくる文字数の個数が異なる→「可変長引数」
引数の前に「...」をつける書き方をして「これは可変長引数ですよ」と宣言しなければいけなかった→「残余引数(レストパラメータ)」
引数の前に「...」をつけなかったことにより、引数が1個に固定されてしまい、頭の文字のみ表示された→不具合の原因
ということっぽいです。
可変長引数(かへんちょうひきすう)とはプログラミング言語において、関数やメソッドやマクロの引数が固定ではなく任意の個数となっている引数のことである。
残余引数構文により、不定数の引数を配列として表すことができます。
参考にさせていただいたブログ
「今日の予定」で引数に丸々入るものだとばっかり思い込んでいたので、「今」「日」みたいに分かれてるって発想がそもそもありませんでした。
でも、「じゃあ中のデータは「今日の予定」で丸々入っていたのはなんで?」と調べてもよくわかっていない部分もあるので、分かり次第追記か別記事を書きたいと思います。
半分ただの覚書みたいになってしまいましたが、とりあえず新しい知識がちょっとだけでも身についたということで、一応記録までに。
今回は以上となります。
BoostNoteをクラウド同期させる方法
↑こちらを参考にしてやりましたが、画面がちょっと私がやったときは違う部分があったため、備忘録で残しておきます。
※BoostNoteのクラウドに保存する方法で調べるとDropBoxやGoogle Driveと同期するやり方も出てきますが、2020年にリニューアルした後はBoostNoteのデフォルトの機能としてクラウド保存がついたようです。
1、BoostNoteをダウンロードする
OSに合わせて選んでください。
私は確か、MacのZip版を選んだ気がします。
2、中を開く
ダウンロードが終わり、アプリを開いてみるとこのような画面になっていると思います。
画像のように人が並んでいるアイコンの画面が選択されていると思いますので、アイコンなしのものを選びます。
3、ストレージを作る
ストレージ名横の下三角をクリックし『New Strage」を選びます。
4、ストレージに名前をつける
ストレージに名前をつけて作成すると、上のように新規ストレージができています。
5、クラウドにつなげる
ストレージ名の横の三角を押し「Preference」を選択。
ストレージをクラウドとリンクするかを上の赤丸部分で設定できます。
最初の時は赤丸の部分が「ログインしないとストレージとクラウドがリンクできません」みたいな表示になっていたので、ログインの作業が入りました。
クラウド上のストレージの名前を決めたらリンクさせる。
左上のように、アイコンの横に矢印がぐるぐるしているマークがつけば、クラウドとの同期完了。
z-indexが効かないときに確認すべき3つの点について
z-indexをつけているのに重なり順が調整されず、試したことと解決方法を記載します。
どのようなときにおこったか
レスポンシブ対応でハンバーガーボタンを作った際、メニューが出現した時にハンバーガーボタンが消えてしまい、メニューを戻せないということがおきました。
そのときのhtmlとCSSは以下の通りとなります。
※関係のない部分は省略して記載しています。
CSS部分
背景色と同化していないか確認する
別のサイトを作った際に「メニューの色とボタンの色を同じにしていたため、メニューが出てきたら同化してしまってボタンが消えたように見えた」ということがあったため今回も真っ先にそれを疑いましたが、今回はきちんと色を変えていたので、その可能性はありませんでした。
positionがついているか確認する
z-indexプロパティは、ボックスの重なりの順序を指定する際に使用します。 z-indexプロパティは、positionプロパティでstatic以外の値が指定されている要素に適用されます。
引用元:http://www.htmq.com/style/z-index.shtml
とのことだったためpositionの付け漏れがないか確認してみましたが、全部についていました。
親要素より子要素のz-indexが大きくなっていないか確認する
今回の原因はこれでした。
親要素
メニュー
参考:https://www.netimpact.co.jp/diary/22704/
z-indexが実質すべて同じ値になっていたためボタンが埋もれてしまうということが起こっていたため、値を調整して今回は解決しました。
スムーズスクロールをした後にスクロールが効かなくなり、ボタンが点滅する不具合を解消する方法
どのようなものを作ろうとしたか
縦長のホームページでよくある「ある程度までスクロールしたら横に出てくる、ページ先頭に戻れるボタンを実装しようとしたときのことでした。
どのような不具合が起きたか
このとき
1、ボタンを押してページ先頭まで戻ったあと、一定時間スクロールが出来なくなる
2、スクロールが効くようになった後、ボタンが急に出たり現れたり、点滅を繰り返す
という不具合が起きました。
そのときのコードは以下のようなものです。
html
エラーの原因の予想
エラーの原因はそれぞれ
1、ボタンを押してページ先頭まで戻ったあと、一定時間スクロールが出来なくなる
→scrollTop: 0と記載したが、何かが邪魔をしスクロールが上まで行き切ってないと判断されているため、scrollTop: 0を満たそうとしてスクロールが出来なくなったのではないか。
2、スクロールが効くようになった後、ボタンが急に出たり現れたり、点滅を繰り返す
→ボタンの表示に関わる記載がtoTopBtn.fadeIn();とtoTopBtn.fadeOut();のため、記載が誤っているのではないか。
と予想しました。
エラーの原因と修正後のコード
予想に反して、原因は1つでした。
if(scrollTop >= posBottom) {
ですが、
ページ下部にいったときにこの条件が複数回呼ばれています。
よって$('body').animate({scrollTop:0},2000);
も複数回呼ばれます。
ページトップに移動した後も実際には呼ばれた回数実行されているので、その間はさらにスクロールしてもscrollTop:0
に移動されているので、スクロールができないような状態になっています。
引用元:javascript - animate()で上端までスムーズスクロールしたあとにスクロールがしばらく効かなくなります。 - スタック・オーバーフロー
if文の判定はボタンが現れる消えるの境い目でのみ行われているのかと思いきや、スクロールに合わせて何度も行われていたため、ページトップに戻った後も
溜まっていたif文の判定の回数だけボタンが現れたり消えたりを繰り返し
この scrollTop: 0が何度も呼ばれていたため一定時間スクロールが効かなかった
のだということがわかりました。
記事を参考にstop()をつけ、上に戻った場合はあとに溜まっているアニメーションをすべてクリアにすることにより、どちらの不具合も解消させることができました。
不具合を受けて
不具合が2つ起きたため原因は別々のところにあると思いきや、同じことが根底にあったというのにはとても驚きました。
複数の不具合が同時に発生したとしても慌てて一度に対処しようとするのではなく、冷静に1つずつ取り組んでいけば早期に解決できるため、1つ1つ確実に解消することを今後心がけていきます。
継承の際のindstance ofの使い方
どのような状況だったのか
どのような結果にしたかったかと実際の結果
どのクラスのインスタンスかによって魔法攻撃ができたり、回復魔法が使えたり挙動を変えたかったので、
Monsterクラス(親クラス)
MagicMonsterクラス(子クラス、Monsterクラスを継承)
HealMonsterクラス(子クラス、継承の継承、Monsterクラスから見れば孫?クラス)
とし、
と最初書いていました。
その結果
ところが、
「HealMonster が出てきているはずなのに、ifの分岐でMagicMonsterに入ってしまっていて、MagicMonsterの挙動をしている」
「MagicMonsterとMonsterが出てきたときはちゃんと正しい分岐に入って、意図した挙動をしている」
ということがおき、HealMonsterの時のみ思った通りに動いていないという結果になりました。
解決策
if文の順番を、
MagicMonsterクラス(子クラス)
↓
HealMonsterクラス(孫?クラス)
↓
Monsterクラス(親クラス)
ではなく
HealMonsterクラス(孫?クラス)
↓
MagicMonsterクラス(子クラス)
↓
Monsterクラス(親クラス)
にしたところ、解決。
なぜそれで解決したのか?
試しにMonsterクラスをif文の先頭に持ってきたところ、MagicMonster が呼ばれているときも、HealMonsterが呼ばれているときも、ifの分岐がMonsterクラスに入っていました。
そのため仮説として
「HealMonsterクラスはMonsterクラスとMagicMonsterクラスを継承していて、その2つの要素も持っているため、instanceof で判定すると、親要素のほうでも反応する」
ということなのではないか、と考えていましたが、PHPマニュアルを見たところ
instanceof は、ある変数が 特定の親クラスを継承したクラスのオブジェクトのインスタンスであるかどうかを調べることもできます。
例2 継承したクラスでの instanceof の使用法
<?php
class ParentClass
{
}
class MyClass extends ParentClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>上の例の出力は以下となります。
bool(true) bool(true)引用 PHPマニュアルhttps://www.php.net/manual/ja/language.operators.type.php
と記載がありました。
「HealMonster が出てきているはずなのに、ifの分岐でMagicMonsterに入ってしまっていて、MagicMonsterの挙動をしている」
という動きをしていると私が思っていたときのPHP側の実際の動きとしては、
「HealMonsterをinstanceofで調べたら、MagicMonsterを親クラスとして継承したクラスだったので、if ($_SESSION['monster'] instanceof MagicMonster のルートに入っていた」
ということで、挙動自体はおかしくなく、instance ofの使い方をきちんと理解していないことが今回のつまづきの原因でした。
最後に
マニュアルが意図していたことに気付いたのが、解決策を思いついて「結局なんでなだろう?」ともう一度見直したときだったので、1度で情報が得られなかったときも、繰り返し確認することが必要だと身に染みて感じました。
画像登録の際のバリデーションが効かない問題
サイズオーバーの画像が登録されてしまうという問題
このよう5MB以上の画像を登録しようとするとエラーメッセージが発生するバリデーションをかけていましたが、明らかに大きいサイズの画像を登録しようとしてもエラーが表示されず、そのまま通ってしまうということが起きました。
詳しい状況として
1:大きいサイズの画像を登録しようとする
2:「登録」ボタンを押してもPOST送信の処理が走らず、登録前の画像が表示される
3:画面にエラーの表示は出ない、もしくは「ARRAY」と表示される
原因
ini_set 関数でログはデフォルトとは別なところに出るようにしており、そちらばかり見ていましたが、デフォルトのphp_error.logをみたところ
というエラー。
調べてみたところ、画像登録の際に気にしなければいけない部分はphp.ini のmemory_limit、post_max_size、upload_max_filesizeの3つ。
post_max_size
integerPOSTデータに許可される最大サイズを設定します。この設定は、ファイルアップロードにも影響します。大きなファイルをアップロード するには、この値を upload_max_filesize より大きく設定する必要があります。 一般的に memory_limit は、post_max_size
よりも大きく する必要があります。 integerを使用する際、 その値はバイト単位で測られます。 この FAQ に記載された 短縮表記を使用することも可能です。 POSTデータの大きさが、post_max_sizeより大きい場合、 $_POST と $_FILES superglobals は空になります。この事象は、いくつかの方法で検出することができます。 例えば、$_GET 変数をデータを <form action="edit.php?processed=1">のように 処理するスクリプトに渡し、 $_GET['processed'] が設定されているかどうかを 確認する方法があります。引用元:PHPマニュアル
https://www.php.net/manual/ja/ini.core.php#ini.post-max-size
とあり、今回、「登録ボタンを押してもPOST処理にいかずはじかれた」、「エラー表示でARRAYと出る」の2点は、POSTデータよりpost_max_sizeが小さかったから起こったんだなということがわかりました。
php.iniの設定を直したらバリデーションが効くようになり、解決しました。
参考:http://blog.prophet.jp/3173
入力保持可能なものと不可能なもの
問題点「入力保持がきかない」
やりたかったこと
textareaタグで作成したフォームに文字を入力した際に、バリデーションエラーでひっかかったとしても入力内容がそのまま保持されるようにする。
実際
バリデーションでひっかかるとtextareaの部分だけ入力内容が消えてしまう。
inputで作成したフォームではそのまま入力内容が保持されているので、PHPのコードの書き方が誤っているわけではなさそうでした。
解決策
inputタグを使用した際に入力保持をしたいときには、上記のようにvalue属性をつけて入力保持のコードを書きますが
textareaの場合は、value属性は付けられないため、開始のタグと閉じタグの間にコードを入れるようにすると効くようになりました。
投稿した写真の入力保持はできるのか?
imput type="file"にもvalue属性はつかず、閉じタグもないので入力保持はできないようです。
そもそも問題、セキュリティ面から画像ファイルの入力保持は出来ないようになっているとのことです。
参考:
https://web-kiwami.com/post-589.html
https://teratail.com/questions/115016