- ベストアンサー
WordPress URL設計の悩み
- WordPressでのURL設計について、1連番号とUUIDのどちらが適切か悩んでいる。
- 連番IDの安全性に関する意見や他の識別子の使用方法についての議論が存在する。
- 具体的な実装例や参考文献を通じて、選択肢の考察を求めている。
- みんなの回答 (29)
- 専門家の回答
質問者が選んだベストアンサー
・既存のコードから追加コードを探すのが大変になるため、追加行と追加コードを書いていきます。 私の方ではgitでソース管理しているので前回のものと比較は簡単にできるので書かなくても大丈夫ですよ。 「※最新コード」のURLが違うのか、ラジオボタンが type="feelingListbox" のままのようです。 ファイルのアップロードも名前やコメントやスタンプと同じところで処理すればいいので、FormDataに追加するのはそちらでやってください。 気になるのは fetch のURL /wp-admin/admin-ajax.php ですかね。 これでうまくいくのかどうか私の方では検証ができていません。
その他の回答 (28)
- dell_OK
- ベストアンサー率13% (766/5720)
・②のonloadリスナーにまとめる方法をとるため、function init() {~}の中に入れるという事でしょうか? そうです。 「onload以降にした方がいい気はしますね。…①」と言うのは、 コードを記述する場所の話しではなくて、 実行するタイミングの話しだと思います。 コメントに書かれているように、 ---- /* ページを全て読み込んでからJavaScriptを実行する場合 */ window.onload = init; ---- ページを全て読み込んでから、initが実行されます。 initの中にリスナーを記述しておけば、つまり、 ページを全て読み込んでから、リスナーが定義される、ことになります。
お礼
こちらが最新の質問になります。JavascriptのXSS対策について話が進んでおらずdell_okさんにアドバイスを頂きたいのですが、HTMLクラスを1つにまとめるということが理解できずどうすれば良いか分かりません… DOMの原因になるため初めは文字を表示させずに入力されたら残りの文字数をカウントして、字数をオーバーしたら超過文字数を表示させるようにコードを考えました。 画像のアップロード機能が名前、メッセージの前になるので、参考サイトのどちらのコードを使えばよいのか分からず前者を使うようにしております。 ※window.onload = function() {} は動かない原因になりうるため window.addEventListener('DOMContentLoaded', function() {} を代用するように変更しております。 ※参考サイト https://took.jp/window-onload/ ※アドバイス頂いたもの submit_button_validation1だけを使って innerHTML="残り<span>"+v+"</span>文字入力できます。"; の時と、 innerHTML="span>"+v+"</span>文字超過しています。"; の時を、ifで制御すればOK ※考えたコード <div class="title-partial parts"> <!-- title-partial + parts --> <h2>名前(name)<span class="required">※必須</span></h2> <div class=parts> <input class=submit_button type="text" type="text" name="name1" id="name" data-length=32 placeholder="未入力の場合は、匿名で表示されます" value="<?php echo $namae; ?>"> <div class="submit_button_validation submit_button_validation"></div> </div> <div class="body-partial parts"><!-- body-partial + parts --> <h2>コメント(comment)<span class="required">※必須</span></h2> <div class=parts> <input class=submit_button type="text" name="name2" id="message" data-length=40 placeholder="荒らし行為や誹謗中傷や著作権の侵害はご遠慮ください"><?php echo $message; ?> <div class="submit_button_validation submit_button_validation"></div> </div> <script> function validation_submit(f) { const submit = document.getElementById("submit_button"); /* 判定は逆なので、逆に渡す */ /*JavaScriptの要素を活性または非活性にする */ submit.disabled = f?false:true; }; function validation_text(parts) { /* このpartsグループの、input=textを抽出 */ /* HTML要素を取得 */ let text=parts.getElementsByClassName('submit_button')[0]; /* バリデーション警告パーツを抽出 */ let validation=parts.getElementsByClassName('submit_button_validation')[0]; validation.style.display = 'none'; /* 例えばのチェック */ window.addEventListener('DOMContentLoaded', function() { let wao = document.getElementsByClassName('submit_button_validation'); const left = text.dataset.length-text.value.length; if (left >= 0) { /* ひとまずclassは複数配置できる形式なので、見つかった最初の1個目にアタッチ */ wao[0].innerHTML="残り<span>"+v+"</span>文字入力できます。"; text.value.length === 0; } else { /* そのまま、2個目にアタッチ */ wao[1].innerHTML="<span>"+v+"</span>文字超過しています。"; } }) }; /* バリデーション条件判断部分 */ function validation() { let parts = document.getElementsByClassName('parts'); let submit=true; for (let i=0;i<parts.length;i++) { if (validation_text(parts[i])!=true) { submit=false; } } validation_submit(submit); }; /* DOM構築が終わってから呼び出される初期化関数 */ function init() { // let text = document.getElementById('submit_button'); // text.oninput = e_text; /* ↑これを、idじゃなくてclass対応に変更↓ */ /* class=parts内の class=submit_buttonに対して設定 */ let parts = document.getElementsByClassName('parts'); for (let i=0;i<parts.length;i++) { parts[i].getElementsByClassName('submit_button')[0].oninput = validation; } validation(); }; window.onload = init; </script>
補足
回答ありがとうございます、なるほど実行するタイミングのことになるのですね。 initの中にまとめるということで理解できました。
- dell_OK
- ベストアンサー率13% (766/5720)
・onloadと書かれたコードは2つあり、window.onload = init; と reader.onload = () => { ですが、前者のコードの意味を調べたところアドバイス頂いたものは後者のほうだと思われます。 アドバイスは前者だと思います。 例えば、これはエラーになります。 ---- <body> <script> const text = document.getElementById("text"); text.value = "text"; </script> <input type="text" id="text"> </body> ---- なぜなら、<input type="text" id="text">が生成される前にスクリプトが実行されてしまうからです。 スクリプトが前に書かれているためです。 エラーにならないようにするには、<input type="text" id="text">が生成された後にスクリプトが実行されるようにします。 ---- <body> <input type="text" id="text"> <script> const text = document.getElementById("text"); text.value = "text"; </script> </body> ---- アドバイスのonloadを使うのでしたらこうです。 ---- <body> <script> function init() { const text = document.getElementById("text"); text.value = "text"; } window.onload = init; </script> <input type="text" id="text"> </body> ---- これで<input type="text" id="text">が生成された後にスクリプトが実行されます。 スクリプトが前に書かれていても大丈夫です。 スクリプトを後に書いてもかまいません。 ---- <body> <input type="text" id="text"> <script> function init() { const text = document.getElementById("text"); text.value = "text"; } window.onload = init; </script> </body> ---- これが、onload、コンテンツが生成された後に実行される、ということだと思います。
補足
A.説明ありがとうございます、理解することが出来ました。1点質問があるのですが<script>のあとにHTMLを書くとエラーになる(クラスが生成されているから)というのは理解できたのですが、onload以降にする場合①はsingle-input.phpでカメラ画像をファイルアップロード時に非表示にするコードをonloadの後ろに挿入する必要がある気がするのですが、 ②のonloadリスナーにまとめる方法をとるため、function init() {~}の中に入れるという事でしょうか? /* ページを全て読み込んでからJavaScriptを実行する場合 */ window.onload = init; ※アドバイス頂いたもの const attach = document.querySelectorAll('.attach'); 画面表示前に呼ばれたどうなるかって考えるとちょっと恐ろしいので、onload以降にした方がいい気はしますね。…① onloadリスナーにまとめると、ソースの上に書いても、DOM構築後にしか呼ばれないので、確実にセレクタの取り込みは成功します。…② ※修正コード https://wandbox.org/permlink/wgw57ZA0Iln9sjdI
- dell_OK
- ベストアンサー率13% (766/5720)
・reader.onload = () => { 以降はfunction init() {~}の中に入れないほうが良い気がするのですが、どこで区切るべきでしょうか? なぜ入れない方がいい気がしたのかわかりませんが、全部です。 その前に、現在のコードで画像の切り替えは動作していますか。
補足
回答ありがとうございます、onload以降にするかまとめる場合というアドバイスの意味を考えたのですが、onload以降に/* カメラ画像をファイルアップロード時に非表示にする */コードを挿入する必要があるのではないかと思いました。 onloadと書かれたコードは2つあり、window.onload = init; と reader.onload = () => { ですが、前者のコードの意味を調べたところアドバイス頂いたものは後者のほうだと思われます。 reader.onload = () => も含めてfunction init() {~}の中に入れてしまうと、/* カメラ画像をファイルアップロード時に非表示にする */コードがonload以降にならない気がするので、reader.onload = () => より前の文を入れるべきではないかと考えました。 まとめる場合という意図が理解できていないため、解釈が間違っている気もしています… コードの切り替えは成功しておらず現在アドバイスを頂いている状態です… /* DOM構築が終わってから呼び出される初期化関数 */ function init() { // let text = document.getElementById('submit_button'); // text.oninput = e_text; /* ↑これを、idじゃなくてclass対応に変更↓ */ /* class=parts内の class=submit_buttonに対して設定 */ let parts = document.getElementsByClassName('parts'); for (let i=0;i<parts.length;i++) { /* oninputは、テキスト入力欄等で文字が入力された時に処理を実行出来ます。*/ parts[i].getElementsByClassName('submit_button')[0].oninput = validation; } validation(); }; /* ページを全て読み込んでからJavaScriptを実行する場合 */ window.onload = init;
- dell_OK
- ベストアンサー率13% (766/5720)
・範囲は下記コード全てになるのでしょうか…? そうです。 まだ続きがあるはずですが、そこから下全部入れてみてください。
補足
回答ありがとうございます、onload以降にするかまとめる場合reader.onload = () => { 以降はfunction init() {~}の中に入れないほうが良い気がするのですが、どこで区切るべきでしょうか? ※該当コード https://wandbox.org/permlink/uxHOg8b67wlybSjm /* カメラ画像をファイルアップロード時に非表示にする */ const attach = document.querySelectorAll('.attach'); const del = document.querySelectorAll('.attachdel'); const clear = document.querySelectorAll('.attachclear'); const viewer = document.querySelectorAll('.viewer'); const changeImg = document.querySelectorAll('.changeImg'); // 入力されたら消す画像 for (let i = 0; i < attach.length; i++) { attach[i].addEventListener('change', () => { if (attach[i].files[0].size > 15 * 1024 * 1024) { alert('ファイルサイズが 15MBバイトを超えています'); return; } del[i].value = ""; viewer[i].innerHTML = ""; if (attach[i].files.length !== 0) { const reader = new FileReader(); reader.onload = () => { var child = null; if (reader.result.indexOf("data:image/jpeg;base64,") === 0 || reader.result.indexOf("data:image/png;base64,") === 0) { child = document.createElement("img"); } else if (reader.result.indexOf("data:video/mp4;base64,") === 0) { child = document.createElement("video"); child.setAttribute("controls", null); } else if (reader.result.indexOf("data:application/pdf;base64,") === 0) { child = document.createElement("iframe"); } else { alert("対象外のファイルです"); alert(reader.result); attach[i].value = ""; } if (child !== null) { child.style.height = "350px"; child.style.width = "528px"; child.src = reader.result; viewer[i].appendChild(child); changeImg[i].classList.add('hideItems'); // もともとの画像を消す } }; reader.readAsDataURL(attach[i].files[0]); } }); clear[i].addEventListener('click', () => { attach[i].value = ""; del[i].value = "1"; viewer[i].innerHTML = ""; changeImg[i].classList.remove('hideItems'); }); }
- dell_OK
- ベストアンサー率13% (766/5720)
・カメラ画像をファイルアップロード時に非表示にするコードをonload以降にするかまとめることは可能でしょうか? function init() {~}の中にいれてみてはどうでしょうか。
補足
アドバイスありがとうございます、function init() {~}の中に入れる場合、範囲は下記コード全てになるのでしょうか…? /* カメラ画像をファイルアップロード時に非表示にする */ const attach = document.querySelectorAll('.attach'); const del = document.querySelectorAll('.attachdel'); const clear = document.querySelectorAll('.attachclear'); const viewer = document.querySelectorAll('.viewer'); const changeImg = document.querySelectorAll('.changeImg'); // 入力されたら消す画像 for (let i = 0; i < attach.length; i++) { attach[i].addEventListener('change', () => { if (attach[i].files[0].size > 15 * 1024 * 1024) { alert('ファイルサイズが 15MBバイトを超えています'); return; } del[i].value = ""; viewer[i].innerHTML = ""; ※該当コード https://wandbox.org/permlink/uxHOg8b67wlybSjm
- dell_OK
- ベストアンサー率13% (766/5720)
・表示画面(single-complete.php)で名前とコメントが表示されずにindex.phpが表示されてしまうのですが、原因は分かりますでしょうか? 私のローカル環境では問題なく表示されます。 固定ページの設定が合ってないのかも知れないですね。 テンプレート:complete URLパーマリンク:質問表示画面
補足
回答ありがとうございます、固定ページを別途作成することを忘れておりました。申し訳ありません。 Javascriptで1点だけお聞きしておきたいことがあるのですが、single-input.phpでカメラ画像をファイルアップロード時に非表示にするコードをonload以降にするかまとめることは可能でしょうか? const ○○を後ろに配置したり、まとめるということが想像できないのですが、どのような形にすべきかアドバイス頂きたいです… ※アドバイス頂いたもの const attach = document.querySelectorAll('.attach'); 画面表示前に呼ばれたどうなるかって考えるとちょっと恐ろしいので、onload以降にした方がいい気はしますね。 onloadリスナーにまとめると、ソースの上に書いても、DOM構築後にしか呼ばれないので、確実にセレクタの取り込みは成功します。 ※最新コード https://wandbox.org/permlink/BUpEovwDnKiZZho1
- dell_OK
- ベストアンサー率13% (766/5720)
質問一覧画面だけで言うとURLに連番を使って予測されやすいとしても攻撃はされないと思います。 予測されたURLにアクセスされても質問画面が表示(アクセス)されるだけです。 質問画面にアクセスされても問題はないと思います。 なぜなら、仮にUUIDや他のものにしていたとしても、質問一覧画面のHTMLを走査してURLを検出してアクセスされるのとほとんど同じです。
補足
A.回答ありがとうございます、確かに両方同じようですね。 表示画面(single-complete.php)で名前とコメントが表示されずにindex.phpが表示されてしまうのですが、原因は分かりますでしょうか? UUIDも一致しているのですが、クエリを実行してカラムを追加するところが原因でしょうか… ※unique_idを保存しているデータベース https://imgur.com/IoCPcfc.jpg ※質問一覧表示画面 http://www.irasuto.cfbx.jp/%E8%B3%AA%E5%95%8F%E8%A1%A8%E7%A4%BA%E7%94%BB%E9%9D%A2?ee10ffd5-36ad-11ee-ad27-e4434ba51b4c ※現在のコード https://wandbox.org/permlink/BUpEovwDnKiZZho1
- dell_OK
- ベストアンサー率13% (766/5720)
・URLを連番にすべきかuuidにすべきか迷っているのですが それは解決した問題で、UUIDにされました。 ---- $url = home_url('質問表示画面?'.$row->unique_id); ----
補足
A.回答ありがとうございます、OKWAVEでは質問IDをURLにする方法も考えたのですが、UUIDが一番安全なようなので以前教えていただいたものを使わせて頂きます。 ※以前アドバイス頂いた質問(回答No.6) https://okwave.jp/qa/q10165331_3.html#answers
お礼
申し訳ありません、データベースにアップロードファイルを格納する場合にサンプルコードを調べた際の参考サイトを提示しておりませんでした。 http://surferonwww.info/BlogEngine/?tag=/Upload
補足
「※最新コード」のURLが違うのか、ラジオボタンが type="feelingListbox" のままのようです。 A.回答ありがとうございます、gitで確認されているとのことで了解いたしました。ラジオボタンを変更したものと異なるリンクのものを修正しておりました申し訳ありません。 ※最新コード https://wandbox.org/permlink/H5perAX6gVLSavpt Q.ファイルのアップロードも名前やコメントやスタンプと同じところで処理すればいいので、FormDataに追加するのはそちらでやってください。 気になるのは fetch のURL /wp-admin/admin-ajax.php ですかね。 これでうまくいくのかどうか私の方では検証ができていません。 A.アドバイスありがとうございます、最新コードのnew-complete.phpの300行目から321行目までの下記コードをnew-complete.phpの251行目に移動いたしました。 現在のsingle-input.phpと参考サイトのFetch API でファイルをアップロードするの例に上がっているコードを比べたところ入力内容をチェックする項目はほぼ同じようでした。 ※修正コード https://wandbox.org/permlink/TyE4ReXNe92MEbIF // 送信データの準備 const formData = new FormData(); formData.append("uploadfile", uploadfile.files[0]); // ファイル内容を詰める const param = { method: "POST", body: formData } // アップロードする fetch("https://example.com/receive.php", param) .then((res)=>{//成功したら(then) ,responseのデータをコンソールに表示 return( res.json() ); }) .then((json)=>{ // 通信が成功した際の処理 }) .catch((error)=>{ // エラー処理 }); }); }); ファイル送信 有無が現在のsingle-input.phpにはなく、ファイルをディレクトリに保存する方法とデータベースに保存する方法で違いがあるようです。 削除や別途表示させる場合のことも考えて、データベースに保存する方法を取りたいのですが、Javascriptで書く必要がありそうで難しいのではないかと懸念しております… Fetch APIはネットワークエラーが起きた際に例外を投げ、それをキャッチできないとウェブアプリケーションの場合は画面が真っ白になるようで、fetch()・then ・then .catch によりエラーをキャッチするため、この文に合わせてデータベースに保存することになりそうです。 ※fetch APIを安全に使う方法 https://www.slideshare.net/i_Pride/fetch-api-255718218 ※入力内容をチェックする項目 1,ファイル容量 サイズ 2,ファイル形式 タイプ 3,ファイル送信 有無 4,MYMETYPE調べる +α 保存(ファイル名作成)