かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

PHP A~Zを簡単に出力したい。

range() 関数を使う

range
range — ある範囲の整数を有する配列を作成する

array range ( mixed $start , mixed $end [, number $step = 1 ] )

<?php
$list = range('A', 'Z');

👇

array(26) {
  [0]=> string(1) "A"
  [1]=> string(1) "B"
  [2]=> string(1) "C"
  [3]=> string(1) "D"
  [4]=> string(1) "E"
  [5]=> string(1) "F"
  [6]=> string(1) "G"
  [7]=> string(1) "H"
  [8]=> string(1) "I"
  [9]=> string(1) "J"
  [10]=> string(1) "K"
  [11]=> string(1) "L"
  [12]=> string(1) "M"
  [13]=> string(1) "N"
  [14]=> string(1) "O"
  [15]=> string(1) "P"
  [16]=> string(1) "Q"
  [17]=> string(1) "R"
  [18]=> string(1) "S"
  [19]=> string(1) "T"
  [20]=> string(1) "U"
  [21]=> string(1) "V"
  [22]=> string(1) "W"
  [23]=> string(1) "X"
  [24]=> string(1) "Y"
  [25]=> string(1) "Z"
}

range()関数はASCIIコードを元に範囲を作るらしいので、
大文字小文字の[A-z]を作ろうと思って、range('A', 'z') としても Za の間に記号が入るので注意が必要っぽい。


[参考]

おしえて A to Z

おしえて A to Z

Javascript Chromeでページトップに戻る(scrollTop)が効かなくなってた件。

Chromeで以前作ったサイトを見ていて、jQueryで実装していたページトップに戻るが効かなくなっているのに気づいてしまいました...

スペック

  • Mac OSX
  • Chrome v61.0.3163.91

$('body').scrollTop() が効かなくなっていた。

今までは、FireFoxIE系はhtmlタグで、webkit系はbodyタグでscrollTopが動作していたので、$('html, body') とするとコールバックが2回呼ばれてしまうのが嫌だったので👇 の様な感じでブラウザ判別してscrollTopを使用するタグを切り替えていました。

var scrollTag = ( window.chrome || 'WebkitAppearance' in document.documentElement.style )? 'body' : 'html';

$(scrollTag).animate({
  scrollTop: 0
}, 'fast', function() {
  console.log('callback');
});

Chromeでは上記の判定で scrollTagbodyになっているので、$('body').scrollTop() が効いているか調べてみると...

// Chrome
$('body').scrollTop(); // => 0 ※常に0が返る

