かもメモ

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

PHP if文の条件の判定順

if文の中に&&や||条件を複数入れた時にどちらから処理されるか、PHPは左からであってると思ったけど、何か右から判定するのが合った気がしたので念のため調べてみました。

次のような関数を作成して、この関数を条件にすれば、出力結果から左右どちらから処理をしているかが判ります。

<?php
function f($str) {
  echo $str;
  return true;
}

&& (AND)

<?php
if( f('A') && f('Z') );   // AZ
if( !f('A') && f('Z') );  // A
if( f('A') && !f('Z') );  // AZ
if( !f('A') && !f('Z') ); // A

左側から処理がされています。

|| (OR)

<?php
if( f('A') || f('Z') );   // A
if( !f('A') || f('Z') );  // AZ
if( f('A') || !f('Z') );  // A
if( !f('A') || !f('Z') ); // AZ

||も同様に左側から処理がされています。  
PHPのif文の条件は左から(先に書いた方から)されるで合っていました!
なので、条件が沢山あるif文を作成する時は、先にbool値だけで判定できるとか関数を呼ばない処理の軽いものから書いておけば計算量が減るということですね。

なんとなく記憶にある右から処理する言語って何だったか気になるところですが、
覚えている範囲だとプログラム言語ではない感じですが、
CSSセレクタを右から辿って検索する(ネストの深い所から上階層に向かって捜査)のでセレクタにタグ名を付けない方が高速というのがあります。

h1.logo {} /* 遅い */
.logo /* CLASSだけの方が速い */
#logo /* IDの方がCLASSより速い */

ef - a tale of memories. OPENING THEME〜euphoric field feat.ELISA

ef - a tale of memories. OPENING THEME〜euphoric field feat.ELISA

MySQL UNION それぞれのSELECT文で取ってきたデータを、それぞれでソート(ORDER BY)してくっつけたい。

MySQLで別々の条件(SELECT文)で取ってきたデータをそれぞれでソートして結合したい。
という事で、2回SQLを発行して取ってきたデータをマージしてしまえば実現できることなのですが、SQL1回で実現できないかと思い調べていて色々とハマったのでメモ。

テーブル
テーブル名: test_table

+----+------+------+
| id | num  | text |
+----+------+------+
|  1 |   10 | b    |
|  2 |    9 | c    |
|  3 |    8 | a    |
|  4 |    7 | e    |
|  5 |    6 | f    |
|  6 |    5 | d    |
|  7 |    4 | i    |
|  8 |    3 | g    |
|  9 |    2 | h    |
| 10 |    1 | j    |
+----+------+------+

UNION (SQL)

複数のSELECT文をまとめることが出来る。
結合するSELECT文で取ってくるカラム数が同じである必要がある。(カラムのデータ型も同じである必要がありそう?)

  • UNION - 重複を排除するためにソートする
  • UNION ALL - ソートしない

重複しない条件で取ってくる場合はUNION ALLを使う方が高速なので良さそうです。

SELECT * FROM test_table WHERE num in (1,2,3)
UNION ALL
SELECT * FROM test_table WHERE num in (4,5,6);

👇 結果

+----+------+------+
| id | num  | text |
+----+------+------+
|  8 |    3 | g    |
|  9 |    2 | h    |
| 10 |    1 | j    |
|  5 |    6 | f    |
|  6 |    5 | d    |
|  7 |    4 | i    |
+----+------+------+

1つめのSELECTで取得されるデータの後に
2つめのSELECTで取得されるデータがくっつき
それぞれidの順になりました。

text順でソートしたい

データを一括でソートする場合は最後にORDER BY <条件>をつければOK

SELECT * FROM test_table WHERE num in (1,2,3)
UNION ALL
SELECT * FROM test_table WHERE num in (4,5,6)
ORDER BY text;

👇結果

