Zend Framework 2模型与Doctrine 2

3
我将为您翻译关于IT技术的内容,涉及Zend Framework 2。我从Ron Allen的教程http://akrabat.com/getting-started-with-zend-framework-2/开始学习,然后使用http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/的教程集成了Doctrine 2 。在此之前,我决定让它变得更加复杂。
我将数据库更改为以下内容:
--
-- Estrutura da tabela `album`
--
CREATE TABLE IF NOT EXISTS `album` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `artist_id` int(11) NOT NULL,
  `title` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `artist` (`artist_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=16 ;

--
-- Estrutura da tabela `artist`
--
CREATE TABLE IF NOT EXISTS `artist` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

我的应用程序有这样的结构:

module
    Album
        src
            Album
                Controller
                    AlbumController.php
                Entity
                    Album.php
    Artist
        src
            Artist
                Controller
                    ArtistController.php
                Entity
                    Artist.php

我的新实体是这样的:

class Album {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer");
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @ORM\ManyToOne(targetEntity="Artist", inversedBy="album")
     * @ORM\JoinColumn(name="artist_id", referencedColumnName="id")
     */
    protected $artist;

    ...
}
class Artist {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer");
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\OneToMany(targetEntity="Album", mappedBy="artist")
     */
    protected $album;


    public function __construct()
    {
        $this->album = new ArrayCollection();
    }

    ...
}

但是它不起作用!我收到了这个消息:
"The target-entity Album\Entity\Artist cannot be found in 'Album\Entity\Album#artist'."

所以我的问题是:出了什么问题?我的实体放错位置了吗?还是我的模块组织不正确?如何让一个实体在多个模块中可见?
更新:
我把我的实体改成了:
class Album {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer");
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @ORM\ManyToOne(targetEntity="\Artist\Entity\Artist", inversedBy="album")
     * @ORM\JoinColumn(name="artist_id", referencedColumnName="id")
     */
    protected $artist;

    ...
}
class Artist {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer");
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\OneToMany(targetEntity="\Album\Entity\Album", mappedBy="artist")
     */
    protected $album;

    ...
}

但是我遇到了同样的错误:

"The target-entity Artist\Entity\Artist cannot be found in 'Album\Entity\Album#artist'."

更新2:

我将我的应用程序结构更改为:

module
    Album
        src
            Album
                Controller
                    AlbumController.php
                    ArtistController.php
                Entity
                    Album.php
                    Artist.php

所以我的实体都在同一个命名空间中,现在我的程序已经可以运行了!=)

但我还有个问题:在ZF2中,我如何使一个实体对于多个模块可见?


很高兴看到你把它搞定了。Doctrine 2 真的喜欢实体在同一个目录中。Symfony 2 有一些包装代码来允许多个目录,但我从来没有仔细研究过细节。你可能需要自己摸索,至少在ZF2真正发布并且更多人开始使用之前是这样的。 - Cerad
是的,我想这只是一个ZF2的问题...但是没有人能回答我的问题...你看,如果你有一个album module(只有selectOne和selectAll)和一个admin module(有selectOne、selectAll、insert、update和delete),你会如何组织你的实体?这就是我的问题...但非常感谢@Cerad的帮助! - Vinicius Garcia
3个回答

2
我找到答案了! =D
我必须等待8小时才能回答自己的问题,所以现在开始吧。
正如我所说的,我重复了这个教程:http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/ 他们教如何配置模块以使其与Doctrine 2一起工作。 在文件module/Album/config/module.config.php中,他们插入了以下代码:
return array(
    'di' => array(
        'instance' => array(
            // ...
            'orm_driver_chain' => array(
                'parameters' => array(
                    'drivers' => array(
                        'Album' => array(
                            'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
                            'namespace' => __NAMESPACE__ . '\Entity',
                            'paths' => array(
                                __DIR__ . '/../src/' . __NAMESPACE__ . '/Entity'
                            ),
                        ),
                    ),
                ),
            ),

根据教程所述:

“这告诉Doctrine,Album模块的实体使用命名空间Album\Entity,并且该命名空间中的类存储在$PROJECT_DIR/module/Album/src/Album/Entity中。”

因此,问题出在这里! Doctrine被配置为仅使用Album\Entity! 所以我改变了代码如下(编程不好...抱歉):
//...
'drivers' => array(
    'Album' => array(
        'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
        'namespace' => __NAMESPACE__ . '\Entity',
        'paths' => array(
            __DIR__ . '/../src/' . __NAMESPACE__ . '/Entity'
        ),
    ),
    'Artist' => array(
        'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
        'namespace' => '\Artist\Entity',
        'paths' => array(
            __DIR__ . '/../../Artist/src/Artist/Entity'
        ),
    ),
//...

如您所见,我配置了一个“艺术家”驱动程序...现在我的应用程序可以正常工作了!=)我仍在寻找正确的方法来配置我的应用程序中的Doctrine,但至少我得到了答案!感谢大家!:)

1
关于您更新的问题:
您的实体和所有其他代码在一个模块中使用时都是“可见”的,只需通过实例化即可在每个其他模块中使用。
$artist = new \Album\Entity\Artist();

或者你可能需要其他的东西。 确保将所有的模块都在应用程序配置中注册。


嗯,那很好!但是为什么我的Doctrine不起作用?它一直显示那个错误消息... - Vinicius Garcia
你问题的最后几行表明没有错误。能否请您分享一下错误信息? - Samuel Herzog

0
默认情况下,Doctrine 2将在与当前实体相同的命名空间中查找相关联的实体。类似这样:
 * @ORM\ManyToOne(targetEntity="\Artist\Entity\Artist", inversedBy="album")

将会需要。免责声明:我没有使用过ZF2。我假设你的类加载器路径都已经设置好了。


嗯,不错。我会试试看的。但是这样保留我的模型正确吗?还是说我应该把它们都放在同一个命名空间中?我的意思是,如果我所有的实体都在那里,我应该有一个名为“models”的目录吗? - Vinicius Garcia
这真的取决于你。Symfony 2在命名空间等方面更成熟一些。你可以浏览文档,看看他们如何组织事物。但Doctrine并不在意这些。它只需要知道在哪里查找实体即可。 - Cerad
请使用新的实体代码和错误信息更新您的问题。如果错误信息确实相同,则说明您忘记更新某些内容了。 - Cerad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接