我有一个接收$ mixed值的函数。 我需要检查是否可以打印,然后打印其他明智的打印类型。
示例值
我的功能
""
在上述条件下,当我尝试打印$ Object时,会导致捕获错误。 是否有方法或内置函数来检查是否可以打印值?或者我是否要手动编写一个?
答案 0 :(得分:2)
您可以使用 gettype 获取变量类型,如:
<?php
$data = array(1, 1., NULL, new stdClass, 'foo');
foreach ($data as $value) {
echo gettype($value), "\n";
}
?>
以上示例将输出类似于:
的内容integer
double
NULL
object
string
答案 1 :(得分:0)
有些类可以由echo
打印,有时候类会将__toString()
方法实现为方便的转换。
以下代码尝试捕获此信息,但可能还有其他情况会发生转换......
class test1 {
public function __toString() {
return "Class test1";
}
}
class test2 {
}
function dmp ( $value ) {
if ( is_object($value) ) {
if ( method_exists($value, '__toString') ) {
echo $value;
}
else {
echo "class=".get_class($value);
}
}
else {
try {
echo $value;
}
catch ( Error $e ) {
echo gettype($value);
}
}
}
$values = [ "string", 0, new test1(), new test2(), [1,2,3]];
foreach ( $values as $value ) {
dmp($value);
}
答案 2 :(得分:0)
使用我编写的此功能:
isPrintable($input, &$text = null) : bool
下面的代码包含一些使用和检查错误处理程序的示例,
<?php
/**
* Check if $input can be echoed
* without any problem.
*/
function isPrintable($input, &$text = null) : bool
{
set_error_handler(function(){throw new \Exception();});
ob_start();
try {
echo $input;
$result = true;
} catch (\Exception $e) {
$result = false;
}
if ($result) {
$text = ob_get_contents();
} else {
$text = null;
}
ob_end_clean();
restore_error_handler();
return $result;
}
//-------- data for test -------
class PrintMe
{
public function __toString()
{
return "I have a magic power";
}
}
$res = fopen("php://memory", 'w');
fclose($res);
$data = [
'array' => ['array'],
'stdClass' => (new \stdClass),
'PrintMe' => (new PrintMe),
'integer' => 1,
'float' => 1.5,
'null' => NULL,
'bool = true' => true,
'bool = false' => false,
'string' => 'foo',
'resource' => tmpfile(),
'resource (unknown type)' => $res
];
//-------- data for test end ---
//set own err handler just for testing
set_error_handler(function(){echo "I am an error handler that should be present\n";});
//trigger an error and test if the defined error handler is present
trigger_error('', \E_USER_ERROR);
//------- check if printable -------
$resultArr = [];
foreach ($data as $name => $unknownTypeVariable) {
$check = isPrintable($unknownTypeVariable) ? 'yes' : 'no';
$resultArr[$name] = $check;
}
echo "\nisPrintable:\n";
print_r($resultArr);
echo "\n";
//------- check if printable end ---
//------- check if printable 2nd form -------
$resultArr = [];
foreach ($data as $name => $unknownTypeVariable) {
if (isPrintable($unknownTypeVariable, $text)) {
$resultArr[$name] = 'Printable: "' . $text . '"';
} else {
$resultArr[$name] = 'Not Printable';
}
}
echo "\nisPrintable 2nd form:\n";
print_r($resultArr);
echo "\n";
//------- check if printable 2nd form end ---
//------- check if printable 2nd form v2 -------
$resultArr = [];
foreach ($data as $name => $unknownTypeVariable) {
$msg = 'Not Printable';
!isPrintable($unknownTypeVariable, $text) ?: $msg = 'Printable: "' . $text . '"';
$resultArr[$name] = $msg;
}
echo "\nisPrintable 2nd form v2:\n";
print_r($resultArr);
echo "\n";
//------- check if printable 2nd form v2 end ---
//------- check if printable 3nd form -------
$resultArr = [];
foreach ($data as $name => $unknownTypeVariable) {
isPrintable($unknownTypeVariable, $text);
$msg = isset($text) ? 'Printable: "' . $text . '"' : 'Not Printable';
$resultArr[$name] = $msg;
}
echo "\nisPrintable 3nd form v2:\n";
print_r($resultArr);
echo "\n";
//------- check if printable 3nd form end ---
//trigger an error and test if the error handler that was before is still present
trigger_error('', \E_USER_ERROR);
//restore error handler that was before testing
restore_error_handler();
//trigger a fatal error - check if restored error handler works
trigger_error('Restored error handler works', \E_USER_ERROR);
给出输出:
I am an error handler that should be present
isPrintable:
Array
(
[array] => no
[stdClass] => no
[PrintMe] => yes
[integer] => yes
[float] => yes
[null] => yes
[bool = true] => yes
[bool = false] => yes
[string] => yes
[resource] => yes
[resource (unknown type)] => yes
)
isPrintable 2nd form:
Array
(
[array] => Not Printable
[stdClass] => Not Printable
[PrintMe] => Printable: "I have a magic power"
[integer] => Printable: "1"
[float] => Printable: "1.5"
[null] => Printable: ""
[bool = true] => Printable: "1"
[bool = false] => Printable: ""
[string] => Printable: "foo"
[resource] => Printable: "Resource id #6"
[resource (unknown type)] => Printable: "Resource id #5"
)
isPrintable 2nd form v2:
Array
(
[array] => Not Printable
[stdClass] => Not Printable
[PrintMe] => Printable: "I have a magic power"
[integer] => Printable: "1"
[float] => Printable: "1.5"
[null] => Printable: ""
[bool = true] => Printable: "1"
[bool = false] => Printable: ""
[string] => Printable: "foo"
[resource] => Printable: "Resource id #6"
[resource (unknown type)] => Printable: "Resource id #5"
)
isPrintable 3nd form:
Array
(
[array] => Not Printable
[stdClass] => Not Printable
[PrintMe] => Printable: "I have a magic power"
[integer] => Printable: "1"
[float] => Printable: "1.5"
[null] => Printable: ""
[bool = true] => Printable: "1"
[bool = false] => Printable: ""
[string] => Printable: "foo"
[resource] => Printable: "Resource id #6"
[resource (unknown type)] => Printable: "Resource id #5"
)
I am an error handler that should be present
Fatal error: Restored error handler works in <path-to-your-php-script> on line 130
您所需要的只是函数isPrintable
,但最好像以后那样保存检查错误处理程序的示例以供以后使用,以后您可以再次检查isPrintable
是否按预期工作带有更新的PHP版本。可能最好的方法是编写一个涵盖该内容的PHPUnit测试。
这一点非常重要,因为在使用错误处理程序时不能百分百成功,可能会给您带来很长一段时间可以跟踪的错误。
输出是用PHP 7.3.8生成的
isPrintable
也应该可以在PHP 5上使用,但我尚未对其进行测试。
如果您不想将函数用于error_handlers并引发异常,则可以使用method_exists来检查对象是否实现了__toString方法。
echo method_exists(new PrintMe, '__toString') ? "yes" : "no";
打印“是”;
echo method_exists(new \stdClass, '__toString') ? "yes" : "no";
打印“否”
并使用is_array检查变量是否为数组。
或者也许最好使用gettype来获取变量的类型,并使用要打印的类型白名单检查它,如果要打印实现__toString的对象,则使用__toString的method_exists。
isPrintable2
的结果与isPrintable
相同,但不使用错误处理程序或异常,因此应该更快。但是,由于它在编写时就知道了变量类型列表,因此它可以工作,因此将来可能会抛出InvalidArgumentException。但是,如果这样做,则只需要用该新类型更新$knownListArr
即可,如果要打印它,只需更新$printableListArr
。
/**
* Check if $input can be echoed
* without any problem.
*/
function isPrintable2($input, &$text = null) : bool
{
$result = true;
$type = gettype($input);
$knownListArr = [
'array',
'NULL',
'object',
'integer',
'double',
'boolean',
'string',
'resource',
'resource (closed)'
];
$printableListArr = [
'NULL',
'object',
'integer',
'double',
'boolean',
'string',
'resource',
'resource (closed)'
];
if (!in_array($type, $knownListArr)) {
$msg = 'Unknown variable type: ' . $type;
$text = null;
throw new \InvalidArgumentException($msg);
}
if (!in_array($type, $printableListArr)) {
$result = false;
}
if ($result &&
$type === 'object' &&
!method_exists($input, '__toString'))
{
$result = false;
}
if ($result) {
$text = (string) $input;
} else {
$text = null;
}
return $result;
}
需要注意的是,echo [];
实际上将使用PHP的警告“ Array
”字符串打印关于数组到字符串的转换。另外,如果您echo null;
,您将得到一个空字符串""
,如果您进行echo false;
由于false
和null
完全不同,因此最好以不同的方式处理此类情况以提高可读性,并以字符串false
和NULL
的形式显示。两者都有误导性的空字符串。
echo true;
也打印字符串1
,与echo 1;
相同,但是如上所述,echo false;
打印一个空字符串,而不是0
。
正如您看到的那样,检测变量是否可打印是一回事,但是例如以明显的方式打印以进行调试是另一回事。