Php 从zend framework 2中的另一个模块获取数据

Php 从zend framework 2中的另一个模块获取数据,php,zend-framework2,Php,Zend Framework2,我安装了SkeletonApplication,并从ZF2文档创建了默认相册模块 之后,我创建了分类模块,比如相册模块。 下面是它的字段:类别id和类别名称 然后为相册表添加了额外字段:cat_id 据你所知,我正试图对专辑进行分类 然后,我将这段代码添加到AlbumForm.php文件中,用于从selectbox选择cat_id字段集 $this->add(array( 'type' => 'Zend\Form\Element\Select', 'name' =&g

我安装了SkeletonApplication,并从ZF2文档创建了默认相册模块

之后,我创建了分类模块,比如相册模块。 下面是它的字段:类别id和类别名称

然后为相册表添加了额外字段:cat_id 据你所知,我正试图对专辑进行分类

然后,我将这段代码添加到AlbumForm.php文件中,用于从selectbox选择cat_id字段集

$this->add(array(
    'type' => 'Zend\Form\Element\Select',
    'name' => 'cat_id',
    'options' => array(
            'value_options' => $selectOptions,
        'label' => 'Category',
     ),
)); 

现在,如何从另一个类别模块到相册模块获取类别名称和类别id?

如果我们能看到您的类别模块文件的代码,那就太好了

首先,你应该考虑如果你真的需要一个新的模块,因为它可能应该在同一个模块中,只是创建新的模型类和新的视图,如果有的话。无论如何,在这一点上,这并不重要

如果您在相册模块中使用SkeletonApplication,那么在module.php中,您有以下代码:

 public function getServiceConfig()
    {
        return array(
                'factories' => array(
                        'Album\Model\AlbumTable' =>  function($sm) {
                            $tableGateway = $sm->get('AlbumTableGateway');
                            $table = new AlbumTable($tableGateway);
                            return $table;
                        },
                        'AlbumTableGateway' => function ($sm) {
                            $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                            $resultSetPrototype = new ResultSet();
                            $resultSetPrototype->setArrayObjectPrototype(new Album());
                            return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                        },
                ),
        );
    }
然后你可能为你的分类表创建了类似的东西,比如

 public function getServiceConfig()
    {
        return array(
                'factories' => array(
                        'Category\Model\CategoryTable' =>  function($sm) {
                            $tableGateway = $sm->get('CategoryTableGateway');
                            $table = new CategoryTable($tableGateway);
                            return $table;
                        },
                        'CategoryTableGateway' => function ($sm) {
                            $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                            $resultSetPrototype = new ResultSet();
                            $resultSetPrototype->setArrayObjectPrototype(new Album());
                            return new TableGateway('category', $dbAdapter, null, $resultSetPrototype);
                        },
                ),
        );
    }
如果差别很大,请告诉我

由于所有配置都已合并,因此无论您是否在其他模块中,您的服务经理都可以在控制器中找到Category\Model\CategoryTable

因此,您必须修改AlbumForm类,例如在构造函数中,您可以传递依赖项,例如servicemanager或“Category\Model\CategoryTable”,以便在需要检索$selectOptions列表时,可以访问它进行任何查询

此外,您可以从中查看更精细的解决方案,但这可能更难理解


此外,您还可以检查这一点,并从jamescarr中获得所需的大致相同的结果。这真的很容易理解,而且是一个很好的解决方案。

如果我们能看到您的类别模块文件的代码,那就太好了

首先,你应该考虑如果你真的需要一个新的模块,因为它可能应该在同一个模块中,只是创建新的模型类和新的视图,如果有的话。无论如何,在这一点上,这并不重要

如果您在相册模块中使用SkeletonApplication,那么在module.php中,您有以下代码:

 public function getServiceConfig()
    {
        return array(
                'factories' => array(
                        'Album\Model\AlbumTable' =>  function($sm) {
                            $tableGateway = $sm->get('AlbumTableGateway');
                            $table = new AlbumTable($tableGateway);
                            return $table;
                        },
                        'AlbumTableGateway' => function ($sm) {
                            $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                            $resultSetPrototype = new ResultSet();
                            $resultSetPrototype->setArrayObjectPrototype(new Album());
                            return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
                        },
                ),
        );
    }
然后你可能为你的分类表创建了类似的东西,比如

 public function getServiceConfig()
    {
        return array(
                'factories' => array(
                        'Category\Model\CategoryTable' =>  function($sm) {
                            $tableGateway = $sm->get('CategoryTableGateway');
                            $table = new CategoryTable($tableGateway);
                            return $table;
                        },
                        'CategoryTableGateway' => function ($sm) {
                            $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                            $resultSetPrototype = new ResultSet();
                            $resultSetPrototype->setArrayObjectPrototype(new Album());
                            return new TableGateway('category', $dbAdapter, null, $resultSetPrototype);
                        },
                ),
        );
    }
如果差别很大,请告诉我

由于所有配置都已合并,因此无论您是否在其他模块中,您的服务经理都可以在控制器中找到Category\Model\CategoryTable

因此,您必须修改AlbumForm类,例如在构造函数中,您可以传递依赖项,例如servicemanager或“Category\Model\CategoryTable”,以便在需要检索$selectOptions列表时,可以访问它进行任何查询

此外,您可以从中查看更精细的解决方案,但这可能更难理解


此外,您还可以检查这一点,并从jamescarr中获得所需的大致相同的结果。它非常容易理解,是一个很好的解决方案。

事实上,您不必为您的类别模型创建新模块 =>将其放入相册模块:

对模块进行乘法不是一个好主意。。。每张桌子一张太多了

在我的先例aswer之后,我看到您仍然有问题,我编写并注释了所有代码,以便您更好地理解:

ServiceManager工厂是一个非常重要的概念,需要很好地理解

因此,首先必须在module.php文件中进行工厂配置:

namespace Album;

use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

use Album\Model\Album;
use Album\Model\AlbumTable;
use Album\Model\Category;
use Album\Model\CategoryTable;

class Module
{

    public function getServiceConfig()
    {
        return array (
            'factories' => array(
                //here already the AlbumTable config

                // here begin the categoryTable factory
                'Album\Model\CategoryTable' =>  function($sm)
                {
                    //get the tableGateway just below in his own factory
                    $tableGateway = $sm->get('CategoryTableGateway');
                    //inject the tableGateway in the Table
                    $table = new CategoryTable($tableGateway);
                    return $table;
                },
                //here is the tableGateway Factory for the category
                'CategoryTableGateway' => function($sm)
                {
                    //get adapter to donnect dataBase
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    // create a resultSet
                    $resultSetPrototype = new ResultSet();
                    //define the prototype of the resultSet 
                    // => what object will be cloned to get the results
                    $resultSetPrototype->setArrayObjectPrototype(new Category());
                    //here you define your database table (category) 
                    //when you return the tableGateway to the CategoryTable factory
                    return new TableGateway('category', $dbAdapter, null, $resultSetPrototype);
                },
            ),
        ),
    }
}
在module/Album/src/Album/Model中创建Category.php文件:

namespace Album\Model;

class Category
{
    public $id;
    public $name;

    public function exchangeArray(){
        $this->id     = (isset($data['id'])) ? $data['id'] : null;
        $this->name = (isset($data['name'])) ? $data['name'] : null;
    }

}
在同一文件夹中创建CategoryTable.php文件。选择输入只需要fetchAll方法,您只需要所有类别的列表

namespace Album\Model;

use Zend\Db\TableGateway\TableGateway;

use Album\Model\Category;

class CategoryTable
{
    protected $tableGateway;

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

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


     public function getCategory($id){
        // ...
     }

    public function saveCategory(Category $category)
    {
       // ...
    }

     public function deleteCategory($id)
     {       
        // ...
     }
}
别忘了在AlbumTable::saveAlbum方法中添加新的cat_id字段

在相册/表单文件夹中创建您的表单和他的过滤器

namespace Album\Form;

class AlbumForm{
    public function __construct($cat_options){

        $this->add(array(
            'name' => 'id',
            'required' => false,
            'type' => 'hidden',
        ));

        $this->add(array(
            'name' => 'cat_id',
            'required' => true,
            'type' => 'Select',
            'options' => array(
                'value_options' => $cat_options,
                'label' => 'Category',
            )
            'attributes' => array(
                'value' => 3, // to select a default value
            )
        ));
        //and the rest of the form
         $this->add(array(
            'name' => 'submit',
            'type' => 'Submit',
            'attributes' => array(
                'id' => 'submitbutton',
                'value' => 'Go',
            ),
        ));
    }
}
注意,我将过滤器放在一个特定的类中,与表单所在的名称空间相同。 =>当您在一个模块中有很多表单和模型时,更容易找到。。。 =>我更喜欢这样,所以我重新编译它:D =>对于同一型号,您可以有多个表单,例如注册、登录和重置密码表单,它们都用于同一用户类

namespace Album\Form;

use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;

class AlbumFilter implements InputFilterAwareInterface
{
    protected $inputFilter;

    public function setInputFilter(InputFilterInterface $inputFilter)
    {
        throw new \Exception("Not used");
    }

    public function getInputFilter()
    {
        if(!$this->inputFilter)
        {
            $inputFilter = new InputFilter();

            $inputFilter->add(array(
                'name'     => 'id',
                'required' => false,
                'filters'  => array(
                    array('name' => 'Int'),
                ),
            ));
            $inputFilter->add(array(
                'name'     => 'cat_id',
                'required' => true,
                'filters'  => array(
                    array('name' => 'Int'),
                ),
            ));

            $inputFilter->add(array(
                'name'     => 'artist',
                'required' => true,
                'filters'  => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim'),
                ),
                'validators' => array(
                    array(
                        'name'    => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min'      => 1,
                            'max'      => 45,
                        ),
                    ),
                ),
            ));

            $inputFilter->add(array(
                'name'     => 'title',
                'required' => true,
                'filters'  => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim'),
                ),
                'validators' => array(
                    array(
                        'name'    => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min'      => 1,
                            'max'      => 45,
                        ),
                    ),
                ),
            ));
            $this->inputFilter = $inputFilter;
        }
        return $this->inputFilter;
    }

}
现在一切都配置好了,让控制器:

namespace Album\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Album\Model\Album;
use Album\Form\AlbumForm;

class MyControler extends AbstractActionController
{
    private $CategoryTable;

    public function getAlbumsTable(){
        if(!$this->Album){
            // get AlbumTable from the ServiceLocator factory (defined in Module.php)
            $this->Album = $this->getServiceLocator()
                ->get('Album\Model\AlbumTable'); 
        }
    }

    public function getCategoryTable(){
        if(!$this->CategoryTable){
            $this->CategoryTable = $this->getServiceLocator()
                ->get('Album\Model\CategoryTable');
        }
    }

    public function addAction(){
        //get the categories from the database
        $categories = $this->getCategoryTable()->fetchall();

        //make an array from the resultSet
            // you can do it as well in your controller
            //or in your form class like I did in my yersterday's answer
        $cat_options = array();
            foreach ($categories as $category) {
                $cat_options[$category->id]=$category->name;
            }

        //create your form with category list as parameter
        $form = new AlbumForm($cat_options);
        //here I recomend to create a specific class for you filters
        // and not put it in your Album class as describe in the zf tutorial

        // => so you can have several forms using the same Model
        // and it is more easy to find on the form folder ;)
        $filter = new AlbumFilter();
        //inject InputFilter in your form
        $form->setInputFilter($filter->getInputFilter());
        //inject data in form
        $form->setData($request->getPost());
        //check the form validity (data vs filters)
        if($form->isValid()){
            //create a new album
            $album = new Album();  
            //hydrate your Album
            $album->exchangeArray($form->getData());
            //ask the albumsTable to save album in the database
            $this->albumsTable->saveAlbum($album);

            //here you can redirect to the Album list
            $this->redirect()->toRoute('Album');
        }
        //call the viewModel if first time you see the page
        // or if validation errors of the form.
        return array('form' =>$form);
    }
}
那么你只需要提出你的观点。。。我不会冒犯你把这个代码放在这里


