1

私は最近 ZF2 の学習を開始しました。誰かがこれを手伝ってくれることを願っています。

私は、Rob Allen の Zend Framework 2 チュートリアル (@rob-allen に感謝します) に取り組んでいます。

また、@AlloVince と @Maciej How to set db adapter to Validator RecordExists in Zend Framework 2のソリューションを使用します (両方の作成者に感謝します)。 editActionでこのソリューションを使用しなかったため、混乱しました。

Fatal error: Call to a member function get() on a non-objectでわかり'adapter' => $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter')ます。

1) Module.php に追加

public function getServiceConfig()
{
    return array(
        'invokables' => array(
            'RegionModel' => 'FcLibraries\Model\Region', //<-- added it
        ),
        'factories' => array(
            'FcLibraries\Model\RegionTable' => function ($sm) {
                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                $table = new RegionTable($dbAdapter);
                return $table;
            },
        ),
    );
}

2) Region.php に追加

/**
 * @var
 */
protected $serviceLocator;
/**
 * @param \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator
 * @return Library
 */
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
    $this->serviceLocator = $serviceLocator;
    return $this;
}
/**
 * @return \Zend\ServiceManager\ServiceLocatorInterface
 */
public function getServiceLocator()
{
    return $this->serviceLocator;
}

        $inputFilter->add($factory->createInput(array(
            'name' => 'name',
            'required' => true,
            'filters' => $this->_filters,
            'validators' => array(
                array(
                    'name' => 'StringLength',
                    'options' => array(
                        'encoding' => 'UTF-8',
                        'min' => 1,
                        'max' => 30,
                    ),
                ),
                array(
                    'name'    => 'Db\NoRecordExists',
                    'options' => array(
                        'table' => $this->table,
                        'field' => 'name',
                        //'exclude' => array(
                        //    'field' => 'id',
                        //    'value' => $this->id
                        //),
                        'adapter' => $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter'),
                    ),
                ),
            ),
        )));

3) addAction の RegionController.php で

$model = $this->getServiceLocator()->get('RegionModel');

の代わりに$model = new Region();

これは addAction では問題なく機能しますが、editAction でどのように使用すればよいかわかりません。

じぶんの

public function editAction()
{
    $id = (int)$this->params()->fromRoute('id', 0);
    if (!$id) {
        return $this->redirect()->toRoute('zfcadmin/region', array(
            'action' => 'add'
        ));
    }
    $data = $this->getRegionTable()->get($id);
    $form = new RegionForm();
    $form->bind($data);
    $form->get('submitBtn')->setAttribute('value', 'Save');
    $request = $this->getRequest();
    if ($request->isPost()) {
        $form->setInputFilter($data->getInputFilter());
        $form->setData($request->getPost());
        if ($form->isValid()) {
            $this->getRegionTable()->save($form->getData());
            return $this->redirect()->toRoute('zfcadmin/regions');
        }
    }
    return array(
        'id' => $id,
        'form' => $form,
    );
}

私のRegionTableには次のコードがあります:

/**
 * @param \Zend\Db\Adapter\Adapter $adapter
 */
public function __construct(Adapter $adapter)
{
    $this->adapter = $adapter;
    $this->resultSetPrototype = new ResultSet();
    $this->resultSetPrototype->setArrayObjectPrototype(new Region());
    $this->initialize();
}
public function get($id)
{
    $id = (int)$id;
    $rowSet = $this->select(array('id' => $id));
    $row = $rowSet->current();
    if (!$row) {
        throw new \Exception("Could not find row $id");
    }
    return $row;
}

私の質問に答えてくれるすべての人に感謝します。

よろしく、ルスラン。

4

2 に答える 2

3

テーブルから収集したエンティティからフォーム フィルタを使用する代わりに、サービス マネージャを介して新しいエンティティをインスタンス化し、データベース アダプタを使用する必要があります。

いくつかのオプションがあります:

  1. 入力フィルターを独自のクラスに移動し、サービス マネージャーを介してインスタンス化して、データベース アダプターが挿入されるようにします。
  2. サービス マネージャー ファクトリを介してインスタンス化されるように、テーブル ゲートウェイ ファクトリのプロトタイプ オブジェクトを変更します。
  3. サービス マネージャーを介して別のエンティティをインスタンス化し、そこから入力フィルターを取得します。

コードをより適切に分離するため、個人的にはオプション 1 を使用します。

いくつかの例:

オプション 1 (私の選択):

これには、フィルターを独自のファイルとクラスに移動し、データベース アダプターを挿入しながらフィルターのファクトリを作成する必要があります。次に、コントローラーで、サービス マネージャーを介してフィルターを取得し、そのフィルターをフォームに適用します。

したがって、最初にフィルターを ModName\src\ModName\Form\RegionFilter.php のファイルに移動し、明らかに ModName をモジュール名に置き換えます。