+----+------+------+
| id | num  | text |
+----+------+------+
|  6 |    5 | d    |
|  5 |    6 | f    |
|  8 |    3 | g    |
|  9 |    2 | h    |
|  7 |    4 | i    |
| 10 |    1 | j    |
+----+------+------+

ソート条件は同じで、1つめのSELECT文で取れるデータをソートした後に、2つめのSELECT文で取れるデータをソートししてくっつけたい

1つめのSELECT文で取れるデータ(numが1,2,3)の後に 2つめのSELECT文で取れるデータ(numが4,5,6)をくっつけて、 それぞれtextでソートしたい場合

それぞれのSELECT文にORDER BY <条件>を付けても...

(SELECT * FROM test_table WHERE num in (1,2,3) ORDER BY text)
UNION ALL
(SELECT * FROM test_table WHERE num in (4,5,6) ORDER BY text);

👇 上手く動作しません SELECT分は括弧()で囲まないとエラーになりました

+----+------+------+
| id | num  | text |
+----+------+------+
|  8 |    3 | g    |
|  9 |    2 | h    |
| 10 |    1 | j    |
|  5 |    6 | f    |
|  6 |    5 | d    |
|  7 |    4 | i    |
+----+------+------+

それぞれにある、ORDER BYは無視されてしまいました。

Note however, absent an ORDER BY (or GROUP BY) clause on the outermost query, the order that the rows are returned is NOT guaranteed.
If you need the rows returned in a particular sequence, you should include an ORDER BY on the outermost query. In a lot of use cases, we can just use an ORDER BY on the outermost query to satisfy the results.
[出典]: mysql - How to use ORDER BY inside UNION - Stack Overflow

外側にORDER BYを付けないと順序は担保されないようです...
と質問をTwitterに投げていた所

がめら大先輩ありがとうございます! Twitter最の高!! (無差別凍結だけは辞めて…)

という事で、
カラム指定に固定値を入れ、それをソート条件でその値を利用するとイケるみたいです!

SELECT *, 1 AS row FROM test_table WHERE num in (1,2,3)
UNION ALL
SELECT *, 2 AS row FROM test_table WHERE num in (4,5,6)
ORDER BY row, text;

👇結果

+----+------+------+-----+
| id | num  | text | row |
+----+------+------+-----+
|  8 |    3 | g    |   1 |
|  9 |    2 | h    |   1 |
| 10 |    1 | j    |   1 |
|  6 |    5 | d    |   2 |
|  5 |    6 | f    |   2 |
|  7 |    4 | i    |   2 |
+----+------+------+-----+

やったぜ!₍₍ (ง ˙ω˙)ว ⁾⁾

1つめのSELECT文で取れるデータをソートした後に、2つめのSELECT文で取れるデータをソートししてくっつけたい

1つめのSELECT文で取得したデータをnumでソートした後に、 2つめのSELECT文で取得したデータをtextでソートして
結合したいような場合

先の例で個別にORDER BYを付けても無視されたので、結構ハマりました。
結論を先に言えば、公式のドキュメントに答えが書いてありました。

個々の SELECT ステートメントに対して ORDER BY を使用しても、UNION がデフォルトでは、順序付けされていない行のセットを生成するため、最終的な結果に行が現れる順序には何も影響を与えません。そのため、このコンテキストでは通常、ORDER BYLIMIT と組み合わせて使用されます。それにより、選択された行の UNION の最終結果での順序に必ずしも影響を与えるわけではないにもかかわらず、SELECT で取得するためのこれらの行のサブセットを決定するために使用されるようになります。ORDER BYSELECT 内に LIMIT なしで現れた場合、この句はいずれにしても何も効果がないため、最適化によって削除されます。
[出典]: MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.2.9.4 UNION 構文

つまり、LIMIT が指定されていれば、それぞれのSELECT文でORDER BYが効くのでは?

(SELECT * FROM test_table WHERE num in (1,2,3) ORDER BY num LIMIT 3)
UNION ALL
(SELECT * FROM test_table WHERE num in (4,5,6) ORDER BY text LIMIT 3);

