对象数组的array_diff

3

我遇到了与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类的对象转换为字符串”。

你能否提供两个数组的样本响应? - Kishen Nagaraju
请阅读此处 http://php.net/manual/zh/function.array-diff.php#refsect1-function.array-diff-notes - Nghi Ho
1个回答

2

不应该使用array_diff来比较带有对象的数组。

正确的做法是使用array_udiff(),并且需要定义对象之间的“差异”是什么。

例如,如果它们具有不同的id,则对象可能是不同的。

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

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

如果您为每个想要通过id进行比较的类添加了ComparableInterface,其中只有一个方法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比较汽车。

顺便说一下:

在循环中执行查询对于Doctrine的性能来说是一个坏主意。最好的方法是将busyWeek的id作为数组传递给findBy方法进行一次查询。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接