首页 > 解决方案 > 对象数组上的array_diff

问题描述

我遇到了 PHP 函数 array_diff 的问题。

在这两种情况下,我都在相同类对象的数组上使用它。

第一种情况:

public function findFreeUsers($weekId)
{
    $em = $this->getEntityManager();
    $week = $em->getRepository(Week::class)->findOneBy(["id" => $weekId]);
    $busyWeeks = $em->getRepository(Week::class)->findWeekBetweenDates($week);
    $busyUsers = array();
    foreach ($busyWeeks AS $busyWeek) {
        $tmp = $em->getRepository(UserWeek::class)->findBy(["week" => $busyWeek["id"]]);
        if ($tmp != null) {
            foreach($tmp AS $singleWeek) {
                $busyUsers[] = $singleWeek->getUser();
            }
        }
    }
    $allUsers = $em->getRepository(User::class)->findAll();
    $freeUsers = array_diff($allUsers, $busyUsers);
    return $freeUsers;
}

第二种情况:

public function findFreeCars($weekId)
{
    $em = $this->getEntityManager();
    $week = $em->getRepository(Week::class)->findOneBy(["id" => $weekId]);
    $busyWeeks = $em->getRepository(Week::class)->findWeekBetweenDates($week);
    $busyCars = array();
    foreach ($busyWeeks AS $busyWeek) {
        $tmp = $em->getRepository(CarWeek::class)->findBy(["week" => $busyWeek["id"]]);
        if ($tmp != null) {
            foreach($tmp AS $singleWeek) {
                $busyCars[] = $singleWeek->getCar();
            }
        }
    }
    $allCars = $em->getRepository(Car::class)->findAll();
    $freeCars = array_diff($allCars, $busyCars);
    return $freeCars;
}

我正在转储这些数组,它们都是具有同一类对象的数组。

在第一种情况下它有效,在第二种情况下,我得到了:

错误:AppBundle\Entity\Car 类的对象无法转换为字符串

标签: phparrayssymfonyarray-difference

解决方案


您不应该使用 array_diff 将数组与对象进行比较。

要正确执行此操作,您需要使用array_udiff()并且您需要定义对象之间的“差异”意味着什么。

例如,如果对象具有不同的 id,它们可能会有所不同

function compareCars(Car $objA, Car $objB) {
  return $objA->getId() <=> $objB->getId();
}

$diff = array_udiff($allCars, $busyCars, 'compareCars')

如果您将例如 ComparableInterface 添加到您想通过 id 比较的每个类中,只使用一个方法 getId() 那么您可以使用多态性的好处

interface ComparableInterface
{
   public function getId();
}


class Car implements ComparableInterface
{
    public function getId()
    {
       return $this->id;
    }
    //rest of the class source 
}

function compareCars(ComparableInterface $objA, ComparableInterface $objB) {
   return $objA->getId() <=> $objB->getId();
}

甚至定义为每个对象返回的 compare() 方法,如果它相等或不相等

interface AdvancedComparableInterface extends ComparableInterface
{
   public function compare(ComparableInterface $obj);
}

class Car implements AdvancedComparableInterface
{
    public function getId()
    {
       return $this->id;
    }

    public function compare(ComparableInterface $obj)
    {
       return $this->getId() <=> $obj->getId();
    }
    //rest of the class source 
}

function compareCars(AdvancedComparableInterface $objA, ComparableInterface $objB) {
   return $objA->compare($objB);
}

如您所见,您可以使用多种方法来定义对象是否与另一个相同。例如,您可以通过 VIN 比较的汽车

边注:

就学说的性能而言,循环执行查询是一个坏主意。如果您通过将busyWeek 的ID 作为数组传递给findBy 方法来进行查询,那就更好了。


推荐阅读