Merge pull request 'PHP 8.5が必須になった' (#33) from php85 into master

Reviewed-on: http://192.168.10.104:3000/suwako/LittleBeast/pulls/33

suwako <suwako@076.moe>、2026-05-06 03:51
コミット 65fa46e5a92ba07732e70c0acaaab8a8e20b2be9 ・親 0223951 ・親 ca9e2f8 ・ファイルを見る

9個のファイル、+33 -37

変更 CHANGELOG.md
@@ -1,5 +1,6 @@
11 # 0.5 (2026年??月??日)
22 * OpenProviderライブラリ
3+* PHP 8.5以上が必須になった
34
45 # ローリング・リリース (2025年01月01日)
56 * 最初プライベートリリース
変更 README-JP.md
@@ -7,7 +7,7 @@
77 サンプル:[https://lbdemo.technicalsuwako.moe/](https://lbdemo.technicalsuwako.moe/)
88
99 ## Little Beast とは?
10-Little Beast は PHP 8.3 以上向けのフレームワークで、076.moe(ゲーム開発会社)と technicalsuwako.moe(社長のブログ)向けに作られました。\
10+Little Beast は PHP 8.5 以上向けのフレームワークで、076.moe(ゲーム開発会社)と technicalsuwako.moe(社長のブログ)向けに作られました。\
1111 メイン考え方は「必要な物だけ拡張し、不要な物は削除する」です。\
1212 各コア機能はライブラリに分割されている為、必要な物だけを選び易い設計になっています。\
1313 全てのモジュールはゼロから書かれており、データベースは一切必要ありません。
@@ -68,9 +68,9 @@
6868
6969 ### OpenBSD サーバー
7070 ```sh
71-pkg_add php-8.4.14 php-gmp-8.4.14
72-rcctl enable php84_fpm httpd relayd
73-rcctl start php84_fpm httpd relayd
71+pkg_add php-8.5.5 php-gmp-8.5.5
72+rcctl enable php85_fpm httpd relayd
73+rcctl start php85_fpm httpd relayd
7474 ```
7575
7676 #### httpd
変更 README.md
@@ -7,7 +7,7 @@
77 Demo installation: [https://lbdemo.technicalsuwako.moe/](https://lbdemo.technicalsuwako.moe/)
88
99 ## What is Little Beast?
10-Little Beast is a PHP 8.3 or above framework made for 076.moe (game developer company) and technicalsuwako.moe (CEO's blog).\
10+Little Beast is a PHP 8.5 or above framework made for 076.moe (game developer company) and technicalsuwako.moe (CEO's blog).\
1111 The core mentality is to extend what you need, and remove what you don't need.\
1212 Each core feature is split into libraries, so it is easy to choose what you need.\
1313 All modules are written from scratch, nothing is to be require a database.
@@ -68,9 +68,9 @@
6868
6969 ### OpenBSD server
7070 ```sh
71-pkg_add php-8.4.14 php-gmp-8.4.14
72-rcctl enable php84_fpm httpd relayd
73-rcctl start php84_fpm httpd relayd
71+pkg_add php-8.5.5 php-gmp-8.5.5
72+rcctl enable php85_fpm httpd relayd
73+rcctl start php85_fpm httpd relayd
7474 ```
7575
7676 #### httpd
変更 route.php
@@ -66,7 +66,7 @@
6666 ];
6767
6868 if (ACTIVITYPUB_ENABLED) {
69- $routes[] = Route::add('GET', '.well-known/webfinger', Home::class.'@apfinger');
69+ $routes[] = Route::add('GET', '.well-known/webfinger', Fediverse::class.'@apfinger');
7070 $routes[] = Route::add('GET', 'ap/following', Fediverse::class.'@apfollowing');
7171 $routes[] = Route::add('GET', 'ap/followers', Fediverse::class.'@apfollowers');
7272 $routes[] = Route::add('GET', 'ap/outbox', Fediverse::class.'@apoutbox');
@@ -39,6 +39,7 @@
3939
4040 use Std\Lib\Curl;
4141 use LogType;
42+use Uri\Rfc3986\Uri;
4243
4344 /**
4445 * ActivityPubプロトコルの実装クラス
@@ -298,14 +299,14 @@
298299 */
299300 public function getWebfinger(): string {
300301 if (!ACTIVITYPUB_ENABLED) return '';
301- $domain = str_replace(['http://', 'https://'], '', $this->domain);
302+ $uri = new Uri($this->domain);
302303 $webfinger = [
303- 'subject' => "acct:{$this->actor}@{$domain}",
304+ 'subject' => "acct:{$this->actor}@{$uri->getHost()}",
304305 'links' => [
305306 [
306307 'rel' => 'self',
307308 'type' => 'application/activity+json',
308- 'href' => "{$domain}/ap/actor",
309+ 'href' => "{$this->domain}/ap/actor",
309310 ],
310311 ],
311312 ];
@@ -445,10 +446,10 @@
445446 $body = json_encode($activity, JSON_UNESCAPED_SLASHES);
446447 $digest = base64_encode(hash('sha256', $body, true));
447448 $date = gmdate('D, d M Y H:i:s \G\M\T');
448- $host = parse_url($inboxUrl, PHP_URL_HOST);
449+ $uri = new Uri($inboxUrl);
449450
450451 $headers = [
451- 'Host' => $host,
452+ 'Host' => $uri->getHost().($uri->getPort() ? ':'.$uri->getPort() : ''),
452453 'Date' => $date,
453454 'Content-Type' => 'application/activity+json',
454455 'Digest' => "SHA-256=$digest",
@@ -38,6 +38,7 @@
3838 namespace Std\Lib;
3939
4040 use Result;
41+use Uri\Rfc3986\Uri;
4142
4243 /**
4344 * php_curlへの依存を排除するための独自のCURL実装
@@ -354,19 +355,18 @@
354355 fwrite($this->stderr, "* 接続中: {$currentUrl}\n");
355356 }
356357
357- $parsed = parse_url($currentUrl);
358- if (!$parsed) {
358+ $uri = new Uri($currentUrl);
359+ if (!$uri) {
359360 $this->responseError = "無効なURL: {$currentUrl}";
360361 return Result::Error($this->responseError);
361362 }
362363
363- $scheme = isset($parsed['scheme']) ? strtolower($parsed['scheme']) : 'http';
364- $host = $parsed['host'];
365- $port = isset($parsed['port'])
366- ? $parsed['port'] : ($scheme === 'https' ? 443 : 80);
367- $path = isset($parsed['path']) ? $parsed['path'] : '/';
368- if (isset($parsed['query'])) {
369- $path .= '?'.$parsed['query'];
364+ $scheme = $uri->getScheme() ?? 'http';
365+ $port = $uri->getPort() ?? ($scheme === 'https' ? 443 : 80);
366+ $path = $uri->getPath();
367+ if ($path === '') $path = '/';
368+ if (NULL !== $uri->getQuery()) {
369+ $path .= '?'.$uri->getQuery();
370370 }
371371
372372 // 認証
@@ -404,7 +404,7 @@
404404 }
405405
406406 $request = "{$method} {$path} HTTP/1.1\r\n";
407- $request .= "Host: {$host}\r\n";
407+ $request .= "Host: {$uri->getHost()}\r\n";
408408 $request .= "User-Agent: {$this->userAgent}\r\n";
409409 $request .= "{$accept}\r\n";
410410 $request .= "Connection: close\r\n";
@@ -462,7 +462,7 @@
462462 $context = stream_context_create(['ssl' => $sslOptions]);
463463
464464 $socket = @stream_socket_client(
465- "tls://{$host}:{$port}",
465+ "tls://{$uri->getHost()}:{$port}",
466466 $errno,
467467 $errstr,
468468 $this->timeout,
@@ -470,7 +470,7 @@
470470 $context
471471 );
472472 } else {
473- $socket = @fsockopen($host, $port, $errno, $errstr, $this->timeout);
473+ $socket = @fsockopen($uri->getHost(), $port, $errno, $errstr, $this->timeout);
474474 }
475475
476476 if (!$socket) {
@@ -637,9 +637,9 @@
637637
638638 if (strpos($redirectUrl, 'http') !== 0) {
639639 if ($redirectUrl[0] === '/') {
640- $parsed = parse_url($currentUrl);
641- $redirectUrl = $parsed['scheme'].'://'.$parsed['host']
642- .(isset($parsed['port']) ? ':'.$parsed['port'] : '')
640+ $uri = new Uri($currentUrl);
641+ $redirectUrl = $uri->getScheme().'://'.$uri->getHost()
642+ .(NULL !== $uri->getPort() ? ':'.$uri->getPort() : '')
643643 .$redirectUrl;
644644 } else {
645645 $redirectUrl = dirname($currentUrl).'/'.$redirectUrl;
@@ -407,6 +407,7 @@
407407 */
408408 public function assertArrayHasKey(mixed $key, array $array,
409409 ?string $message = null): Tester {
410+ if (NULL === $key) throw new AssertionFailedException("配列鍵がありません");
410411 if (!is_array($array) && !($array instanceof \ArrayAccess)) {
411412 throw new AssertionFailedException(
412413 '第2引数は配列又はArrayAccessを実装している必要があります');
変更 util.php
@@ -471,10 +471,3 @@
471471 while ($lower * 2 <= $val) $lower *= 2;
472472 return $lower;
473473 }
474-
475-// PHP 8.3と8.4の場合
476-if (!function_exists('array_last')) {
477- function array_last(array $array): mixed {
478- return $array === [] ? null : $array[array_key_last($array)];
479- }
480-}
@@ -20,7 +20,7 @@
2020 {@ endif @}
2121 {@ endif @}
2222 <meta name="description" content="{{ $description }}" />
23- <meta name="keywords" content="{{ SITEINFO['tags'].(isset($meta->category) ? ',' : '') }}{@ if (isset($meta) && isset($meta->category)) @}{@ foreach ($meta->category as $k => $cat) @}{{ $cat.($k === array_key_last($meta->category) ? '' : ',') }}{@ endforeach @}{@ endif @}" />
23+ <meta name="keywords" content="{{ SITEINFO['tags'].(isset($meta->category) ? ','.implode(',', $meta->category) : '') }}" />
2424
2525 <meta property="og:title" content="{{ SITEINFO['title'] }}: {{ $pagetit }}" />
2626 <meta property="og:description" content="{{ $description }}" />