array_diff для массива объектов - PullRequest
0 голосов
/ 06 ноября 2018

У меня проблема с 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 не может быть преобразован в строку

1 Ответ

0 голосов
/ 06 ноября 2018

Вы не должны использовать array_diff для сравнения массивов с объектами.

Чтобы сделать это правильно, вам нужно использовать array_udiff () и вам необходимо определить, что означает «разница» между объектами.

Например, объекты могут отличаться, если у них разные идентификаторы

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

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

Если вы добавили, например, 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

Примечание:

Выполнение запросов в цикле - плохая идея с точки зрения эффективности доктрины. Будет лучше, если вы сделаете один запрос, передав идентификаторы busyWeek в виде массива в метод findBy.

...