如何使用tablegateway连接表

时间:2017-06-13 16:03:05

标签: zend-db zend-framework3

使用tableadapter时如何在zend3中连接表?问题不在于如何一般地连接表,而是关于如何在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单位(关键项目ID)。第二个问题是如何正确使用别名,因为我在两个表中都有一些具有不同数据的字段名,例如每个表都有一个列快捷方式。

编辑:新信息  为了查看数据的来源,我重命名了我的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;
}

现在我得到一个有趣的输出(我也添加了我的dataarray的内容)

output in browser

我有两个名称相同的列,它们是快捷方式和ci-number,这些数据字段与tableadapter表中的相同数据字段混合在一起。

U1不是伽利略的捷径,它是单位的捷径。伽利略的捷径应该是GAL。似乎第二个表(单位)填充了名称相同的列,但我不会从表格单元中获取任何字段。

编辑:显示我从求职者的消费中得到的补充:

我编辑了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; ?>

我得到了一个有趣的输出,所以仍然缺少某些东西。我希望两个联合表中都有al列。

enter image description here

EDIT2:显示下一个版本

这是我的方法fetchAll()/ class 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; ?>

}

这里有一个新截图: screenshot shows the unit, but no column out of project

EDIT3:添加单位资料

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;
    }

因为我还有抽样数据,我的两个表单元和项目的截图

databasestuff

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 个答案:

答案 0 :(得分:1)

如果您知道如何处理模型中的两个表,这非常简单。假设您拥有ProjectTableUnitTable个模型以及两个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);          
}

答案 1 :(得分:0)

我认为你错过了这一点。您无法访问操纵表网关的表。您应该做的是使用表格网关,这样您就不必再处理表格和SQL了。因此模式的名称为Table Gateway

了解ZF manual describes this的方式。

完成此操作后,可以轻松地将两个表连接到表网关的单个方法之后。此方法返回一个完全从数据库概念中删除的模型。