はじめに
PHPは動的型付け言語であり、変数の型は実行時に自動で変換されることが多いですが、明示的に型を変換したい場面は少なくありません。そのための手段として、PHPには大きく2つのアプローチがあります。
- キャスト演算子:
(int)$val・(string)$valのように新しい値を返す settype():変数そのものの型を破壊的に変換する
settype() は変数を参照渡しで受け取り、変数自体の型と値を直接書き換える関数です。戻り値は成功/失敗を示す bool であり、変換後の値は引数の変数に反映されます。
本記事では、この独特な挙動を持つ settype() の仕様・変換規則・実践的なユースケースを詳しく解説します。
関数の基本情報
| 項目 | 内容 |
|---|---|
| 関数名 | settype() |
| 利用可能バージョン | PHP 4以降 |
| 所属 | 変数操作関数(Variable Handling) |
| 戻り値 | bool(成功時true、失敗時false) |
| 拡張機能 | 不要(コア関数) |
シグネチャ
settype(mixed &$var, string $type): bool
パラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
$var | mixed& | 型を変換する変数(参照渡し) |
$type | string | 変換後の型名(下表参照) |
指定できる型名
$type 文字列 | 変換後の型 |
|---|---|
"bool" / "boolean" | bool |
"int" / "integer" | int |
"float" / "double" | float |
"string" | string |
"array" | array |
"object" | object(stdClass) |
"null" | null |
上記以外の文字列を渡すと
falseを返します。
キャスト演算子との決定的な違い
$a = "42";
$b = "42";
// キャスト:元の変数は変わらず、新しい値を返す
$intVal = (int)$a;
var_dump($a); // string(2) "42" ← 変わっていない
var_dump($intVal); // int(42)
// settype:変数そのものが書き換わる
settype($b, 'int');
var_dump($b); // int(42) ← 変数自体が変わった
使い分けの指針
| 観点 | キャスト (int)$v | settype($v, 'int') |
|---|---|---|
| 変数への影響 | 元の変数は不変 | 元の変数を破壊的に変換 |
| 戻り値 | 変換後の値 | 成功/失敗の bool |
| 可読性 | 高い(一目で型がわかる) | やや低い |
| 動的な型指定 | ❌ 型を文字列で渡せない | ✅ 型名を変数で渡せる |
| 主な用途 | 一般的な型変換 | 動的・ループでの一括変換 |
型変換の動作一覧
→ int への変換
| 元の値 | 変換後 | 備考 |
|---|---|---|
true | 1 | |
false | 0 | |
"42" | 42 | |
"3.9" | 3 | 切り捨て |
"12abc" | 12 | 先頭の数値部分のみ |
"abc" | 0 | 数値でない場合は0 |
null | 0 | |
3.9 | 3 | 切り捨て |
→ float への変換
| 元の値 | 変換後 |
|---|---|
"3.14" | 3.14 |
"1e3" | 1000.0 |
true | 1.0 |
null | 0.0 |
→ bool への変換
Falsy(falseになる値) | Truthy(trueになる値) |
|---|---|
0、0.0、"0"、""、[]、null | それ以外すべて |
→ string への変換
| 元の値 | 変換後 |
|---|---|
true | "1" |
false | "" |
null | "" |
42 | "42" |
3.14 | "3.14" |
→ array への変換
| 元の値 | 変換後 |
|---|---|
スカラー値 $v | [$v](要素1つの配列) |
null | [](空配列) |
| オブジェクト | プロパティ名をキーにした配列 |
→ object への変換
| 元の値 | 変換後 |
|---|---|
連想配列 ['k'=>'v'] | (object)['k'=>'v'](stdClass) |
| スカラー値 | scalarプロパティを持つstdClass |
null | 空のstdClass |
実践サンプル集(PHP 8.x対応)
サンプル1:基本的な型変換の動作確認
<?php
declare(strict_types=1);
$cases = [
['42', 'int'],
['3.14', 'float'],
[0, 'bool'],
[1, 'bool'],
['hello', 'int'],
['12abc', 'int'],
[null, 'string'],
[true, 'string'],
[false, 'string'],
['99.9', 'int'],
];
echo str_pad('元の値', 14) . str_pad('型', 8) . "変換後\n";
echo str_repeat('-', 45) . "\n";
foreach ($cases as [$value, $type]) {
$before = var_export($value, true);
$var = $value;
settype($var, $type);
$after = var_export($var, true);
printf("%-14s %-8s %s\n", $before, "→ {$type}", $after);
}
実行結果:
元の値 型 変換後
---------------------------------------------
'42' → int 42
'3.14' → float 3.14
0 → bool false
1 → bool true
'hello' → int 0
'12abc' → int 12
NULL → string ''
true → string '1'
false → string ''
'99.9' → int 99
解説: '12abc'→intが12になる(先頭の数値部分を採用)、'hello'→intが0になるなど、PHPの型ジャグリングの挙動がsettype()でも同様に適用されます。
サンプル2:動的な型名を使った一括バリデーション・変換
型名を動的に文字列で渡せるsettype()の最大の強みを活かしたパターンです。
<?php
declare(strict_types=1);
/**
* フォーム入力値を定義したスキーマに従って型変換するクラス
*/
class FormTypeCaster
{
/**
* @param array<string, string> $schema フィールド名 => 期待する型
*/
public function __construct(
private readonly array $schema
) {}
/**
* @param array<string, mixed> $input
* @return array<string, mixed>
*/
public function cast(array $input): array
{
$result = [];
foreach ($this->schema as $field => $type) {
if (!array_key_exists($field, $input)) {
continue;
}
$value = $input[$field];
if (!settype($value, $type)) {
throw new \InvalidArgumentException(
"'{$type}' は有効な型ではありません(フィールド: {$field})"
);
}
$result[$field] = $value;
}
return $result;
}
}
// 使用例:フォーム送信データ(すべて文字列として届く)
$rawInput = [
'user_id' => '42',
'age' => '25',
'price' => '1980.5',
'is_active' => '1',
'name' => 'Alice',
'score' => '87.3',
];
$schema = [
'user_id' => 'int',
'age' => 'int',
'price' => 'float',
'is_active' => 'bool',
'name' => 'string',
'score' => 'float',
];
$caster = new FormTypeCaster($schema);
$casted = $caster->cast($rawInput);
foreach ($casted as $key => $value) {
printf("%-12s : %-8s = %s\n", $key, gettype($value), var_export($value, true));
}
実行結果:
user_id : integer = 42
age : integer = 25
price : double = 1980.5
is_active : boolean = true
name : string = 'Alice'
score : double = 87.3
解説: settype() は型名を文字列変数で渡せるため、スキーマ配列との組み合わせが非常に相性がよいです。キャスト演算子では switch や match が必要になる場面を簡潔に実装できます。
サンプル3:配列の全要素を一括型変換
配列内の値を一括で同じ型に変換するユースケースです。
<?php
declare(strict_types=1);
/**
* 配列の全要素を指定した型に変換する
*
* @template T
* @param array<mixed> $items
* @param string $type
* @return array<mixed>
*/
function castAll(array &$items, string $type): bool
{
foreach ($items as &$item) {
if (!settype($item, $type)) {
return false;
}
}
unset($item);
return true;
}
// CSVから読み込んだ数値データ(すべて文字列)
$csvRow = ['10', '25', '3', '99', '42', '7'];
$scoreStrs = ['85.5', '92.0', '78.3', '66.7', '95.1'];
$flagStrs = ['1', '0', '1', '1', '0'];
castAll($csvRow, 'int');
castAll($scoreStrs, 'float');
castAll($flagStrs, 'bool');
echo "整数配列: ";
echo implode(', ', array_map(fn($v) => "$v", $csvRow)) . "\n";
// 10, 25, 3, 99, 42, 7
echo "合計: " . array_sum($csvRow) . "\n"; // 186
echo "\nスコア配列: ";
echo implode(', ', $scoreStrs) . "\n";
// 85.5, 92, 78.3, 66.7, 95.1
echo "平均: " . round(array_sum($scoreStrs) / count($scoreStrs), 2) . "\n"; // 83.52
echo "\nフラグ配列: ";
echo implode(', ', array_map(fn($v) => $v ? 'true' : 'false', $flagStrs)) . "\n";
// true, false, true, true, false
実行結果:
整数配列: 10, 25, 3, 99, 42, 7
合計: 186
スコア配列: 85.5, 92, 78.3, 66.7, 95.1
平均: 83.52
フラグ配列: true, false, true, true, false
解説: foreach で参照渡し(&$item)と settype() を組み合わせることで、配列全体を一括変換できます。array_map() でキャストするより変数を直接書き換えるスタイルになります。
サンプル4:設定値の型安全な読み込み
設定ファイルやデータベースから取得した値を確実に正しい型で扱うパターンです。
<?php
declare(strict_types=1);
class TypedConfig
{
private array $store = [];
/** @param array<string, array{value: mixed, type: string}> $definitions */
public function __construct(array $definitions)
{
foreach ($definitions as $key => $def) {
$value = $def['value'];
settype($value, $def['type']);
$this->store[$key] = $value;
}
}
public function get(string $key, mixed $default = null): mixed
{
return $this->store[$key] ?? $default;
}
public function getInt(string $key, int $default = 0): int
{
$v = $this->store[$key] ?? $default;
return is_int($v) ? $v : (int)$v;
}
public function getBool(string $key, bool $default = false): bool
{
$v = $this->store[$key] ?? $default;
return is_bool($v) ? $v : (bool)$v;
}
public function getString(string $key, string $default = ''): string
{
$v = $this->store[$key] ?? $default;
return is_string($v) ? $v : (string)$v;
}
}
// .envやDBから取得した「すべて文字列」の設定値
$rawConfig = [
'db_port' => ['value' => '3306', 'type' => 'int'],
'debug_mode' => ['value' => '1', 'type' => 'bool'],
'max_retries' => ['value' => '3', 'type' => 'int'],
'timeout' => ['value' => '30.5', 'type' => 'float'],
'app_name' => ['value' => 'MyApp', 'type' => 'string'],
'cache_enable' => ['value' => '0', 'type' => 'bool'],
];
$config = new TypedConfig($rawConfig);
echo "db_port : " . $config->getInt('db_port') . " (" . gettype($config->get('db_port')) . ")\n";
echo "debug_mode : " . ($config->getBool('debug_mode') ? 'true' : 'false') . "\n";
echo "timeout : " . $config->get('timeout') . " (" . gettype($config->get('timeout')) . ")\n";
echo "cache_enable : " . ($config->getBool('cache_enable') ? 'true' : 'false') . "\n";
echo "app_name : " . $config->getString('app_name') . "\n";
実行結果:
db_port : 3306 (integer)
debug_mode : true
timeout : 30.5 (double)
cache_enable : false
app_name : MyApp
解説: 型定義をデータ構造として保持し、settype() でコンストラクタ内に一括変換するパターンです。設定値の型保証を宣言的に記述できます。
サンプル5:オブジェクト・配列変換の動作
array・object への変換という少し特殊なケースです。
<?php
declare(strict_types=1);
// --- array への変換 ---
// スカラー → 配列
$val = 42;
settype($val, 'array');
var_dump($val); // array(1) { [0]=> int(42) }
// null → 空配列
$val = null;
settype($val, 'array');
var_dump($val); // array(0) {}
// オブジェクト → 配列(プロパティがキーになる)
$obj = new stdClass();
$obj->name = 'Alice';
$obj->score = 95;
settype($obj, 'array');
print_r($obj);
// Array ( [name] => Alice [score] => 95 )
// --- object への変換 ---
// 連想配列 → stdClass
$assoc = ['id' => 1, 'name' => 'Bob', 'active' => true];
settype($assoc, 'object');
var_dump($assoc instanceof stdClass); // bool(true)
echo $assoc->name . "\n"; // Bob
// スカラー → scalar プロパティを持つ stdClass
$num = 100;
settype($num, 'object');
var_dump($num);
// object(stdClass)#1 (1) { ["scalar"]=> int(100) }
// --- null への変換 ---
$data = ['lots', 'of', 'data'];
settype($data, 'null');
var_dump($data); // NULL
実行結果:
array(1) {
[0]=>
int(42)
}
array(0) {
}
Array
(
[name] => Alice
[score] => 95
)
bool(true)
Bob
object(stdClass)#1 (1) {
["scalar"]=>
int(100)
}
NULL
解説: objectへの変換ではstdClassが生成されます。連想配列のキーがそのままプロパティ名になります。nullへの変換は変数をリセットする用途に使えます。
サンプル6:settype()の戻り値を使ったバリデーション付き変換
変換の成否を確認しながら処理するパターンです。
<?php
declare(strict_types=1);
/**
* 型変換の結果を表すValue Object
*/
class CastResult
{
private function __construct(
public readonly bool $success,
public readonly mixed $value,
public readonly string $errorMessage = '',
) {}
public static function ok(mixed $value): self
{
return new self(true, $value);
}
public static function fail(string $message): self
{
return new self(false, null, $message);
}
}
/**
* 安全な型変換(変換後の値が意図通りか検証付き)
*/
function safeCast(mixed $value, string $type): CastResult
{
$validTypes = ['bool','boolean','int','integer','float','double','string','array','object','null'];
if (!in_array($type, $validTypes, true)) {
return CastResult::fail("不明な型: {$type}");
}
$var = $value;
if (!settype($var, $type)) {
return CastResult::fail("変換失敗: " . var_export($value, true) . " → {$type}");
}
// 追加検証:数値変換で情報が失われすぎていないか
if (in_array($type, ['int', 'integer'], true)
&& is_string($value)
&& !is_numeric($value)
&& $value !== ''
) {
return CastResult::fail(
"非数値文字列を int に変換: '{$value}' → {$var}(情報損失の可能性)"
);
}
return CastResult::ok($var);
}
// --- テスト ---
$tests = [
['42', 'int'],
['3.14', 'float'],
['hello', 'int'], // 非数値 → 警告
['1', 'bool'],
['invalid', 'xyz'], // 不正な型
[null, 'string'],
[[1,2,3], 'object'],
];
foreach ($tests as [$value, $type]) {
$result = safeCast($value, $type);
$label = $result->success ? '✅' : '❌';
$detail = $result->success
? var_export($result->value, true) . ' (' . gettype($result->value) . ')'
: $result->errorMessage;
printf(
"%s %-12s → %-8s %s\n",
$label,
var_export($value, true),
$type,
$detail
);
}
実行結果:
✅ '42' → int 42 (integer)
✅ '3.14' → float 3.14 (double)
❌ 'hello' → int 非数値文字列を int に変換: 'hello' → 0(情報損失の可能性)
✅ '1' → bool true (boolean)
❌ 'invalid' → xyz 不明な型: xyz
✅ NULL → string '' (string)
✅ array (...) → object object(stdClass)#1 ... (object)
解説: settype() 自体は不正な型名以外ではほぼ true を返すため、変換後の値が意図通りかを独自に検証するラッパーが実用上有効です。データ品質が重要な場面ではこのパターンが役立ちます。
よくある落とし穴
① 戻り値で変換結果を得ようとする
// ❌ settype() はboolを返す(変換後の値ではない)
$result = settype($var, 'int'); // true/false
// ✅ 変換後の値は $var 自体に入っている
settype($var, 'int');
echo $var; // 変換後の値
② false → string の挙動に注意
$val = false;
settype($val, 'string');
var_dump($val); // string(0) "" ← "false"にはならない!
false を文字列に変換すると "" (空文字)になります。"false" という文字列にはなりません。
③ "1" → bool は true
$val = "0";
settype($val, 'bool');
var_dump($val); // bool(false)
$val = "false"; // ← "false"という文字列
settype($val, 'bool');
var_dump($val); // bool(true) ← !"false"は空でない文字列なのでtrue
"false" という文字列は true に変換されます(空文字でも"0"でもないため)。
④ 元の変数が破壊される
$original = "42.5";
settype($original, 'int');
// $original はもう "42.5" ではなく 42 になっている
// 元の値が必要な場合はコピーしてから変換する
$copy = $original;
settype($copy, 'int');
⑤ PHP 8.x での strict_types との関係
declare(strict_types=1) は関数の引数型の厳格化であり、settype() の動作には影響しません。settype() は常に「弱い型変換」を行います。
まとめ
| ポイント | 内容 |
|---|---|
| 主な用途 | 動的な型変換・スキーマ駆動の一括変換・配列要素の型統一 |
| キャストとの違い | 変数を破壊的に変換する(元の変数が書き換わる) |
| 最大の強み | 型名を文字列変数で渡せる(動的型指定) |
| 戻り値 | 変換後の値ではなく成功/失敗のbool |
| 注意点 | false→""、"false"→trueなど直感に反する変換がある |
| PHP 8.x推奨 | 通常はキャスト演算子やintval()等が推奨。settype()は動的な型名が必要な場面に |
settype() はキャスト演算子と違い「型名を動的に渡せる」という唯一の強みがあります。スキーマ配列との組み合わせや大量データの一括型変換など、型名をデータとして扱いたい場面では今も有効な選択肢です。
PHP 8.x / 執筆時点の最新安定版にて動作確認済み