👇結果

+----+------+------+
| id | num  | text |
+----+------+------+
| 10 |    1 | j    |
|  9 |    2 | h    |
|  8 |    3 | g    |
|  6 |    5 | d    |
|  5 |    6 | f    |
|  7 |    4 | i    |
+----+------+------+

(ꆤ.̫ꆤ)ニッコリ

次のようにしたほうがより確実かもしれません。(上記は、偶然 1つめSELECTデータの後に2つめのSELCTが結合されているだけのかもしれないので)

(SELECT *, 1 AS row FROM test_table WHERE num in (1,2,3) ORDER BY num LIMIT 3)
UNION ALL
(SELECT *, 2 AS row FROM test_table WHERE num in (4,5,6) ORDER BY text LIMIT 3)
ORDER BY row;

👇結果

+----+------+------+-----+
| id | num  | text | row |
+----+------+------+-----+
| 10 |    1 | j    |   1 |
|  9 |    2 | h    |   1 |
|  8 |    3 | g    |   1 |
|  5 |    6 | f    |   2 |
|  7 |    4 | i    |   2 |
|  6 |    5 | d    |   2 |
+----+------+------+-----+

LIMIT が使えない場合

取得する数が分かってるとか、取得する上限が決まっているのであれば問題ないのですが、データを全件取得したいとかでLIMITが使えない場合、それぞれのSELECT文にORDER BYを付けても無視されてしまいます。

先の 1つめのSELECT文で取得したデータをnumでソートした後に、 2つめのSELECT文で取得したデータをtextでソートして
結合したいような場合
LIMITを使わずに実現できるかにチャレンジしてみましたが、私の力では実現できませんでした...
例えば

SELECT T1.* FROM
  (SELECT * FROM test_table WHERE num in (1,2,3) ORDER BY num) AS T1 
UNION 
SELECT T2.* FROM 
  (SELECT * FROM test_table WHERE num in (4,5,6) ORDER BY text) AS T2;

SELECT文をサブクエリにしてみても...

+----+------+------+
| id | num  | text |
+----+------+------+
|  8 |    3 | g    |
|  9 |    2 | h    |
| 10 |    1 | j    |
|  5 |    6 | f    |
|  6 |    5 | d    |
|  7 |    4 | i    |
+----+------+------+

UNIONで結合する限り ORDER BY は無視されてしまいました。

LIMITに大きな数字で設定してしまう

LIMITを使って全件取得する方法を検索しました。

From the MySQL documentation:

To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:

SELECT * FROM tbl LIMIT 95,18446744073709551615;

So getting all rows might look as follows:

