| この記事の要点 |
|---|
|
エラー内容
|
A non well formed numeric value encountered |
この文言はPHP 7.1〜7.4で、先頭だけ数値として読める文字列を算術演算に使った際のE_NOTICEです。PHP 8では同じ先頭数値の条件はE_WARNINGのA non-numeric value encounteredとなり、数値として始まらない文字列の算術演算はTypeErrorになります。実行したPHP版と入力値を分けて調べてください。
発生条件 / 原因
- 数値に変換できない(先頭が数値だが末尾に非数字が含まれる)文字列を四則演算の対象にしたとき
- 例:
"10abc" + 5→ 値は15になるが、PHP 7.4ではNotice、PHP 8.5ではWarningが出る - 例:
"1.5kg" * 2→ 値は3になるが、PHP 7.4ではNotice、PHP 8.5ではWarning - DBから取得した値、HTTPリクエストパラメータ、CSV読み込みなど、外部からの文字列を直接演算しているケース
- 日付の差分計算で
"2024-01-01"をそのまま演算した
対処法
1. 明示的に数値型へキャストする
以下は変換の例として残します。入力検証の代わりにはなりません。10abcが10、abcが0になると、警告が消えても誤った数量を受け入れるおそれがあります。先に形式・単位・範囲を検証してください。
|
$result = (int) $value + 5; |
2. intval() / floatval() を使う
|
$result = intval($value) + 5; |
上の文字列例は先頭の数値部分だけに変換され、算術演算の警告が出なくなります。数値で始まらない文字列も0へ変換され得るので、警告が消えたことだけを正しい入力の証明にしないでください。
3. 事前にバリデーションする
入力値が想定外の文字列の場合は弾く方が安全です。
|
if (!is_numeric($value)) { |
4. Laravel等のフレームワーク
Laravelのrequest()->integer()は整数への変換であり、入力検証ではありません。Laravel 13でqty=10abcを渡すとinteger(qty)は10でした。Validationで形式と範囲を先に検査し、成功後に変換します。numericは小数や指数表記も対象になるため、整数数量ならintegerとmin/maxなど、用途に合うルールを選んでください。
|
$request->validate(['qty' => 'required|integer|min:1']); |
PHPバージョン別の挙動
| PHPバージョン | 挙動 |
|---|---|
| PHP 7.0以前 | 警告なしで暗黙変換 |
| PHP 7.1 – 7.4 | 「A non well formed numeric value encountered」E_NOTICE(先頭だけ数値の文字列)。完全非数値の演算はE_WARNING |
| PHP 8.0以降 | 部分数値はWarning、完全に非数値はTypeError |
注意点
- Notice/Warningは通常のPHPでは継続し得るが、フレームワークのエラーハンドラが例外へ変換する場合もある。ログと実際の停止条件を確認する
- PHP 8では完全非数値の算術演算は
TypeError。先頭だけ数値の文字列のWarningとは区別する error_reportingで抑制するのではなく、入力値を正しい型にする方向で直す
再現した入力と結果
| 演算 | PHP 7.4.33 | PHP 8.5.1 |
|---|---|---|
| 10abc + 5(文字列) | 15 / E_NOTICE | 15 / E_WARNING |
| 1.5kg * 2(文字列) | 3 / E_NOTICE | 3 / E_WARNING |
| abc + 5(文字列) | 5 / E_WARNING | TypeError |
| (int)10abc(文字列) | 10、演算のNoticeなし | 10、演算のWarningなし |
最後の行は文字列の明示変換です。不正な入力を正しくしたのではなく、数値以外の部分を無視した結果です。検証では一時的なエラーハンドラでレベルと文言を記録しました。本番でerror_reportingを下げたり、例外だけ無視して処理を通したりする対処は勧めません。
整数数量なら形式と範囲を検証する
以下は数量を1〜1000の整数に限定する独立例です。小数・指数表記・単位付き文字列・配列・真偽値を数量として受け入れません。01のような表記もFILTER_VALIDATE_INTの規則に従って判定されるため、許可する入力形式は業務仕様で決めてください。
<?php
function parseQuantity($value): int
{
if (!is_int($value) && !is_string($value)) {
throw new InvalidArgumentException('Quantity must be an integer or integer string');
}
$quantity = filter_var($value, FILTER_VALIDATE_INT, [
'options' => ['min_range' => 1, 'max_range' => 1000],
]);
if ($quantity === false) {
throw new InvalidArgumentException('Quantity must be between 1 and 1000');
}
return $quantity;
}
// Example: parseQuantity('10') returns 10; parseQuantity('10abc') throws.parseQuantity(10)と文字列10は成功し、10abcや1.5kgは例外になります。小数の測定値などは、この数量用関数を使い回さず、単位・小数点・許容範囲を別に設計します。is_numericは数値文字列かの判定であって、正の整数数量や上限を保証するものではありません。
Laravelで検証してから取り出す例
元のmin:1例に上限も付ける場合のコントローラ断片です。実際の上限は業務仕様へ合わせてください。
$request->validate(['qty' => 'required|integer|min:1|max:1000']);
$qty = $request->integer('qty');Laravel 13のValidatorで文字列10は成功し、10abc・0・-1・1.5・1001は失敗することを確認しました。元のコード例は維持し、変換と入力検証の違いを補足しています。
日付や単位付きデータは数値変換しない
2024-01-01のような日付文字列をキャストすると年の数値だけを読むなど、警告が消えても日数計算にはなりません。日付は日付として解析し、書式・存在する日付・タイムゾーンを検証してから差分を求めます。kgや通貨記号も無条件に除去せず、入力仕様に沿って解析してください。
今回の確認範囲はPHP 7.4.33 / 8.5.1の演算・警告レベル・変換、数量関数の正常2/異常13ケース、Laravel 13の変換と検証6ケースです。PHP 7系は保守用の比較で、新規導入は勧めません。実システムのすべての演算箇所・HTTPエラー処理は未検証です。
公式資料: PHPの数値文字列と版による違い、Laravelの整数入力取得、Laravelの入力検証(2026年10月確認)。
子ページはありません
- Fatal error: Maximum execution time of 30 seconds exceeded in...
- Fatal error: Uncaught Error: Cannot use object of type stdClass as array in ...
- Warning: Use of undefined constant ... - assumed '...' (this will throw an Error)
- ERROR: Call to undefined method Maatwebsite\Excel\Excel::load()
- Maximum execution time of 30 seconds exceeded
- Your requirements could not be resolved to an installable set of packages. ... To enable extensions, verify that they are enabled in your .ini files:
- could not find driver
- the requested PHP extension mbstring is missing from your system.
- the requested PHP extension dom is missing from your system.
- A non well formed numeric value encountered
- Warning: Cannot modify header information - headers already sent by ...
- php_network_getaddresses: getaddrinfo failed: Name or service not known
- XMLWriter::openUri(): Unable to resolve file path
- Object of class stdClass could not be converted to string
- Class 'Google_Service_Youtube' not found
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38