如果您仍然需要在应用程序中创建多个模块,您可以使用工厂使用getobjectTable方法调用控制器中的任何objectTable:正如Carlos所说,getServiceConfig数组都合并在一个中,因此您可以从应用程序中的任何位置获取任何表:

Infact,您不必为类别模型创建新模块 =>将其放入相册模块:

这不是一个好主意 多重模块。。。每张桌子一张太多了

在我的先例aswer之后,我看到您仍然有问题,我编写并注释了所有代码,以便您更好地理解:

ServiceManager工厂是一个非常重要的概念,需要很好地理解

因此,首先必须在module.php文件中进行工厂配置:

namespace Album;

use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

use Album\Model\Album;
use Album\Model\AlbumTable;
use Album\Model\Category;
use Album\Model\CategoryTable;

class Module
{

    public function getServiceConfig()
    {
        return array (
            'factories' => array(
                //here already the AlbumTable config

                // here begin the categoryTable factory
                'Album\Model\CategoryTable' =>  function($sm)
                {
                    //get the tableGateway just below in his own factory
                    $tableGateway = $sm->get('CategoryTableGateway');
                    //inject the tableGateway in the Table
                    $table = new CategoryTable($tableGateway);
                    return $table;
                },
                //here is the tableGateway Factory for the category
                'CategoryTableGateway' => function($sm)
                {
                    //get adapter to donnect dataBase
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    // create a resultSet
                    $resultSetPrototype = new ResultSet();
                    //define the prototype of the resultSet 
                    // => what object will be cloned to get the results
                    $resultSetPrototype->setArrayObjectPrototype(new Category());
                    //here you define your database table (category) 
                    //when you return the tableGateway to the CategoryTable factory
                    return new TableGateway('category', $dbAdapter, null, $resultSetPrototype);
                },
            ),
        ),
    }
}
在module/Album/src/Album/Model中创建Category.php文件:

namespace Album\Model;

class Category
{
    public $id;
    public $name;

    public function exchangeArray(){
        $this->id     = (isset($data['id'])) ? $data['id'] : null;
        $this->name = (isset($data['name'])) ? $data['name'] : null;
    }

}
在同一文件夹中创建CategoryTable.php文件。选择输入只需要fetchAll方法,您只需要所有类别的列表

namespace Album\Model;

use Zend\Db\TableGateway\TableGateway;

use Album\Model\Category;

class CategoryTable
{
    protected $tableGateway;

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

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


     public function getCategory($id){
        // ...
     }

    public function saveCategory(Category $category)
    {
       // ...
    }

     public function deleteCategory($id)
     {       
        // ...
     }
}
别忘了在AlbumTable::saveAlbum方法中添加新的cat_id字段

在相册/表单文件夹中创建您的表单和他的过滤器

namespace Album\Form;

class AlbumForm{
    public function __construct($cat_options){

        $this->add(array(
            'name' => 'id',
            'required' => false,
            'type' => 'hidden',
        ));

        $this->add(array(
            'name' => 'cat_id',
            'required' => true,
            'type' => 'Select',
            'options' => array(
                'value_options' => $cat_options,
                'label' => 'Category',
            )
            'attributes' => array(
                'value' => 3, // to select a default value
            )
        ));
        //and the rest of the form
         $this->add(array(
            'name' => 'submit',
            'type' => 'Submit',
            'attributes' => array(
                'id' => 'submitbutton',
                'value' => 'Go',
            ),
        ));
    }
}
注意,我将过滤器放在一个特定的类中,与表单所在的名称空间相同。 =>当您在一个模块中有很多表单和模型时,更容易找到。。。 =>我更喜欢这样,所以我重新编译它:D =>对于同一型号,您可以有多个表单,例如注册、登录和重置密码表单,它们都用于同一用户类

namespace Album\Form;

use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;

class AlbumFilter implements InputFilterAwareInterface
{
    protected $inputFilter;

    public function setInputFilter(InputFilterInterface $inputFilter)
    {
        throw new \Exception("Not used");
    }

    public function getInputFilter()
    {
        if(!$this->inputFilter)
        {
            $inputFilter = new InputFilter();

            $inputFilter->add(array(
                'name'     => 'id',
                'required' => false,
                'filters'  => array(
                    array('name' => 'Int'),
                ),
            ));
            $inputFilter->add(array(
                'name'     => 'cat_id',
                'required' => true,
                'filters'  => array(
                    array('name' => 'Int'),
                ),
            ));

            $inputFilter->add(array(
                'name'     => 'artist',
                'required' => true,
                'filters'  => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim'),
                ),
                'validators' => array(
                    array(
                        'name'    => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min'      => 1,
                            'max'      => 45,
                        ),
                    ),
                ),
            ));