SELECT * FROM tbl LIMIT 0,18446744073709551615;
[出典]: [https://stackoverflow.com/questions/15950871/select-all-records-using-mysql-limit-and-offset-query:title]

MySQLのドキュメントに「96番目から最後まで取得したいなら、何か大きな数字を使えば実現できる」と書いてあるから、
LIMITを使って、最初から取得するにはその大きな数字を使えば良い。
という事らしいw パワープレイだwww
ドキュメントに本当に書いていましたw

なので、UNIONを使って全件取得で、それぞれのSELECT文を別にソートする場合は、大きな数字でLIMITを書ければ上手くいきそうです。

(SELECT * FROM test_table WHERE num in (1,2,3,7,8,9) ORDER BY num LIMIT 18446744073709551615)
UNION ALL
(SELECT * FROM test_table WHERE num in (4,5,6,10) ORDER BY text LIMIT 18446744073709551615);

👇 結果

+----+------+------+
| id | num  | text |
+----+------+------+
| 10 |    1 | j    |
|  9 |    2 | h    |
|  8 |    3 | g    |
|  4 |    7 | e    |
|  3 |    8 | a    |
|  2 |    9 | c    |
|  1 |   10 | b    |
|  6 |    5 | d    |
|  5 |    6 | f    |
|  7 |    4 | i    |
+----+------+------+

できました。(ᵒ̤̑ ₀̑ ᵒ̤̑) (データの入る上限がある程度決まっているなら、ここまで大きな数字でなかったり、カラム数をカウントしてLIMITに設定するとかでも良いのかもしれません)

 

今日のアイカツ格言
「困ったときは公式ドキュメント」
f:id:kikiki-kiki:20171222090214p:plain

速度の問題とかまたあまり良く解ってないので、2回SQL発行した方が高速かもしれません。この辺りは課題として学んでいきたいと思います。


[参考]

SQLアンチパターン

SQLアンチパターン

iPhone・iPad インターネット共有が出来なくなった時のメモ

出先ではiPadiPhoneテザリングで使っているのですが、突然wifiの「インターネット共有」 でテザリングできなくなったの解決するまでに試してみたことのメモ。

1. 再起動

iPhoneiPadをして、iPhoneで「インターネット共有」をONにし、その後 iPadwifi からテザリングの回線名を選択します。

2. iPad(共有回線を使う側)のネットワーク設定のリセットを行う

iPadの「設定 > 一般 > リセット > ネットワーク設定をリセット」を選択。
iPadが再起動するので、改めてwifiからテザリングをしている回線を選択。
もろもろ保存されていたwifiのパスワードを再入力しないといけなくなってしまうのですが、私の場合はこれで解決しました。

3. iCloudからログアウトしてログインし直す

テザリングする側・される側両方の端末でiCloudから一度ログアウトし、ログインし直すと解決する場合もあるそうです。  

突然ネットに繋げれなくなるとSIMの無いiPadだとランチョンマットになってしまうので、解決方法にたどり着くまでヒヤヒヤしました...
(SIMフリー版買っておけばよかったかも...)


JS 表示してるページのURLを取得したりするアレコレのメモ

URLを取得する方法のメモ (Chrome / Firefox / Safari で確認しています。)

例えばこんなURL

1. http://example.com/dir/
2. http://www.example.com/dir/
3. http://example.com/dir/index.html#section01
4. http://www.example.com/dir/index.html#section01
5. http://example.com/dir/index.html?s=foo
6. http://www.example.com/dir/index.html?s=foo

今のページのURLを取得する

window.location.href

又は

document.URL // 読み取り専用

👇

// 1. => "http://example.com/dir/"
// 2. => "http://www.example.com/dir/"
// 3. => "http://example.com/dir/index.html#section01"
// 4. => "http://www.example.com/dir/index.html#section01"
// 5. => "http://example.com/dir/index.html?s=foo"
// 6. => "http://www.example.com/dir/index.html?s=foo"

ドメイン名を取得

window.location.host
// 又は window.location.hostname

👇

// 1. 3. 5. => "example.com"
// 2. 4. 6. => "www.example.com"

プロトコルを取得

window.location.protocol

👇 1 ~ 4 共通

// "http"

サイトのトップページのURLを取得

プロトコルドメイン名から作成できる。

window.location.protocol + '//' + window.location.host

👇

// 1. 3. 5. => "http://example.com"
// 2. 4. 6. => "http://www.example.com"

ドメイン以下のパス

window.location.pathname

👇

// 1. 2. => "/dir/"
// 3. 4. 5. 6. => "/dir/index.html"

※ URLの末に/が無ければ無いまま取得されるっぽい

トップページ(http://example.com)の場合は/が取得される

window.location.pathname // => "/"

ハッシュを取得

window.location.hash

👇

// 1. 2. 5. 6. => ""
// 3. 4. => "#section01"

パラメーターを取得

window.location.search

👇

// 1. 2. 3. 4. => ""
// 5. 6. => "?s=foo"

※ ブラウザの場合locationwindowオブジェクトのプロパティなので、wondow.は省略可 (但しスコープ内にlocationって名前の変数を作っていない場合)


[参考]

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

印刷用CSSのメモ

WEBページを印刷する需要ってもうそんなに無い気もするのだけれど、必要になったのでメモ。

印刷用のCSS

1. 印刷用のCSSをmedia="print"指定した別ファイルで読み込ませる
<link rel="stylesheet" type="text/css" href="main.css" media="screen">
<link rel="stylesheet" type="text/css" href="print.css" media="print">

印刷用のスタイルは print.css だけで完結する

2. メディアクエリ @media print で指定する

印刷用のメディアクエリを追加するCSSは印刷時にも有効になるようにmedia="all"で指定します

<link rel="stylesheet" type="text/css" href="main.css" media="all">

main.css 内に下記のメディアクエリを作成してその中に印刷用のCSSを記述する

@media print {
  /* 印刷用のCSS */
}

※ 印刷時もWEB表示用のCSSも有効になるので、不要なスタイルはこのメディアクエリ内で打ち消す必要がある。

用紙の設定 @pront

まだ対応していないブラウザもありますが、用紙サイズや空きなどの指定が行なえます。 f:id:kikiki-kiki:20171212230215p:plain
Can I use... Support tables for HTML5, CSS3, etc

例:
A4サイズ 上下12mm 左右7mm空き

@pront {
  size: A4
  margin: 12mm 7mm;
}

用紙サイズ指定 size: <width> < height > で指定

@page { size: 120mm 297mm; } /* A4サイズ */

A4 縦向き (A4が 210mm x 297mm なので portrait は省略可 )

@page { size: A4 portrait; }

A4 横向き

@page { size: A4 landscape; }

サイズに指定できるキーワード

keyword size
A5 148mm x 210mm
A4 210mm x 297mm
B5 176mm x 250mm
B4 250mm x 353mm
JIS-B5 182mm x 257mm
JIS-B4 257mm x 364mm
letter 8.5in x 11in
legal 8.5in x 14in
ledger 11in x 17in

[参考]

iOS javascript clickイベントが効かないにはまる。

レスポンシブなサイトを作成していてモバイルの時によくある、メニューアイコンを押したら全画面にメニューが表示されてメニュー以外をクリックするとメニューが閉じる機能を作っていました。
Chromeの開発ツールでは意図したとおりに動作していたのですが、iPhone実機で確認した所メニュー以外の部分をタップしたらメニューを閉じる機能が動作していませんでした。

確認環境

clickイベントが効かないパターンがあるっぽい

動作しなかった例

$(document).on('click', 'div.hitarea', function(){ /*... 処理 */ });

※ 対象の要素を解りやすくするために敢えてdiv.hitareaと書いています

どうやら$(document).on$('body').on のようなイベントの登録のしかたで、イベント対象がaタグではない時にクリックイベントが無視されてしまうようです。

解決方法

1. クリック対象となる要素にcursor: pointerというスタイルを付ける

クリック対象の要素にcursor: pointerというスタイルがあれば、aタグでなくてもクリックイベントが効くようになるようです。(イベントがdocumentやbodyといったものに登録されている場合イベントターゲットがpointerな要素ならタップ可能な要素だとiOSが判定するような仕組みっぽいです。)

今回の例だと次のようにスタイルを加えるとクリックイベントが動作するようになりました。

div.hitarea {
  cursor: pointer;
}

ボタンのように使いたい機能だった場合はこの方法が簡単です。
しかし、今回のようなレスポンシブなサイトで、ボタンエリア以外をクリックしたらメニューを閉じたいというような場合、モバイルで見てる時は良いのですがPCで見るとモーダルのメニュー上どこにマウスを持っていってもカーソルがクリック可能なポインターになってしまうので、ちょっと問題がありました。

2. document, body にイベントを登録しなければOK

iOSでクリックイベントが動作しないのは、documentまたはbodyにイベントが登録されている かつ 対象の要素がaタグでない(pointerのスタイルがない) とき ですので、$(document).on$('body').onとしなければ問題なく動作します。

例えば次のようなHTML構造で

<body>
  <div class="container">
    <div class="hitarea"></div>
  </div>
</body>

単純に最初から画面にある該当要素だけでクリックイベントが効けば良いのであれば

$(document).on('click', 'div.hitarea', function(){ /*... 処理 */ });

ではなく

$('div.hitarea').on('click', function(){ /*... 処理 */ }); 

とすればOKです。

後から追加される要素にもクリックイベントが効く必要があるときは、

$('.container').on('click', 'div.hitarea', function(){ /*... 処理 */ }); 

上記のようにdocumentbodyではなく対象となる要素が追加される親要素にイベント登録をすれば、後から追加されるdiv.hitarea要素にもクリックイベントが効くようになります。

 
Chromeの開発ツールで見た目と動作問題ないなーと思っても実機だと挙動が異なることがあるってのを改めて実感しました。(iOSで見てたブラウザもデフォルトのSafariChromeとも異なりますからそりゃ違いもありますよねw)
モバイルサイト製作時はめんどくさがらずに、ケーブル繋いで実機のブラウザで見て確認・デバックをしなきゃなーって思いました。(でも、ちょっとめんどくさい...

過去にaタグだけどclickイベントが効かない事があったのですが、href属性を付けていなかったので、cursor: poinrerのスタイルが無い扱いになってたから、動作しなかったんじゃないかなって今回の件でナゾが判明した気がしました。


[参考]

CSS Fixedしたコンテンツでスクロールさせたい

モバイルのメニューとかposition: fixedでデザインしたけど、メニューが長かったりデバイス回転させたりしたらメニューが見切れるからfixedしたモーダル内でスクロールを表示させたい時の実装方法のメモ

top, left, right, bottom と overflow を利用する

.modalNav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow-y: auto;
}

position: fixedと一緒に top: 0, bottom: 0, left: 0, right: 0 を使用するとコンテンツがエリア全体に伸びるので、そこにoverflowの指定があればfixedしたコンテンツであってもスクロールを表示させることができるようです。
縦方向のスクロールを発生させるだけならtop: 0;bottom: 0;の指定があればleftrightの指定は特に無くても問題ないようでした。

サンプル

See the Pen Scroll in Fixed modal by KIKIKI (@chaika-design) on CodePen.


HTML&CSSとWebデザインが 1冊できちんと身につく本

HTML&CSSとWebデザインが 1冊できちんと身につく本

Wordpress CMB2 1行text(input)フィールドでHTMLタグを入力できるようにしたい。

WordPressにコードベースでカスタムフィールドを作成することが出来るCMB2。

とても便利なのですが、
1行textフィールド(通常のinput[type="text"])はデフォルトだとHTMLタグを保存時に除去(sanitization)する仕様になっていました。(以前はサニタイズされてなかった気がするのだけど...)
HTMLタグが入るなら最初からtextareaにしとけば良いだけなのですが、運用段階でやっぱりこのフィールドにHTMLタグ入れたいんだよね。とかが発生する可能性は無きにもあらずです。

例えば、こんな感じで改行いれたいとか。
f:id:kikiki-kiki:20171110203347p:plain

sanitization_cb を使って独自のサニタイズ処理を適応する

sanitization_cb
Bypass the CMB sanitization (sanitizes before saving) methods with your own callback. Set to false if you do not want any sanitization (not recommended).

サニタイズを変更したいフィールドのを作成している箇所にsanitization_cbプロパティを作成し、値にデータ保存前に値を処理するコールバック関数名を指定します。

<?php // function.php
// <中略>

$cmb->add_field([
  'id'     => $fieldID,
  'name'   => '発売日',
  'type'   => 'text',
  // sanitaize callback
  'sanitization_cb' => 'cmb_allow_html_cb',
]);

// <中略>

/**
 *  Sanitization Handler: Allow HTML tag
 * @param  mixed      $value      The unsanitized value from the form.
 * @param  array      $field_args Array of field arguments.
 * @param  CMB2_Field $field      The field object
 *
 * @return mixed                  Sanitized value to be stored.
 */
function cmb_allow_html_cb($value, $field_args, $field) {
  // 保存する値を返す
  return wp_kses_post( $value );
}

コールバック関数は最後に保存する値をreturnします。
上の例では、値を保存する前に行われるコールバック関数でwp_kses_post()を使ってWordPressの投稿コンテンツと同じHTMLタグが使える様にしています。

これで、この1行テキストの中では改行<br>を始めとするHTMLタグを使うことが出来るようになりました!

加工したい形式ごとに処理関数作成する手間がありますが、デフォルトの処理関数をバイパスできるので自由度が高いです!

公式リファレンスには同じような使い方のescape_cbというプロパティもありましたが、こちらはサニタイズ処理が終わった後で呼び出されるっぽく、既にHTMLが除去された値が$valueで渡されてきたので、HTMLタグを残したい場合には適していませんでした。


[参考]

PHP 配列のキー・Objectのキー(プロパティ)の有無をチェックしたい。

配列のキーの有無のチェック

<?php
// return: bool
array_key_exists( 'key_name', $array );

array_key_exists
指定した key が配列に設定されている場合、 array_key_exists() は TRUE を返します。 key は配列添字として使用できる全ての値を使用可能です。
注意:
array_key_exists() は、最初のレベルのキーだけを捜します。 多次元配列のネストされたキーは、この関数では見つけられません。

isset()との違い

isset() は未定義またはNULLの時 false になるので、配列の値がnullの時、配列にキーが存在してもfalseになってしまう。
ex

<?php
$arr = [
  'str'        => 'text',
  'blank_str'  => '',
  'no'         => 1,
  'zero'       => 0,
  'bool_true'  => true,
  'bool_false' => false,
  'null'       => null,
];

👇 array_key_exists

<?php
array_key_exists("str", $arr);        // => true
array_key_exists("blank_str", $arr);  // => true
array_key_exists("no", $arr);         // => true
array_key_exists("zero", $arr);       // => true
array_key_exists("bool_true", $arr);  // => true
array_key_exists("bool_false", $arr); // => true
array_key_exists("null", $arr);       // => true
array_key_exists("no_key", $arr);     // => false ... 存在しないキーとの時だけfalse

isset

<?php
isset($arr["str"]);        // => true
isset($arr["blank_str"]);  // => true
isset($arr["no"]);         // => true
isset($arr["zero"]);       // => true
isset($arr["bool_true"]);  // => true
isset($arr["bool_false"]); // => true
isset($arr["null"]);       // => false ... 値がnullだとキーが存在してもfalse
isset($arr["no_key"]);     // => false

オブジェクトのプロパティの有無のチェック

<?php
// return: bool
property_exists( $object, 'property_name' );

property_exists
この関数は、与えられたプロパティ property が 指定されたクラスに存在するかどうかを確認します。
注意:
isset() とは対照的に、 プロパティの値が NULL の場合でも property_exists() は TRUE を返します。

プロパティの値が無くても、プロパティが存在していれば true になる

変数が何の型なのか調べる

<?php
// return: string
gettype( $var );

gettype
PHP 変数 var の型を返します。 型のチェックには、この関数ではなく is_* 関数を使います。


[参考]

初めてのPHP

初めてのPHP

お知らせ。「放射線について考えよう」

こちらのWEBサイトのイラストを担当させていただいております。

多田将先生のわかりやすい文章で章ごとにステップを積むように理解が深まっていくサイトです。 各章5~15分程度で読めてしまうと思いますので、チラッとでも読んでみてください!!

以前に多田先生の本について書いた記事がりますのでこちらもよろしければ。

以上、宣伝でした。


宇宙のはじまり (イースト新書Q)

宇宙のはじまり (イースト新書Q)

ニュートリノ (イースト新書Q)

ニュートリノ (イースト新書Q)