zf2 табличная функция как tablegateway/table

Как я могу использовать табличную функцию, как

select * from pv_my_table_valued_function(1)

"pv_my_table_valued_function(?)" в качестве таблицы для моего прохода

например, нормальная реализация будет:

'Application\Model\MyTable' =>  function($sm) {
     $tableGateway = $sm->get('MyTableGateway');
     $table = new MyTable($tableGateway);
     return $table;
},
'MyTableGateway' => function ($sm) {
      $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
      $resultSetPrototype = new ResultSet();
      $resultSetPrototype->setArrayObjectPrototype(new MyTableEntity());
      return new TableGateway('my_table', $dbAdapter, null, $resultSetPrototype);
},

Могу ли я сделать то же самое, например:

'MyTableValuedGateway' => function ($sm) {
          $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
          $resultSetPrototype = new ResultSet();
          $resultSetPrototype->setArrayObjectPrototype(new MyTableValued());
          return new TableGateway('pv_my_table_valued_function(?)', $dbAdapter, null, $resultSetPrototype);
    },

Или есть другие идеи, как это сделать вместо того, чтобы потом приводить объект Select к строке и заменять имя таблицы?

Редактировать:

В качестве быстрого базового примера того, как я буду использовать tableGateway позже: в моей модели MyTable.php

public function fetchAll()
{
    // I already initialized the tableGateway via Dependecy Injection in 
    // a __construct() in an abstract class
    $select = $this->tableGateway->getSql()->select();

    // some sql stuff
    $select->where(...);
    $select->order(...);

    // now it gets tricky.. what I normally do is known
    $resultSet = $this->tableGateway->selectWith($select);

    // what I need to do when using my table valued function is like
    $adapter = $this->tableGateway->getAdapter();
    $platform = $adapter->getPlatform();
    $sqlStr = $select->getSqlString($platform);

    $select = str_replace('FROM [my_table]', "FROM pv_my_table_valued_function({$this->my_special_parameter}) AS my_pv", $sqlStr);

    $resultSet = $adapter->query($select, array());

    return $resultSet;
}

Итак, как я могу "остаться" с объектом Select, но каким-то образом передать этот параметр с помощью символа подстановки?

Надеюсь, что это делает это более ясным

1 ответ

Если вы посмотрите на конструктор Zend\Db\TableGateway\TableGateway класс, вы обнаружите, что этот класс принимает имя таблицы в качестве первого параметра.

Предположим, что имя вашей таблицы происходит из параметра GET с именем table. Таким образом, фабрика может выглядеть следующим образом.

namespace Application\Db\TableGateway\Factory;

class MyDynamicTableFactory 
{
    public function __invoke(ContainerInterface $container)
    {
        // bc zf2 (remove when using zf3)
        $serviceLocator = $container->getServiceLocator();

        // table name from get parameter
        $router = $serviceLocator->get('router');
        $request = $serviceLocator->get('request');
        $match = $router->match($request);

        $table = $match->getParam('table');

        // adapter
        $adapter = $serviceLocator->get('Zend\Db\Adapter\Adapter');

        // resultset
        $resultset = new HydratingResultset(
            new ClassMethods(),
            new YourDynamicTableEntity()
        );

        // table gateway
        $gateway = new TableGateway($table, $adapter, null, $resultset);

        return $gateway;
    }
}

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

Просто напишите свою фабрику в вашем сервисном конфиге в module.config.php файл следующим образом...

'service_manager' => [
    'factories' => [
        'MyDynamicTable' => MyDynamicTableFactory::class,
    ],
],

С помощью этой нотации вы можете получить шлюз динамической таблицы везде, где доступен сервисный локатор. Имейте в виду, что вы не должны вызывать сервисный локатор в контроллере. Просто передайте его через внедрение зависимостей или используйте фабрики для каждого класса, который вам нужен.

Пример вызова для вашей таблицы шлюза на фабрике

$gateway = $serviceLocator->get('MyDynamicTable');

Короче говоря: используйте фабрику вместо анонимной функции, чтобы она была чистой и простой. Независимо от того, является ли фабрика или анонимная функция вызовом шлюза таблицы, принимает имя таблицы в качестве параметра в конструкторе. Так что просто получите имя таблицы из любого места и передайте его в качестве параметра.

Другие вопросы по тегам