            $inputFilter->add(array(
                'name'     => 'title',
                'required' => true,
                'filters'  => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim'),
                ),
                'validators' => array(
                    array(
                        'name'    => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min'      => 1,
                            'max'      => 45,
                        ),
                    ),
                ),
            ));
            $this->inputFilter = $inputFilter;
        }
        return $this->inputFilter;
    }

}
现在一切都配置好了,让控制器:

namespace Album\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Album\Model\Album;
use Album\Form\AlbumForm;

class MyControler extends AbstractActionController
{
    private $CategoryTable;

    public function getAlbumsTable(){
        if(!$this->Album){
            // get AlbumTable from the ServiceLocator factory (defined in Module.php)
            $this->Album = $this->getServiceLocator()
                ->get('Album\Model\AlbumTable'); 
        }
    }

    public function getCategoryTable(){
        if(!$this->CategoryTable){
            $this->CategoryTable = $this->getServiceLocator()
                ->get('Album\Model\CategoryTable');
        }
    }

    public function addAction(){
        //get the categories from the database
        $categories = $this->getCategoryTable()->fetchall();

        //make an array from the resultSet
            // you can do it as well in your controller
            //or in your form class like I did in my yersterday's answer
        $cat_options = array();
            foreach ($categories as $category) {
                $cat_options[$category->id]=$category->name;
            }

        //create your form with category list as parameter
        $form = new AlbumForm($cat_options);
        //here I recomend to create a specific class for you filters
        // and not put it in your Album class as describe in the zf tutorial

        // => so you can have several forms using the same Model
        // and it is more easy to find on the form folder ;)
        $filter = new AlbumFilter();
        //inject InputFilter in your form
        $form->setInputFilter($filter->getInputFilter());
        //inject data in form
        $form->setData($request->getPost());
        //check the form validity (data vs filters)
        if($form->isValid()){
            //create a new album
            $album = new Album();  
            //hydrate your Album
            $album->exchangeArray($form->getData());
            //ask the albumsTable to save album in the database
            $this->albumsTable->saveAlbum($album);

            //here you can redirect to the Album list
            $this->redirect()->toRoute('Album');
        }
        //call the viewModel if first time you see the page
        // or if validation errors of the form.
        return array('form' =>$form);
    }
}
那么你只需要提出你的观点。。。我不会冒犯你把这个代码放在这里


如果您仍然需要在应用程序中创建多个模块,则可以使用工厂使用getobjectTable方法调用控制器中的任何objectTable:正如Carlos所说,getServiceConfig数组都合并在一个中,因此,您可以从应用程序中的任何位置获取任何表:

就像您所说的my Album module的module.php和Category module的module.php完全相同。我查了samsonasik的链接,但就像你说的,我不明白。我会检查你的新链接,然后回到这里。如果你没有得到其他示例,我将按照我自己的方法为你提供更多易于理解的代码。这是一个很好的教程,可以帮助你理解如何做到这一点,但它与数据库无关。所以我没有很好地理解它正如您所说,我的相册模块的module.php和分类模块的module.php完全相同。我查了samsonasik的链接,但就像你说的,我不明白。我会检查你的新链接,然后回到这里。如果你没有得到其他示例,我将按照我自己的方法为你提供更多易于理解的代码。这是一个很好的教程,可以帮助你理解如何做到这一点,但它与数据库无关。所以我没有很好地理解它我建议我的博客帖子我建议我的博客帖子我按照你说的做了一切,但是添加相册页面得到了这个错误:致命错误:在C:\xampp\htdocs\tasarim\module\album\src\album\Controller\album Controller.php的第39行调用非对象上的成员函数fetchall,我按照你说的做了一切,但是添加相册页面得到了这个错误:致命错误:在第39行的C:\xampp\htdocs\tasarim\module\Album\src\Album\Controller\AlbumController.php中对非对象调用成员函数fetchall