Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHP 8 になるまでの sort は相当ヤバい
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
taisuke arase
September 27, 2024
Technology
0
85
PHP 8 になるまでの sort は相当ヤバい
taisuke arase
September 27, 2024
Tweet
Share
More Decks by taisuke arase
See All by taisuke arase
PHP 9 に備えよ - 動的プロパティ、どうすればいぃ?
taisukearase
0
6.6k
Other Decks in Technology
See All in Technology
私たち準委任PdEは2つのプロダクトに挑戦する ~ソフトウェア、開発支援という”二重”のプロダクトエンジニアリングの実践~ / 20260212 Naoki Takahashi
shift_evolve
PRO
2
200
We Built for Predictability; The Workloads Didn’t Care
stahnma
0
150
Exadata Fleet Update
oracle4engineer
PRO
0
1.1k
生成AIと余白 〜開発スピードが向上した今、何に向き合う?〜
kakehashi
PRO
0
150
今こそ学びたいKubernetesネットワーク ~CNIが繋ぐNWとプラットフォームの「フラッと」な対話
logica0419
5
430
Why Organizations Fail: ノーベル経済学賞「国家はなぜ衰退するのか」から考えるアジャイル組織論
kawaguti
PRO
1
190
AIが実装する時代、人間は仕様と検証を設計する
gotalab555
1
290
Agile Leadership Summit Keynote 2026
m_seki
1
670
旅先で iPad + Neovim で iOS 開発・執筆した話
zozotech
PRO
0
100
Claude_CodeでSEOを最適化する_AI_Ops_Community_Vol.2__マーケティングx_AIはここまで進化した.pdf
riku_423
2
610
コスト削減から「セキュリティと利便性」を担うプラットフォームへ
sansantech
PRO
3
1.6k
プロポーザルに込める段取り八分
shoheimitani
1
640
Featured
See All Featured
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
110
Odyssey Design
rkendrick25
PRO
1
500
Crafting Experiences
bethany
1
51
Designing Experiences People Love
moore
144
24k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
61k
Docker and Python
trallard
47
3.7k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.1k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.8k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
58
50k
Building Adaptive Systems
keathley
44
2.9k
Un-Boring Meetings
codingconduct
0
200
Transcript
PHP 8 になるまでの sort は相当ヤバい 2024.09.28 PHP Conference Okinawa 2024
荒瀬 泰輔 #phpcon_okinawa #track_a
荒瀬 泰輔 @at_taisuke PHPer歴 5年くらい サイボウズかき氷部の部長 2024月刊ぺちこん参加 北海道 東京 香川
福岡 沖縄 2
3
沖縄のおすすめかき氷 4
かんな +plus さん 東京の三宿の人気店「和キッチン かんな」の分店 沖縄ならではの食材を使ったかき 氷 写真は「イエロー」 (パッション フルーツとマンゴーのかき氷)
5
avocafe さん アボカド料理店 クリーミーなアボカドはかき氷 にしても美味しい! 写真は「アボカドキャラメルナッ ツ」 6
行きたいお店 天の群星(てぃんのむりぶし) PLUS MINUS 琉冰( Ryu-Pin) 皆さんのおすすめかき氷、沖縄ぜんざいのお店あったら #phpcon_okinawa で教えてください! 7
本題 8
…の前に 9
[悲報 ] タイトル、半分釣りだった 10
結論 数値と文字列をごちゃ混ぜにした配列を sort しようとしている のがヤバい とはいえ PHP 8 より前の比較演算もヤバいのでどっちもヤバい sort
をするならヤバいコードは掃討しましょう 11
Agenda 当初話す予定だったブログ記事の紹介 x でのご指摘を受けての再調査 PHP の比較の挙動 おまけ PHP の比較 true
or false ? クイズ 「数値から始まる文字列」について 12
当初話す予定だったブログ記事の紹介 13
事前にこの場で話す内容をブログ記事に してました 「 CYBOZU SUMMER BLOG FES '24」 という企画で 8/15
に公開 PHP 8 になるまでの sort は相当ヤバい https://zenn.dev/t_arase/articles/0a12bfd6a76e25 当初話す予定だったブログ記事の紹介 14
PHP 7の比較に矛盾が生じてるぞ! <?php // PHP 7.4.33 var_dump(11 < '12'); //
true var_dump('12' < 'a1'); // true var_dump('a1' < 10); // true var_dump(10 < 11); // true 当初話す予定だったブログ記事の紹介 15
当初話す予定だったブログ記事の紹介 https://commons.wikimedia.org/wiki/File:Impossible_staircase.svg より 16
sort の結果もおかしいぞ! <?php $arr1 = [11, 10, '12', 'a1']; sort($arr1);
var_export($arr1); echo PHP_EOL; $arr2 = ['12', 'a1', 11, 10]; sort($arr2); var_export($arr2); echo PHP_EOL; var_dump($arr1 === $arr2); 当初話す予定だったブログ記事の紹介 17
# PHP 7.4.33 array ( 0 => 10, 1 =>
11, 2 => '12', 3 => 'a1', ) array ( 0 => '12', 1 => 'a1', 2 => 10, 3 => 11, ) bool(false) // var_dump($arr1 === $arr2) 当初話す予定だったブログ記事の紹介 18
PHP 8 でこの矛盾が解消されたぞ! <?php // PHP 8.0.0 var_dump(11 < '12');
// true var_dump('12' < 'a1'); // true var_dump('a1' < 10); // false ここが変わった var_dump(10 < 11); // true 当初話す予定だったブログ記事の紹介 19
PHP 8 で比較演算の挙動が変わったため 数値と「数値形式ではない文字列」を比較する際 PHP 7 まで:文字列を数値に変換してから比較 PHP 8 から:数値を文字列に変換してから比較
するようになった 数値と「数値形式の文字列」を比較する際は今まで通り文字列を数値 に変換してから比較する 'hoge' == 0; // true PHP 7.4.33 まで 'hoge' == 0; // false PHP 8.0.0 から 当初話す予定だったブログ記事の紹介 PHP RFC: Saner string to number comparisons https://wiki.php.net/rfc/string_to_number_comparison より 20
sort 順も正しくなった! // PHP 8.0.0 array ( 0 => 10,
1 => 11, 2 => '12', 3 => 'a1', ) array ( 0 => 10, 1 => 11, 2 => '12', 3 => 'a1', ) bool(true) 当初話す予定だったブログ記事の紹介 21
PHP 8 までの sort は相当おかしい! ヨシ! 当初話す予定だったブログ記事の紹介 22
x でのご指摘を受けての再調査 23
記事公開後、コメントをいただきました 文字列と数値混じりの sortができるように変わったと誤解しそう なので、できない例も載せても良いのではと思いました var_dump(11 < '12'); var_dump('12' < '3a');
var_dump('3a' < '4'); var_dump('4' < 11); x でのご指摘を受けての再調査 ぺん! @tompng さんありがとうございました! https://x.com/at_taisuke/status/1824000184231321736 24
確かに PHP 8 でも比較がおかしいよう な …? // PHP 8.0.0 var_dump(11
< '12'); // true var_dump('12' < '3a'); // true var_dump('3a' < '4'); // true var_dump('4' < 11); // true x でのご指摘を受けての再調査 25
$arr1 = [11, '4', '12', '3a']; sort($arr1); var_export($arr1); $arr2 =
['12', '3a', 11, '4']; sort($arr2); var_export($arr2); var_dump($arr1 === $arr2); array ( 0 => '4', 1 => 11, 2 => '12', 3 => '3a', ) array ( 0 => 11, 1 => '12', 2 => '3a', 3 => '4', ) bool(false) x でのご指摘を受けての再調査 26
自分の遭遇した例がたまたま PHP 8 でいい感じになっただけで、 ダメなパターンもある どうしてこういう結果になるのか再度調査しなくては x でのご指摘を受けての再調査 27
PHP の比較の挙動 28
文字列同士の比較 先頭の文字から順に Unicode 値を使い辞書的に比較する 'a' < 'b'; // true 'a'
< 'A'; // false 'a ' < 'a1' // true PHP の比較の挙動 29
おさらい: PHP 8 での比較で変わった点 数値と「数値形式ではない文字列」を比較する際 PHP 7 まで:文字列を数値に変換してから比較 PHP 8
から:数値を文字列に変換してから比較 するようになった 数値と「数値形式の文字列」を比較する際は今まで通り文字列を数値 に変換してから比較する 'hoge' == 0; // true PHP 7.4.33 まで 'hoge' == 0; // false PHP 8.0.0 から PHP の比較の挙動 30
「数値形式の文字列」について PHP には「数値形式の文字列( numeric strings) 」という概念があ る PHP 7.4.33 までは「
0個以上のスペース + 数値」がこれに該当した が、 PHP 8 からは「 0個以上のスペース + 数値 + 0個以上のスペース」に 変更になった // 数値形式の文字列の例 '11' ' 11 ' // 後ろにスペースがあるため、PHP 8 より前ではただの文字列扱いだった '000011' '11.0' '+11.0E0' PHP の比較の挙動 31
コメントをもらった例を見てみる 11 < '12'; // true // 数値と「数値形式の文字列」の比較のため、「数値形式の文字列」を数値として扱う '12' <
'3a'; // true // 文字列同士の比較となり、最初の1文字目の Unicode で比較される '3a' < '4'; // true // 文字列同士の比較となり、最初の1文字目の Unicode で比較される '4' < 11; // true // 数値と「数値形式の文字列」の比較のため、「数値形式の文字列」を数値として扱う 何と比較されるかで、その値が文字列として扱われるか、数値として 扱われるか変わるため、 sort して順番をつけることができない つまりこんな値を sort しようとするのが悪い PHP の比較の挙動 32
結論 数値と文字列をごちゃ混ぜにした配列を sort しようとしている のがヤバい とはいえ PHP 8 より前の比較演算もヤバいのでどっちもヤバい sort
をするならヤバいコードはそーっとしておかずに掃討しまし ょう 33
ここまで話せたらあとはおまけ 34
PHP の比較 true or false ? クイズ 35
全て PHP 8.0.0 以降の結果で考えてください 全部で 4問です PHP の比較 true or
false ? クイズ 36
10 < 11 true or false ? PHP の比較 true
or false ? クイズ 37
true 数値どうしの比較 10 < 11 PHP の比較 true or false
? クイズ 38
1 < '1 ' true or false ? PHP の比較
true or false ? クイズ 39
false 数値と「数値形式の文字列」の比較のため、 「数値形式の文字列」を 数値として扱う 1 < '1 ' PHP の比較
true or false ? クイズ 40
'1a' < 10 true or false ? PHP の比較 true
or false ? クイズ 41
false 文字列どうしの比較となり、数値を文字列として扱い 1文字目から順 に Unicode で比較される '1a' < 10 ちなみに
PHP 7.4.33 までだと '1a' が数値として扱われ、数値どう しの比較になり、 true になる PHP の比較 true or false ? クイズ 42
'123' < '45 ' true or false ? PHP の比較
true or false ? クイズ 43
false 「数値形式の文字列」どうしの比較になり、両方を数値として扱う '123' < '45 ' ちなみに PHP 7.4.33 までだと
'45 ' が文字列として扱われ、最初 の文字の '1' と '4' の比較の結果、 true になる PHP の比較 true or false ? クイズ 44
「数値から始まる文字列」について 45
「数値から始まる文字列」について PHP には「数値から始まる文字列 (leading-numeric strings)」 という概念も存在する 「数値から始まる文字列」は「数値形式の文字列」 + 任意の文字列 で構成される
'123abc' これは比較演算の際にはただの文字列と同じ扱いになる '123' < '45abc' // true 「数値から始まる文字列」について 46
「数値から始まる文字列」について 「数値から始まる文字列」は数値にキャストした場合には「数値形式 の文字列」部分を数値に変換した値になる var_dump((int) '45abc'); // 45 var_dump((int) 'abc45'); //
0 「数値から始まる文字列」は 数値型が宣言されている引数に入れる ことはできない。 function foo(int $i) { var_dump($i); } foo("123 "); // int(123) foo("123abc"); // TypeError 「数値から始まる文字列」について 47
「数値から始まる文字列」かどうかの見 分け方 「数値から始まる文字列」かどうかは数値に足してみて warning が 出るかどうかで判断できる。 ( PHP 8.3 )
var_dump(123 + "123 "); // int(246) var_dump(123 + "123a"); // Warning: A non-numeric value encountered // int(246) 「数値から始まる文字列」について 48
PHP 7.4.33 までの「数値形式の文字列」 PHP 7.4.33 までは、数値の後ろにスペースがある場合は「数値から 始まる文字列」扱いとなっていた。 // PHP 7.4.33
var_dump(123 + "123 "); // Notice: A non well formed numeric value encountered // int(246) 「数値から始まる文字列」について 49
ご清聴ありがとうございました! 50