在RFC中给出了这个例子:
// only values are compared $a = (object) ["a" => "b"]; $b = (object) ["b" => "b"]; echo $a <=> $b; // 0
但是当我执行它时,我输出1作为输出:
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b; //1
我现在不明白&lt; =&gt;比较对象?在RFC中,它表示仅通过值进行比较。
P.S。我在流浪汉下使用PHP 7.0.4-6 + deb.sury.org~trusty + 1(cli)(NTS)
UPD:
php > echo (object)["b"=>"b"] <=> (object)["b"=>"b"];
0
php > echo (object)["b"=>"b"] <=> (object)["a"=>"b"];
1
php > echo (object)["a"=>"b"] <=> (object)["b"=>"b"];
1
答案 0 :(得分:4)
在阅读RFC时,我们发现它与自身相矛盾:
添加新运算符(expr)&lt; =&gt; (expr),如果两个操作数相等则返回0,如果左边更大则返回1,如果右边更大则返回-1。 使用与现有比较运算符完全相同的比较规则:&lt;,&lt; =,==,&gt; =和&gt;。 (有关详细信息,请参阅手册)
注意:请参阅==
,这意味着太空船运营商进行了松散的比较。
稍后在示例中:
// only values are compared $a = (object) ["a" => "b"]; $b = (object) ["b" => "b"]; echo $a $b; // 0
太空船运营商只是运营商<
,==
和>
的组合。它根据评估结果给出各自的返回值:
operator(s): < = >
return value: -1 0 1
现在arrays和objects有点复杂types。要了解<=>
PHP太空船运营商的作用,我们需要查看并了解<
,==
和>
如何适用于数组和对象。
让我们看看每种类型的比较运算符<
,>
,==
。首先,我们将查看<
和>
,然后我们会查看==
。
现在,数组<
和>
已记录在案here:
┌───────────┬───────────┬──────────────────────────────────────────────────┐ │ type of │ type of │ │ │ Operand 1 │ Operand 2 │ Result │ ├───────────┼───────────┼──────────────────────────────────────────────────┤ │ array │ array │ Array with fewer members is smaller, │ │ │ │ if key from operand 1 is not found in operand 2 │ │ │ │ then arrays are uncomparable, │ │ │ │ otherwise - compare value by value │ └───────────┴───────────┴──────────────────────────────────────────────────┘
这也可以由code编写和表示:
示例#2标准数组比较的转录
<?php // Arrays are compared like this with standard comparison operators function standard_array_compare($op1, $op2) { if (count($op1) < count($op2)) { return -1; // $op1 < $op2 } elseif (count($op1) > count($op2)) { return 1; // $op1 > $op2 } foreach ($op1 as $key => $val) { if (!array_key_exists($key, $op2)) { return null; // uncomparable } elseif ($val < $op2[$key]) { return -1; } elseif ($val > $op2[$key]) { return 1; } } return 0; // $op1 == $op2 } ?>
我们可以通过一些测试轻松测试。使用methods like in math并且始终只更改一件事,因此我们可以确保在这里正确无误:
/**
/*
/* Testing operators: < and >
/*
*/
//Test case
//Variations: amount, values and keys (order)
//Test count: 9
// Failed: 0
// Passed: 9
{
//Test case 1.1
$a = [1];
$b = [1];
//Passed
var_dump("Same amount of elements, keys and values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.2
$a = [1];
$b = [1, 1];
//Passed
var_dump("NOT same amount of elements, but same values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.3
$a = [10];
$b = [1, 1];
//Passed
var_dump("NOT same amount of elements nor values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.4
$a = [1 => 1];
$b = [10 => 1];
//Passed
var_dump("Same amount of element and values, NOT same keys: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.5
$a = [10];
$b = [1];
//Passed
var_dump("Same amount of elements and keys, NOT same values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.6
$a = [1 => 1, 2 => 1];
$b = [2 => 1, 1 => 1];
//Passed
var_dump("Same amount of elements and keys in different order: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.7
$a = [1 => 1, 2 => 5];
$b = [2 => 5];
//Passed
var_dump("Same values, NOT same amount of elements nor keys: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.8
$a = [10 => 1];
$b = [1 => 10];
//Passed
var_dump("NOT same keys nor values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.9
$a = [1 => 1, 2 => 1];
$b = [2 => 10, 1 => 1];
//Passed
var_dump("Same amount of elements and values, NOT same keys nor order: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
}
echo PHP_EOL . PHP_EOL . PHP_EOL; //Test case separator
/**
/*
/* Test case end
/*
*/
//NULL, TRUE, FALSE 2 str func
function bool2str($v){if($v === NULL)return "NULL";elseif($v === FALSE)return "FALSE";elseif($v === TRUE)return "TRUE";else return "UNEXPECTED: '$v'";}
对于相等/同一性运算符==
和===
,我们找到了数组here的文档:
┌───────────┬──────────┬──────────────────────────────────────────────────┐ │ Example │ Name │ Result │ ├───────────┼──────────┼──────────────────────────────────────────────────┤ │ $a == $b │ Equality │ TRUE if $a and $b have the same key/value pairs. │ │ $a === $b │ Identity │ TRUE if $a and $b have the same key/value pairs │ │ │ │ in the same order and of the same types. │ └───────────┴──────────┴──────────────────────────────────────────────────┘
和以前一样,我们可以使用一些测试代码来测试它:
/**
/*
/* Testing operators: == and ===
/*
*/
//Test case
//Variations: amount, values and keys (order)
//Test count: 5
// Failed: 0
// Passed: 5
{
//Test case 2.1
$a = [1];
$b = [1];
//Passed
var_dump("Same amount of elements, values and keys: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.2
$a = [1];
$b = [10, 1];
//Passed
var_dump("NOT same amount of elements, but same values: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.3
$a = [10];
$b = [1];
//Passed
var_dump("Same amount of elements, but not values: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.4
$a = [1 => 1];
$b = [10 => 1];
//Passed
var_dump("Same amount of elements and values, but not keys: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.5
$a = [1 => 1, 2 => 2];
$b = [2 => 2, 1 => 1];
//Passed
var_dump("Same amount of elements, key and values, but different order: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
}
echo PHP_EOL . PHP_EOL . PHP_EOL; //Test case separator
/**
/*
/* Test case end
/*
*/
//NULL, TRUE, FALSE 2 str func
function bool2str($v){if($v === NULL)return "NULL";elseif($v === FALSE)return "FALSE";elseif($v === TRUE)return "TRUE";else return "UNEXPECTED: '$v'";}
因此,我们可以看到并确认数组的比较运算符按预期和记录的方式工作!
<子> Full Testing File 子>
<
的文档
记录了here的>
和/**
/*
/* Testing operators: < and >
/*
*/
//Test case
//Variations: amount, values and keys (order)
//Test count: 10
// Failed: 0
// Passed: 10
{
//Test case 1.1
$a = (object)["a" => 1];
$b = (object)["a" => 1];
//Passed
var_dump("Same amount of elements, keys and values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.2
$a = (object)["a" => 1];
$b = (object)["a" => 1, "b" => 1];
//Passed
var_dump("NOT same amount of elements, but same values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.3
$a = (object)["a" => 10];
$b = (object)["a" => 1, "b" => 1];
//Passed
var_dump("NOT same amount of elements nor values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.4
$a = (object)["a" => 1];
$b = (object)["b" => 1];
//Passed
var_dump("Same amount of element and values, NOT same keys: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.5
$a = (object)["a" => 10];
$b = (object)["a" => 1];
//Passed
var_dump("Same amount of elements and keys, NOT same values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.6
$a = (object)["a" => 1, "b" => 1];
$b = (object)["b" => 1, "a" => 1];
//Passed
var_dump("Same amount of elements and keys in different order: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.7
$a = (object)["a" => 1, "b" => 5];
$b = (object)["b" => 5];
//Passed
var_dump("Same values, NOT same amount of elements nor keys: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.8
$a = (object)["c" => 1];
$b = (object)["a" => 10];
//Passed
var_dump("NOT same keys nor values: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.9
$a = (object)["a" => 1, "b" => 1];
$b = (object)["b" => 10, "a" => 1];
//Passed
var_dump("Same amount of elements and values, NOT same keys nor order: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
//Test case 1.10
class A {public $a = 1;}
$a = new A;
class B {public $a = 1;}
$b = new B;
//Passed
var_dump("Same amount of elements and values and keys, but different not built-in class: " . "'<' -> " . bool2str($a < $b) . " '>' -> " . bool2str($a > $b));
}
echo PHP_EOL . PHP_EOL . PHP_EOL; //Test case separator
/**
/*
/* Test case end
/*
*/
//NULL, TRUE, FALSE 2 str func
function bool2str($v){if($v === NULL)return "NULL";elseif($v === FALSE)return "FALSE";elseif($v === TRUE)return "TRUE";else return "UNEXPECTED: '$v'";}
:
┌───────────┬───────────┬──────────────────────────────────────────────────┐ │ type of │ type of │ │ │ Operand 1 │ Operand 2 │ Result │ ├───────────┼───────────┼──────────────────────────────────────────────────┤ │ object │ object │ Built-in classes can define its own comparison, │ │ │ │ different classes are uncomparable, │ │ │ │ same class compare properties same as arrays │ └───────────┴───────────┴──────────────────────────────────────────────────┘
和以前一样,我们也可以测试一下:
==
包含对象的===
和/**
/*
/* Testing operators: == and ===
/*
*/
//Test case
//Variations: amount, values and keys (order)
//Test count: 7
// Failed: 0
// Passed: 7
{
//Test case 2.1
$a = (object)["a" => 1];
$b = (object)["a" => 1];
//Passed
var_dump("Same amount of elements, values and keys: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.2
$a = (object)["a" => 1];
$b = (object)["a" => 10, "b" => 1];
//Passed
var_dump("NOT same amount of elements, but same values: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.3
$a = (object)["a" => 10];
$b = (object)["a" => 1];
//Passed
var_dump("Same amount of elements, but not values: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.4
$a = (object)["a" => 1];
$b = (object)["b" => 1];
//Passed
var_dump("Same amount of elements and values, but not keys: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.5
$a = (object)["a" => 1, "b" => 2];
$b = (object)["b" => 2, "a" => 1];
//Passed
var_dump("Same amount of elements, key and values, but different order: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.6
class C {public $a = 1;}
$a = new A;
class D {public $a = 1;}
$b = new B;
//Passed
var_dump("Same amount of elements and values and keys, but different not built-in class: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
//Test case 2.7
$a = (object)["a" => 1];
$b = $a;
//Passed
var_dump("Same exact instance: " . "'==' -> " . bool2str($a == $b) . " '===' -> " . bool2str($a === $b));
}
echo PHP_EOL . PHP_EOL . PHP_EOL; //Test case separator
/**
/*
/* Test case end
/*
*/
//NULL, TRUE, FALSE 2 str func
function bool2str($v){if($v === NULL)return "NULL";elseif($v === FALSE)return "FALSE";elseif($v === TRUE)return "TRUE";else return "UNEXPECTED: '$v'";}
文档有自己的页面here:
使用比较运算符(==)时,会以简单的方式比较对象变量,即:如果两个对象实例具有相同的属性和值,则它们是相同的,并且是同一类的实例。
当使用标识运算符(===)时,当且仅当它们引用同一类的同一实例时,对象变量才相同。
再次对此进行测试:
<
所以我们看到,具有对象的比较运算符的行为与预期和记录完全一致!即使进行了宽松的比较,也要考虑属性和值。
<子> Full Testing File 子>
由于已报告此错误here,错误报告可能基于RFC中的评论,其中说明:
//仅比较值
但除此之外,这是RFC中唯一带有注释的示例,RFC明确指出它使用与==
,>
和if (!array_key_exists($key, $op2)) {
return null; // uncomparable
}
相同的比较规则。
这意味着提供的代码示例将无法比较,因为它没有相同的属性/键。
至于相等,它将需要相同的属性/键和值,因此它不能相等,并且比上面的代码示例中所示的无法比较的更少或更多:
$a = (object)["b" => "b"];
$b = (object)["a" => "b"];
var_dump($a > $b); //FALSE
var_dump($a < $b); //FALSE
var_dump($a == $b); //FALSE
如果我们单独尝试每个比较运算符,我们也会看到这一点:
StdClass
所有返回false,因为它是无法比较的。
只是因为class A {
public $a = "";
public $b = "";
}
$a = new A;
$a->a = "b";
unset($a->b);
$b = new A;
$b->b = "b";
unset($b->a);
var_dump($a);
var_dump($b);
var_dump($a <=> $b); //1
会有自己的比较,我们可以用我们自己的类测试它:
0
同样的输出:1。
所以我想说因为它无法比较,所以不应该返回1
,-1
或FALSE
。它应该返回NULL
或{{1}}或类似的东西。
现在我想说这种行为没有正确记录。
答案 1 :(得分:0)
echo $object1 <=> $object2; // 0
仅当
时才会返回0
$object1
和$object2
是同一类的实例在您的示例中,如果它返回0
而不是1
,我会感到惊讶。
也许是RFC中的拼写错误?