Chromeのアップデートで仕様変更になったようで、Firefoxを同じでhtmlタグでscrollTopが動作するようになり、$('body').scrollTop() が常に0になってしまうようになっていた為に「ページトップに戻る」が動作しなくなっていたようです... (いつのアップデートで変更になってたんだろう???

ブラウザごとの scrollTop の効くタグを調べてみる。

改めて、どのブラウザがbodyで動作するのか、htmlで動作するのかを調べてみました。
IE系が手元に無いので、調べ次第追加します。

👇 codepen に簡単なHTMLとscriptを作成して、各ブラウザでチェックしてみて動作する方のタグを調べます。にちょっとしたチェック用のHTMLとかJSをcodepenに作っておくと緊急時に割りとお役立ちなのです!

See the Pen scroll test HTML or BODY? by KIKIKI (@chaika-design) on CodePen.

ブラウザ バージョン html body
Chrome 61.0.3163.91 ×
Safaei 10.1.2 ×
Firefox 55.0.3 ×
Vivaldi 1.12.955.36 ×
Opera 47.0.2631.83 ×
Safari (iPhone) 10.0 ×
Edge 41.16299 ×
IE 11.125 ×

以前調べた時と違って、ChromeVivaldi では body タグではscrollTopが効かなく、htmlタグで効くようになっていました。
追記 IE, Edgeを調べました。 IEhtmlでEdgeはbodyで動作するようです... MS君は何故自社ブラウザで挙動揃えないのよ....

scrollTopを使用するタグのブラウザ別判定を変更する。

使用していたscrollTopを使用するタグを決めるブラウザ判定のスクリプトを変更します。

IE・Edgeは調べてません 調べました。2018.04.06

var ua = navigator.userAgent;
var scrollTag = (( !window.chrome && 'WebkitAppearance' in document.documentElement.style ) || ( ua.indexOf('OPR') !== -1 || ua.indexOf('Edge') !== -1 ))? 'body' : 'html';

OperaとEdgeが少し厄介で。window.chrome オブジェクトを持っているけど、body タグにしなければならないので、OperaとEdgeの判定のためだけにユーザーエージェントを利用して (ua.indexOf('OPR') !== -1 || ua.indexOf('Edge') !== -1) で常にbodyになるようにしてあげる必要がありました。

OperaとEdgeの問題があるのでif文で書いてしまう方が見やすいような気がします。

var ua = navigator.userAgent;
var scrollTag;
if( ua.indexOf('OPR') !== -1 || ua.indexOf('Edge') !== -1 ) {
  scrollTag = 'body';
} else {
  scrollTag = ( !window.chrome && 'WebkitAppearance' in document.documentElement.style )? 'body' : 'html';
}

 
調べていると body, html {height: 100%}というCSSが原因?という記事も出てきたのですが、私の確認できる範囲ではこれを削除してもうまく動作せず、変更時のサイトへの影響範囲が大きいのでjavascriptの判定の方を変更する事にしました。

また、いつブラウザの仕様が変わってしまうか解りませんので、その時はまた調べて変更する必要がありそうです。(メンドー
昔作ったサイトでは色々と動かなくなってそう...


[参考]

トップをねらえ2! Blu-ray Box

トップをねらえ2! Blu-ray Box

Ajaxを使ってWordPressからコンテンツを取得したい。

WordPress製のサイトに独自のコンテンツなどを取得できるAjaxを作成する方法のメモ

  1. 呼び出すアクション名を決める
  2. Ajax送信先をjsから使えるように出力する
  3. Ajaxで呼び出される関数を作成する (PHP)
  4. フロントからAjaxでの呼出しを作成する (javascript)

1. 呼び出すアクション名を決める

アクション名はPHPの関数名やnoce、jsのAjax内などで何度も使うので、どんな仕様にするか決めて仕様に合ったアクション名を先に決めておくのが良いと思います。

今回は my-ajax-action というアクション名にします。

2. Ajax送信先のパスなどの出力

WordPressAjaxのリクエス送信先 /wp-admin/admin-ajax.php のパスやnoneなどの情報をjavascriptグローバル変数として出力する

<?php // function.php
function my_enqueue_scripts() {
  $handle = 'my-script';
  // Ajaxの呼出しが書かれているスクリプトのパス
  $jsFile = 'path/to/myscript.js';
  
  wp_register_script($handle, $jsFile, ['jquery']);
  
  // 1.で決めたアクション名
  $acrion = 'my-ajax-action';
  // 配列をJSのオブジェクトに変換したscriptを出力する
  wp_localize_script($handle, 'MY_AJAX', [
    'api'    => admin_url( 'admin-ajax.php' ),
    'action' => $acrion,
    'nonce'  => wp_create_nonce( $acrion ),
  ]);
  
  wp_enqueue_script($handle);
}
add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts' );

$handleで指定された myscript.js の出力タグの前に次のようなスクリプトが出力されます。

<script type='text/javascript'>
/* <![CDATA[ */
var MY_AJAX = {
  "api": "http:\/\/example.com\/wordpress\/wp-admin\/admin-ajax.php",
  "action": "my-ajax-action",
  "nonce": "生成されたNONCE値"
}
/* ]]> */
</script>

※ 実際には1行で出力されます。グローバル変数になっちゃうので、ちょっとイケてない感あります…

複数のアクションを作成する場合は、アクションとそれに対応したnonceが取得しやすいように配列をネストするなどして工夫してください。

3. 呼び出される関数の作成 (PHP)

3.1 Ajaxから呼び出される関数を定義する

add_action アクションフックで、Ajaxから呼び出される関数を登録する。

<?php // function.php
function my_ajax_event() {
}
add_action( 'wp_ajax_my-ajax-action', 'my_ajax_event' );
add_action( 'wp_ajax_nopriv_my-ajax-action', 'my_ajax_event' );
  • wp_ajax_{action名} … ログインユーザーの時、呼び出される
  • wp_ajax_nopriv_{action名} … 非ログインユーザーの時、呼び出される

フロントから呼び出される場合は、両方のアクションフックを設定する必要がある。
管理画面で使うだけなら、常にログインユーザーなので wp_ajax_{action名} の方だけでOK。

3.2 Ajaxで呼び出される関数の処理を作成する

<?php // function.php
function my_ajax_event() {
  // wp_create_nonce の引数に渡したものと同じ アクション名
  $action = 'my-ajax-action';
  
  // nonceのチェック
  if( check_ajax_referer($action, 'nonce', false) ) {
    $data = [];

    // Ajax(post)のdataから渡される値を使用する場合は $_POST から取得する (適時エスケープ)
    $id = intval( $_POST['post_id'] );
    $name = esc_html( $_POST['name'] );
    
    /* wordpressから色々取得したり、Ajaxで返すデータ作成する */
    
    // 配列をjson形式にエンコード
    $data = json_encode($data);
  } else {
    // エラー
    status_header( '403' );
    $data = 'Forbidden';
  }

  // Ajaxに返す
  header( 'Content-Type: application/json; charset=UTF-8' );
  echo $data;

  die();
}
add_action( 'wp_ajax_my-ajax-action', 'my_ajax_event' );
add_action( 'wp_ajax_nopriv_my-ajax-action', 'my_ajax_event' );

nonceのチェック

check_ajax_referer( $action, $query_arg, $die )
  • $action (string)
    nonceのアクション名
    nonce作成時の wp_create_nonce() に渡したアクション名と同じ文字列を指定する
  • $query_arg (string)
    $_REQUESTで渡される配列の nonce が格納されているキーを指定
    上の例の場合は data: { nonce: 値 } としてAjaxから送ればOK
  • $die (boolean) default: true
    trueの時 nonce が無効なら die() する
    falseの時 nonce のチェック結果を true / false で返す

Ajax(post)のdataで渡される値は$_POSTで取得することができます。
nonceのチェック関数は内部では$_REQUESTから取得している様なので、$_REQUESTの方がget/postどちらでも取得できるで良いのかもしれません。

Ajaxで呼び出される関数の最後に die() がないと返されるデータの最後に0が追加されてしまうので、忘れないようにdieしておく必要があります。

4. Javascriptの作成 (Ajax呼出し)

後はフロントのjavascriptからAjaxで呼び出すだけです。
URLやアクション名は 2. で作成したグローバル変数から使用します。

// global MY_AJAX
"use strict";
$(function() {
  $.ajax({
    url: MY_AJAX.api,
    type: 'post',
    data: {
      // 呼び出すアクション名
      action: MY_AJAX.action,
      // アクションに対応するnonce
      nonce: MY_AJAX.nonce,
      // ▼ その他 渡したいデータがあれば適時 ▼
      post_id: 12345,
      name: 'name'
    }
  })
  .done(function( res ) {
    console.log( res );
  })
  .fail(function( jqXHR, textStatus, errorThrown ) {
    console.log( jqXHR, textStatus, errorThrown, arguments);
  });
});

 
これで、Ajaxを使ってWordPressから独自のコンテンツとか値を取得することができるようになりました。
Ajaxを使うために出力するjavascriptの変数がglobal変数になってしまうのが、やっぱイケてない感じなので、どうにか出来ないものかと思っています。。。


[参考]

世界一わかりやすいWordPress 導入とサイト制作の教科書 (世界一わかりやすい教科書)

世界一わかりやすいWordPress 導入とサイト制作の教科書 (世界一わかりやすい教科書)