2017-06-13 6 views
0

Comment joindre les tables à zend3 lors de l'utilisation TableAdapter? La question n'est pas de savoir comment joindre les tables en général, mais comment faire cela dans zend et où placer le code.comment rejoindre les tables en utilisant tablegateway

Disons que je habe une classe de table * par exemple:

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

Je voudrais joindre deux tables, comment puis-je faire, Ist ici le bon endroit pour le faire? J'ai essayé d'implémenter la fonction suivante:

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

} 

Je n'ai pas eu d'erreur, j'ai plutôt mélangé des données. Après cela, j'ai essayé avec des alias ne fonctionnait pas non plus.

Ma question est, comment construire ce TableClass, si je dois joindre deux tables. Les tables seront projet 1 -> n unit (clé projectID). La deuxième question serait de savoir comment utiliser les alias correctement, parce que j'ai des noms de champs dans les deux tables avec des données différentes, par exemple chaque table a un raccourci de colonne.

EDIT: De nouvelles informations Pour voir où proviennent les données, je renomme les variables de mon 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; 
} 

Maintenant, je reçois une sortie intéressante (j'ai ajouté le contenu de mon tableauDonnees aussi)

output in browser

J'ai deux colonnes qui portent le même nom, qui sera raccourci et ci-nombre, ces zones de données sont mélangés avec les mêmes de la table TableAdapter.

U1 est pas le raccourci de Galileo est le raccourci de l'appareil. Le raccourci de Galileo devrait être GAL. Il semble que les colonnes nommées de la même manière soient remplies par la seconde table (unité) mais je ne recevrai aucun champ de l'unité de table.

EDIT: pour montrer l'addition, je distinguais des sugestions de jobaer:

ma classe I edited 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(); 
} 

J'ai effectué aussi mon module.php comme suggéré, est ici un extrait

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

Mon action du contrôleur n'a pas changé:

return new ViewModel([ 
         'projects' => $this->projectTable->fetchAll(), 
          ]); 

À mon avis j'ai essayé de saisir les colonnes des deux tables:

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

J'ai eu une sortie intéressante, donc quelque chose manque encore. Je m'attendais à avoir toutes les colonnes des deux tables jointes.

enter image description here

EDIT2: montrer prochaine version

ici est ma méthode fetchAll()/classe 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(); 

Voici mon ViewScript:

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

}

et voici une nouvelle capture d'écran: screenshot shows the unit, but no column out of project

EDIT3: l'ajout d'unité Stuff

class UnitTable 
{ 
    private $tableGateway='t_unit'; 

    public function __construct(TableGatewayInterface $tableGateway) 
    { 
     $this->tableGateway = $tableGateway; 
    } 

    public function fetchAll() 
    { 
     return $this->tableGateway->select(); 
    } 

Unité de classe aussi:

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

bcause Je n'ai SampleData encore, une capture d'écran de mes deux tables unité et projet

databasestuff

EDIT4: Factorypart de 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); 
         } 
         ], 
         ]; 
    } 

Répondre

1

Ceci est très simple si vous savez comment gérer deux tables dans un modèle. En supposant que vous avez ProjectTable et UnitTable modèles et deux TableGateway services. Ceux-ci géreront deux tables respectivement dans la base de données. Donc, si vous voulez les rejoindre dans votre modèle ProjectTable qui serait alors

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

Maintenant, créez deux TableGateway services pour le traitement des deux tables et les passer au constructeur de la ProjectTable comme suit Pouvez-vous expliquer un peu plus loin ou donner un exemple pour joindre?

Model\ProjectTable::class => function($container) { 
    $projectTableGateway = $container->get(Model\ProjectTableGateway::class);   
    $unitTableGateway = $container->get(Model\UnitTableGateway::class); 

    return new Model\ProjectTable($projectTableGateway, $unitTableGateway);   
} 
+0

Je suis un grand pas en avant, mais cela ne fonctionne pas encore correctement.La sortie montre les colonnes de la table unit_table je peux les saisir al, mais elle n'a pas trouvé les colonnes de la table project_table à côté des deux qui sont nommés les mêmes dans les deux tables. Quels sont raccourci et CI_Number. Alors, comment puis-je obtenir toutes les colonnes? –

+0

Votre 'ProjectTableGateway' est correct mais n'affiche pas votre' UnitTableGateway'. J'ai commenté là où fournir des colonnes pour chaque table. Mais je n'ai pas dit comment utiliser les alias. Ici c'est pour la table d'unité $ sqlSelect-> columns (array ('alias_name' => 'column_name', ...)); C'est pour la table de projet $ sqlSelect-> join ('t_project', 't_unit.ProjectID = t_project.ProjectID', array ('alias_name' => 'nom_colonne', ...)); – unclexo

+0

J'ai essayé ceci, avec une seule colonne, juste pour comprendre. $ sqlSelect-> join ('t_project', 't_unit.ProjectID = t_project.ProjectID', array ('P' => 'Nom du projet')); Je reçois une erreur Remarque: Propriété non définie: Importer \ Model \ Unit :: $ P dans C: \ xampp \ htdocs \ ohb \ module \ Import \ view \ import \ import \ index.phtml sur la ligne 37 et mon vardump ne pas montre la colonne. –

0

Je pense que vous manquez le point. Vous n'accédez pas aux tables qui manipulent les passerelles de table. Ce que vous devez faire est d'utiliser des passerelles de table, de sorte que vous n'avez plus à traiter avec des tables et SQL. D'où le nom du motif Table Gateway.

Regardez comment ZF manual describes this. Après avoir fait cela, il est facile de joindre deux tables derrière une seule méthode d'une passerelle de table. Cette méthode renvoie un modèle complètement supprimé de la notion de base de données.

+0

Parce que j'ai lu tout ce que je pouvais déjà trouver, et je n'ai pas bien compris. Bien sûr, j'ai pu accéder à mon adaptateur dans mon contrôleur et exécuter un sql à partir d'ici, mais je veux vraiment comprendre ce concept de tablegateway. –

+0

thx à vous aussi jobain a obtenu la solution –