Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PHP 8 になるまでの sort は相当ヤバい
Search
taisuke arase
September 27, 2024
Technology
110
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
PHP 8 になるまでの sort は相当ヤバい
taisuke arase
September 27, 2024
More Decks by taisuke arase
See All by taisuke arase
PHP 9 に備えよ - 動的プロパティ、どうすればいぃ?
taisukearase
0
7.6k
Other Decks in Technology
See All in Technology
30座EKS, 180次升級淬煉的EKS Upgrade Skill 的歷程
eric8230
0
200
SREの視点で考えるSIEM活用術 〜AWS環境でのセキュリティ強化〜
cscengineer
PRO
0
130
AIエージェントの権限管理 3: Agentic RAG の Fine grained access control 編
ren8k
0
160
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
12k
AI時代の「技術的負債」の変質ー概念の終焉と再解釈、エージェントと共に向かう先
nwiizo
1
3k
株式会社シーエーシー エンジニア向け会社紹介資料
cac
0
57k
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
30
17k
技術的負債から考える、AI時代のエンジニアリング投資 — ビズリーチの技術的負債と向き合った経験から、変更し続けられるソフトウェアを考える/ technical-debt-con2026
visional_engineering_and_design
4
3.3k
Cloudflare Workers 向けアプリを C# で構築する ~WASM Native AOT への道~
nenonaninu
1
600
EventBridge に「合流」はない ― サーバーレスのワークフローを育てるということ / No Join in EventBridge
yusukeshimizu
2
340
LLMに渡さなかった仕事
nanaism
0
1.2k
「守り」で活用するオンデバイスLLM 〜写ってはいけないを総力戦で防ぐ〜 / iOSDC Japan 2026
nakamuuu
0
180
Featured
See All Featured
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Claude Code のすすめ
schroneko
67
230k
Paper Plane
katiecoart
PRO
4
53k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
18k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.8k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
660
Product Roadmaps are Hard
iamctodd
55
13k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
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