コードを次のように変更します。

<?php
namespace Region\Form;

use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Db\Adapter\Adapter;

class RegionFilter implements InputFilterAwareInterface {

    /**
     * @var inputFilter
     */
    protected $inputFilter;

    /**
     * @var Database Adapter
     */
    protected $dbAdapter;

    /**
     * @param \Zend\InputFilter\InputFilterInterface $inputFilter
     * @throws \Exception
     */
    public function setInputFilter(InputFilterInterface $inputFilter) {
        throw new \Exception("Not used");
    }

    /**
     * @param \Zend\Db\Adapter $dbAdapter
     */
    public function __construct(Adapter $dbAdapter) {
        $this->dbAdapter = $dbAdapter;
    }

    /**
     * 
     * @return Zend\Db\Adapter
     */
    public function getDbAdapter() {
        return $this->dbAdapter;
    }

    /**
     * @return \Zend\InputFilter\InputFilter
     * 
     * Get the input filter (build it first)
     */
    public function getInputFilter() {
        if (!$this->inputFilter) {

            $inputFilter = new InputFilter();
            $factory = new InputFactory();

            $inputFilter->add($factory->createInput(array(
                'name' => 'name',
                'required' => true,
                'filters' => $this->_filters,
                'validators' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min' => 1,
                            'max' => 30,
                        ),
                    ),
                    array(
                        'name' => 'Db\NoRecordExists',
                        'options' => array(
                            'table' => $this->table,
                            'field' => 'name',
                            //'exclude' => array(
                            //    'field' => 'id',
                            //    'value' => $this->id
                            //),
                            'adapter' => $this->getDbAdapter(),
                        ),
                    ),
                ),
            )));
                    $this->inputFilter = $inputFilter;
        }

        return $this->inputFilter;
    }
}
?>

次に、Module.php で次のようなファクトリを作成します。

public function getServiceConfig()
{
    return array(
        'factories' => array(
            'ModName\Form\RegionFilter' => function($sm) {
                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                return new RegionFilter($dbAdapter);
            },
        ),
    );
}

最後に、コントローラーで次のようにします。

if ($request->isPost()) {
    $filter = $this->getServiceLocator()->get('ModName\Form\RegionFilter');
    $form->setInputFilter($filter->getInputFilter());
    $form->setData($request->getPost());
    if ($form->isValid()) {
        $this->getRegionTable()->save($form->getData());
        return $this->redirect()->toRoute('zfcadmin/regions');
    }
}

オプション 2:

Regionこれには、注入されたインスタンスを使用してテーブルを構築することが含まれます。次に、プロトタイプをこれに設定できます。

だからあなたのテーブル構成で:

public function __construct(Adapter $adapter, Region $region)
{
    $this->adapter = $adapter;
    $this->resultSetPrototype = new ResultSet();
    $this->resultSetPrototype->setArrayObjectPrototype($region);
    $this->initialize();
}

そして、あなたの工場:

public function getServiceConfig()
{
    return array(
        'invokables' => array(
            'RegionModel' => 'FcLibraries\Model\Region', 
        ),
        'factories' => array(
            'FcLibraries\Model\RegionTable' => function ($sm) {
                $region = $sm->get('RegionModel');
                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                $table = new RegionTable($dbAdapter,$region);
                return $table;
            },
        ),
    );
}

残りのコードはそのままにしておくことができるはずです。例えばコントローラー。今、私はこの方法をテストしていないので、100% うまくいくわけではありませんが、うまくいくはずです。私が以前に使用した他の2つの方法。

オプション 3 (最も単純):

これには、サービス マネージャーを介して別のリージョン モデルを取得し、それを使用して入力フィルターをフォームに適用することが含まれます。

public function editAction()
{
    $id = (int)$this->params()->fromRoute('id', 0);
    if (!$id) {
        return $this->redirect()->toRoute('zfcadmin/region', array(
            'action' => 'add'
        ));
    }
    $data = $this->getRegionTable()->get($id);
    $form = new RegionForm();
    $form->bind($data);
    $form->get('submitBtn')->setAttribute('value', 'Save');
    $request = $this->getRequest();
    if ($request->isPost()) {
        $region = $this->getServiceLocator()->get('RegionModel');
        $form->setInputFilter($region->getInputFilter());
        $form->setData($request->getPost());
        if ($form->isValid()) {
            $this->getRegionTable()->save($form->getData());
            return $this->redirect()->toRoute('zfcadmin/regions');
        }
    }
    return array(
        'id' => $id,
        'form' => $form,
    );
}

私はコードをテストしていませんが、要点を理解する必要があります。ご不明な点がございましたら、お気軽にお問い合わせください。

于 2013-03-30T12:46:47.070 に答える