Как объединить таблицы с помощью tablegateway
Как объединить таблицы в Zend3 при использовании Tableadapter? Вопрос не в том, как вообще объединить таблицы, а в том, как это сделать в Zend и где разместить код.
Допустим, у меня есть * класс таблицы, например:
namespace Import\Model;
use RuntimeException;
use Zend\Db\TableGateway\TableGatewayInterface;
class ProjectTable
{
private $tableGateway='t_project';
public function __construct(TableGatewayInterface $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
return $this->tableGateway->select();
}
Я хотел бы объединить две таблицы, как я могу это сделать, не здесь ли подходящее место для этого? Я пытался реализовать следующую функцию:
public function Project_Unit(Unit $unit = null){
$select = $this->tableGateway->getSql()->select()
->join('t_unit', 't_project.ProjectID = t_unit.ProjectID',array('UnitID','CI_Number', 'Unitname','Shortcut','Suppliername')); //, left
return $this->tableGateway->selectWith($select);
}
Я не получил ошибку, я вместо этого перепутал данные. После этого попробовал с псевдонимами тоже не сработало.
У меня вопрос, как построить этот класс таблиц, если мне нужно объединить две таблицы. Таблицами будет проект 1 -> n единица (ключевой идентификатор проекта). Второй вопрос заключается в том, как правильно использовать псевдонимы, потому что у меня есть несколько имен полей в обеих таблицах с разными данными, например, у каждой таблицы есть ярлык столбца.
РЕДАКТИРОВАТЬ: Новая информация Чтобы увидеть, откуда поступают данные, я переименовал переменные моего Exchangearray:
public function exchangeArray(array $data)
{
$this->PProjectID= !empty($data['ProjectID']) ? $data['ProjectID'] : null;
$this->PCI_Number= !empty($data['CI_Number']) ? $data['CI_Number'] : null;
$this->PDescription= !empty($data['Description']) ? $data['Description'] : null;
$this->Projectname= !empty($data['Projectname']) ? $data['Projectname'] : null;
$this->PShortcut= !empty($data['Shortcut']) ? $data['Shortcut'] : null;
$this->PComponent_Class= !empty($data['Component_Class']) ? $data['Component_Class'] : null;
}
Теперь я получаю интересный вывод (я также добавил содержимое моего массива данных)
У меня есть два столбца, которые называются одинаково, это будет ярлык и ci-номер, эти поля данных смешиваются с одинаковыми из таблицы tableadapter таблицы.
U1 - это не ярлык galileo, а ярлык устройства. Ярлык Галилея должен быть GAL. Кажется, что столбцы с одинаковыми именами заполнены второй таблицей (блоком), но я не получу никаких полей из таблицы.
РЕДАКТИРОВАТЬ: показать дополнение, которое я сделал из предложений от Jobaer:
Я отредактировал свой класс ProjectTable:
class ProjectTable
{
//private $tableGateway='t_project';
private $projectTableGateway;
private $unitTableGateway;
// public function __construct(TableGatewayInterface $tableGateway)
// {
// $this->tableGateway = $tableGateway;
// }
public function __construct(
TableGatewayInterface $projectTableGateway,
TableGatewayInterface $unitTableGateway)
{
$this->projectTableGateway = $projectTableGateway;
$this->unitTableGateway = $unitTableGateway;
}
public function fetchAll()
{
$sqlSelect = $this->unitTableGateway->getSql()->select();
/**
* columns for the "project_table" exactly it is unit_table
*/
$sqlSelect->columns(array('CI_Number', 'ProjectID','Unitname','Shortcut','Suppliername'));
/**
* this can take two more arguments:
* an array of columns for "unit_table"
* and a join type, such as "inner"
*/
$sqlSelect->join('t_project', 't_unit.ProjectID = t_project.ProjectID');
/**
* set condition based on columns
*/
//$sqlSelect->where(array('unit_table.project_id' => $id));
$resultSet = $this->unitTableGateway->selectWith($sqlSelect);
return $resultSet;
//return $this->tableGateway->select();
}
Я также отредактировал мой Module.php, как предложено, здесь идет фрагмент
// Model\ProjectTable::class => function($container) {
// $tableGateway = $container->get(Model\ProjectTableGateway::class);
// return new Model\ProjectTable($tableGateway);
// },
Model\ProjectTable::class => function($container) {
$projectTableGateway = $container->get(Model\ProjectTableGateway::class);
$unitTableGateway = $container->get(Model\UnitTableGateway::class);
return new Model\ProjectTable($projectTableGateway, $unitTableGateway);
},
Model\ProjectTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Project());
return new TableGateway('t_project', $dbAdapter, null, $resultSetPrototype);
}
Мое действие контроллера не изменилось:
return new ViewModel([
'projects' => $this->projectTable->fetchAll(),
]);
На мой взгляд, я попытался захватить столбцы обеих таблиц:
foreach ($projects as $project) :
// $unit=$units->fetchAllP($project->ProjectID);
var_dump(get_object_vars($project));?>
<tr>
<td><?= $this->escapeHtml($project->Unitname) ?></td>
<td><?= $this->escapeHtml($project->Projectname) ?></td>
<td><?= $this->escapeHtml($project->Shortcut) ?></td>
<td><?= $this->escapeHtml($project->CI_Number) ?></td>
<td><?= $this->escapeHtml($project->Description) ?></td>
<td><?= $this->escapeHtml($project->Component_Class) ?></td>
<td>
<a href="<?= $this->url('project', ['action' => 'edit', 'id' => $project->ProjectID]) ?>">Edit</a>
<a href="<?= $this->url('project', ['action' => 'delete', 'id' => $project->ProjectID]) ?>">Delete</a>
</td>
<?php endforeach; ?>
Я получил интересный вывод, так что чего-то все еще не хватает. Я ожидал иметь все столбцы из обеих соединенных таблиц.
EDIT2: показать следующую версию
вот мой метод fetchAll()/ класс ProjectTable
public function fetchAll()
{
$sqlSelect = $this->unitTableGateway->getSql()->select();
$sqlSelect->columns(array('UnitID','CI_Number', 'ProjectID','Unitname','Shortcut','Suppliername'));
$sqlSelect->join('t_project', 't_unit.ProjectID = t_project.ProjectID', array('Project' =>'Projectname','CI' =>'CI_Number','PDescription' =>'Description','PShortcut' =>'Shortcut','PComponent' =>'Component_Class','PProjectID' =>'ProjectID'));
//$sqlSelect->where(array('unit_table.project_id' => $id));
$resultSet = $this->unitTableGateway->selectWith($sqlSelect);
//return $resultSet;
return $resultSet->toArray();
//return $this->tableGateway->select();
Вот мой скрипт:
<?php
//var_dump(get_object_vars($projects));
foreach ($projects as $project) :
//var_dump(get_object_vars($project));
?>
<tr>
<td><?= $project['Project']?></td>
<td><?= $project['CI']?></td>
<td><?= $project['Unitname']?></td>
<?php
endforeach; ?>
}
EDIT3: добавление Unit Stuff
class UnitTable
{
private $tableGateway='t_unit';
public function __construct(TableGatewayInterface $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
return $this->tableGateway->select();
}
Блок класса также:
class Unit implements InputFilterAwareInterface
{
public $UnitID;
public $CI_Number;
public $ProjectID;
public $Unitname;
public $Shortcut;
public $Suppliername;
private $inputFilter;
public function exchangeArray(array $data)
{
$this->UnitID= !empty($data['UnitID']) ? $data['UnitID'] : null;
$this->CI_Number= !empty($data['CI_Number']) ? $data['CI_Number'] : null;
$this->ProjectID= !empty($data['ProjectID']) ? $data['ProjectID'] : null;
$this->Unitname= !empty($data['Unitname']) ? $data['Unitname'] : null;
$this->Shortcut= !empty($data['Shortcut']) ? $data['Shortcut'] : null;
$this->Suppliername= !empty($data['Suppliername']) ? $data['Suppliername'] : null;
}
Потому что у меня пока есть только выборочные данные, снимок экрана моего блока из двух таблиц и проекта
EDIT4: заводская часть module.php
public function getServiceConfig()
{
return [
'factories' => [
Model\ImportTable::class => function($container) {
$tableGateway = $container->get(Model\ImportTableGateway::class);
return new Model\ImportTable($tableGateway);
},
Model\ImportTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Import());
return new TableGateway('t_dcl', $dbAdapter, null, $resultSetPrototype);
},
Model\DclimportTable::class => function($container) {
$tableGateway = $container->get(Model\DclimportTableGateway::class);
return new Model\DclimportTable($tableGateway);
},
Model\DclimportTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Dclimport());
return new TableGateway('t_dcl_import', $dbAdapter, null, $resultSetPrototype);
},
Model\FollowupTable::class => function($container) {
$tableGateway = $container->get(Model\FollowupTableGateway::class);
return new Model\FollowupTable($tableGateway);
},
Model\FollowupTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Followup());
return new TableGateway('t_dcl_wv', $dbAdapter, null, $resultSetPrototype);
},
Model\UnitTable::class => function($container) {
$tableGateway = $container->get(Model\UnitTableGateway::class);
return new Model\UnitTable($tableGateway);
},
Model\UnitTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Unit());
return new TableGateway('t_unit', $dbAdapter, null, $resultSetPrototype);
},
// Model\ProjectTable::class => function($container) {
// $tableGateway = $container->get(Model\ProjectTableGateway::class);
// return new Model\ProjectTable($tableGateway);
// },
Model\ProjectTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Project());
return new TableGateway('t_project', $dbAdapter, null, $resultSetPrototype);
},
Model\ProjectTable::class => function($container) {
$projectTableGateway = $container->get(Model\ProjectTableGateway::class);
$unitTableGateway = $container->get(Model\UnitTableGateway::class);
return new Model\ProjectTable($projectTableGateway, $unitTableGateway);
}
],
];
}
2 ответа
Это очень просто, если вы знаете, как обрабатывать две таблицы в модели. Если у вас есть ProjectTable
а также UnitTable
модели и два TableGateway
Сервисы. Они будут обрабатывать две таблицы соответственно в базе данных. Так что если вы хотите присоединиться к ним в вашем ProjectTable
модель, которая затем будет
ProjectTable.php
class ProjectTable
{
private $projectTableGateway;
private $unitTableGateway;
public function __construct(
TableGatewayInterface $projectTableGateway,
TableGatewayInterface $unitTableGateway)
{
$this->projectTableGateway = $projectTableGateway;
$this->unitTableGateway = $unitTableGateway;
}
public function projectUnit($id)
{
/**
* as you are joing with "project_table"
* this will handle "unit_table"
*/
$sqlSelect = $this->unitTableGateway->getSql()->select();
/**
* columns for the "unit_table".
* if want to use aliases use as
* array('alias_name' => 'column_name')
*/
$sqlSelect->columns(array('column_one', 'column_two'));
/**
* this can take two more arguments:
* an array of columns for "project_table"
* and a join type, such as "inner"
*/
$sqlSelect->join('project_table', 'unit_table.project_id = project_table.id');
/**
* set condition based on columns
*/
$sqlSelect->where(array('unit_table.project_id' => $id));
$resultSet = $this->unitTableGateway->selectWith($sqlSelect);
return $resultSet;
}
}
Теперь создайте два TableGateway
сервисы для обработки двух таблиц и передачи их ProjectTable
конструктор как следующий
Model\ProjectTable::class => function($container) {
$projectTableGateway = $container->get(Model\ProjectTableGateway::class);
$unitTableGateway = $container->get(Model\UnitTableGateway::class);
return new Model\ProjectTable($projectTableGateway, $unitTableGateway);
}
Я думаю, что вы упускаете суть. Вы не получаете доступ к таблицам, которые управляют шлюзами таблиц. Вам следует использовать шлюзы таблиц, чтобы вам больше не приходилось иметь дело с таблицами и SQL. Отсюда и название шаблона Table Gateway.
Посмотрите, как руководство ZF описывает это.
После того, как вы это сделаете, легко объединить две таблицы за одним методом шлюза таблиц. Этот метод возвращает модель, которая полностью исключена из понятия базы данных.