Модель Zend Framework 2/3 с отношением к себе и другой модели

Сначала я прочитал следующие два вопроса stackoverflow, но они не дали мне ответа:

В моем приложении у меня есть таблица базы данных сотрудников, которая имеет множество свойств, но наиболее интересным для меня в настоящее время является manager_id и bank_id которые являются внешними ключами.

  • manager_id является внешним ключом для другого сотрудника (как вы можете себе представить, у сотрудника может быть один менеджер)
  • bank_id является внешним ключом для другой модели / таблицы базы данных с именем bank — потому что сотрудник может иметь банковский счет 😉

Теперь в моем EmployeeTable.php файл у меня есть те магические методы где я получаю результаты базы данных.

Чтобы получить одного сотрудника, я делаю это:

/**
* @param int $id
*
* @return Employee
*/
public function getEmployeeById($id)
{
$rowset = $this->tableGateway->select(['id' => (int) $id]);
/** @var Employee $row */
$row = $rowset->current();

if (!$row) {
throw new RuntimeException(sprintf(
'Could not find row with identifier %d',
(int) $id
));
}

return $row;
}

Но без каких-либо sql присоединяется У меня есть только manager_id и bank_id в возвращенном объекте сотрудника.

Вопрос: Как лучше всего получать необходимую информацию?

Пока у меня есть две мысли:

Первый

Должен ли я — если $row не пусто — позвоните, например, bankTable объект (через внедрение зависимости), который имеет getBankById метод.
Тогда я продлю Employee.php модель с $bank свойство с геттером / сеттером и до return утверждение в моем getEmployeeId метод я бы сделал что-то вроде этого:

$row->setBank($this->bankTable->getBankById($row->bank_id));

Но я боюсь рекурсивного цикла, делающего это для manager_id потому что я бы назвал тот же метод, в котором я сейчас нахожусь.

второй

Или я должен продлить getEmployeeById метод с левым соединением, чтобы получить данные из банковской таблицы следующим образом:

$select = $this->tableGateway->getSql()->select()
->join(['b' => 'bank'], 'bank_id = m.id',
[
'bank.id' => 'id',
'bank.description' => 'description',
'bank.bic' => 'bic',
],
Select::JOIN_LEFT)
->join(['m' => 'employee'], 'manager_id = m.id',
[
'manager.id' => 'id',
'manager.forename' => 'forename',
'manager.surname' => 'surname',
// and all the other properties
],
Select::JOIN_LEFT);

$result = $this->tableGateway->selectWith($select);

$row= $result->current();
$resultSet = $this->hydrator->hydrate($this->hydrator->extract($row), $row);

К сожалению, я должен дать соединенные столбцы псевдонимы, иначе я бы перезаписал id от сотрудника с идентификатором банка и т. д.

После такого вида SQL-выражения вы можете увидеть, что я извлеку результат, чтобы получить свойства как значения, а затем их гидрировать.

Гидратация будет выглядеть так:

/**
* @param array $data
* @param Employee $object
*
* @return Employee
*/
public function hydrate(array $data, $object)
{
if (!$object instanceof Employee) {
throw new \BadMethodCallException(sprintf(
'%s expects the provided $object to be a PHP Employee object)',
__METHOD__
));
}

$employee = new Employee();
$employee->exchangeArray($data);

$bank = new Bank();
$bank->exchangeArray($data, 'bank.');
$employee->setBank($bank);

$manager = new Employee();
$manager->exchangeArray($data, 'manager.');
$employee->setManager($manager);

return $employee;
}

В результате этого у меня есть чистый employee модель (без этих дополнительных столбцов псевдонимов) и дополнительно 2 новых свойства, которые являются объектами другого сотрудника (менеджера) и банка.

Но это выглядит довольно перегруженным …

Спасибо за чтение до сих пор — Если у вас есть какие-либо советы или рекомендации, они тепло приветствуются!

РЕДАКТИРОВАТЬ

Я отредактировал мой EmployeeTableFactory сделать следующее (об увлажнении):

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new HydratingResultSet();
$resultSetPrototype->setHydrator(new EmployeeHydrator());
$resultSetPrototype->setObjectPrototype(new Employee());

$tableGateway = new TableGateway('employee', $dbAdapter, null, $resultSetPrototype);

return new EmployeeTable($tableGateway);
}

Я изменил свой EmployeeHydrator реализовать HydratorInterface потому что я уже использовал экстракт и теперь он соответствует необходимому интерфейсу для resultSetPrototype->setHydrator() метод.

Теперь все становится довольно легко в getEmployeeById метод, потому что с помощью следующего кода у меня уже есть готовый объект сотрудника и все связанные объекты внешнего ключа (из-за моего EmployeeHydrator)

$result = $this->tableGateway->selectWith($select);
$row = $result->current(); // the given employee object result already hydrated!

return $row;

Мне нравится эта реализация

3

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]