0
0

More than 1 year has passed since last update.

PHP 2つの配列やオブジェクトの中身が同じかどうか調べる

Last updated at Posted at 2022-05-07

説明

PHPUnitテストでオブジェクトが返ってくる時プロパティを一個一個比較してますか?私はserializeして文字列比較してます。「PHPで配列が同じかどうか比較する方法」なるものであまり良いものがない気がしたので私の書く比較方法を書きたいと思います。これは誤った方法かもしれません。でも構いません。誤った方法を世に広め世界を混沌に陥れるのは私の人生の目的であるのだから。

まぢで完全に同じかどうか分身かどうか

trueになるのは

  1. リソースが同じ(リソース番号が同じ)
  2. オブジェクトが同じインスタンス(参照が同じ)
  3. 配列の中身が同じ(オブジェクトが入っている時は同じインスタンスが入っている事)
$x === $y

中身の値が同じかどうか

trueになるのは

  1. オブジェクトのクラス名とプロパティとその値が同じ
  2. 配列の中身が同じ(オブジェクトが入っている時はオブジェクトのクラス名とプロパティとその値が同じ)

※リソースはserializeすると「i:0;」となる。数値の0と同じ。意味がないため使わない

serialize($x) === serialize($y)

テスト

/**
 * @param mixed $x
 * @param mixed $y
 * @return bool
 */
function assertSameValue($x, $y) {

    if (is_resource($x) && is_resource($y)) {
        // return get_resource_id($x) === get_resource_id($y);
        return $x === $y;
    }

    if (is_resource($x) || is_resource($y)) {
        return false;
    }

    return serialize($x) === serialize($y);
}

class assertSameValueTestClass {
    public $str = 'str';
}

class unchiTest extends TestCase {

    function testAssertSameValue() {

        $x = 0;
        $y = 0;
        $this->assertTrue(assertSameValue($x, $y));

        $x = 0;
        $y = '0';
        $this->assertFalse(assertSameValue($x, $y));

        $x = ['a', 'b'];
        $y = ['a', 'b'];
        $this->assertTrue(assertSameValue($x, $y));
        $this->assertTrue($x === $y);

        $x = ['a',];
        $y = ['a', 'b'];
        $this->assertFalse(assertSameValue($x, $y));
        $this->assertFalse($x === $y);

        $a = new \stdClass();
        $b = new \stdClass();
        $x = [$a];
        $y = [$b];
        $this->assertTrue(assertSameValue($x, $y));
        $this->assertFalse($x === $y);

        // インスタンスが同じ
        $x = new \stdClass();
        $y = $x;
        $y->a = 'a';
        $this->assertTrue(assertSameValue($x, $y));
        $this->assertTrue($x === $y);

        // インスタンスは違う、中身は同じ
        $x = new \stdClass();
        $y = new \stdClass();
        $this->assertFalse($x === $y);
        $this->assertTrue(assertSameValue($x, $y));

        // インスタンスは違う、中身が違う
        $x = new \stdClass();
        $x->a = 'a';
        $y = new \stdClass();
        $y->b = 'b';
        $this->assertFalse($x === $y);
        $this->assertFalse(assertSameValue($x, $y));

        $x = new \stdClass();
        $y = new assertSameValueTestClass();
        $this->assertFalse(assertSameValue($x, $y));

        $x = new \stdClass();
        $x->str = 'str';
        $y = new assertSameValueTestClass();
        $this->assertTrue(assertSameValue($x->str, $y->str));
        $this->assertFalse(assertSameValue($x, $y));

        $x = new \stdClass();
        $x->a = 'a';
        $y = new \stdClass();
        $this->assertFalse(assertSameValue($x, $y));

        $x = new \stdClass();
        $x->a = ['a', 'b', 'c' => ['key' => 'val']];
        $x->i = 1;

        $y = new \stdClass();
        $y->a = ['a', 'b', 'c' => ['key' => 'val']];
        $y->i = 1;
        $this->assertTrue(assertSameValue($x, $y));

        $x = fopen('php://stdin', 'r');
        $y = fopen('php://stdin', 'r');
        $this->assertFalse(assertSameValue($x, $y));
        fclose($x);
        fclose($y);

        $x = fopen('php://stdin', 'r');
        $y = $x;
        $this->assertTrue(assertSameValue($x, $y));
        fclose($x);

        $x = fopen('php://stdin', 'r');
        $y = 0;
        $this->assertFalse(assertSameValue($x, $y));
        fclose($x);
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0