原则2中的一对多关系ORM不插入远程键


One to many relationships in Doctrine 2 ORM not inserting remote key

大家好!

我在一些原则2的关系上遇到了问题,这些关系目前使我陷入困境。

我正试图在我的AnalyticsCampaign模型和我的AnalyticsData模型之间建立一个非常好的和简单的一对多关系。

下面是我的代码和我的问题。

foreach($entries as $entry)
{
    // Instance of AnalyticsCampaign model with data in it.
    $campaign = $this->_getCampaignByGoogleId($entry['campaignId']);            
    $daysAgo = time() - $campaign->getUpdated();
    $dateCreated = time() - $campaign->getCreated();
    if($daysAgo>=86400 || $dateCreated < 86400)
    {
        // More or equal to 1 day has passed since last database update
        // Let's insert these fuckers.
        // Insert the new GA data.
        $data = new Model_AnalyticsData();
        $data->fromArray($entry);
        $data->setCampaign($campaign->getId());
        $campaign->data = array($data);
        $this->em->persist($campaign);
    }
}
$this->em->flush();

Analytics Campaign data

<?php

/**
 * AnalyticsCampaign
 *
 * @Table(name="analyticsCampaign")
 * @Entity
 */
class Model_AnalyticsCampaign
{
    const STATUS_ACTIVE = 1;
    const STATUS_INACTIVE = 0;
    /**
     * @var integer $id
     *
     * @Column(name="id", type="integer", nullable=false)
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     */
    private $id;
    /**
     * @var string $name
     *
     * @Column(name="name", type="string", length=255, nullable=true)
     */
    private $name;
    /**
     * @var string $analyticsCampaignId
     *
     * @Column(name="analyticsCampaignId", type="integer", length=25, nullable=false)
     */
    private $analyticsCampaignId;

    /**
     * @Column(type="integer")
     */
    private $updated;
    /**
     * @Column(type="integer")
     */
    private $created;
    /**
     * @Column(type="integer")
     */
    private $status;
    /**
     * @OneToMany(targetEntity="Model_AnalyticsData", mappedBy="campaign", cascade={"persist"})
     * @param 'Doctrine'Common'Collections'ArrayCollection $data
     */
    private $data;

    public function __construct()
    {
        $this->updated();
        $this->created = time();
        if(empty($this->status))
        {
            $this->status = Model_AnalyticsCampaign::STATUS_INACTIVE;
        }
    }
    public function updated()
    {
        $this->updated = time();
    }
    public function created()
    {
        $this->created = time();
    }
    public function getId()
    {
        return $this->id;
    }

    public function fromArray(array $array)
    {
        $objects = get_object_vars($this);
        foreach($array as $item => $value)
        {
            if(array_key_exists($item, $objects))
            {
                $this->$item = $value;
            }
        }
    }
    public function setUpdated()
    {
        $this->updated();
    }
    public function getUpdated()
    {
        return ((!empty($this->updated)) ? $this->updated : 0);
    }
    public function setCreated()
    {
        $this->created();
    }
    public function getCreated()
    {
        return ((!empty($this->created)) ? $this->created : 0);
    }
    public function setStatus($status)
    {
        $statusFlag = "SELF::STATUS_".strtoupper($status);
        if(!defined($statusFlag))
        {
            throw new 'InvalidArgumentException("Status '$status' is not valid", 500);
        }
        $this->status = constant($statusFlag);
    }
    public function getStatus()
    {
        $constants = getActiveStatusConstants();
        if(isset($constants[$this->status]))
        {
            return $constants[$this->status];
        }
    }
    private function getActiveStatusConstants()
    {
        $vars = get_object_vars();
        $potentialStatus = array();
        foreach($vars as $var)
        {
            if(strpos("STATUS_") == 0)
            {
                // Matching all of our status variables.
                $potentialStatus[] = array(
                    constant("SELF::$var") => substr($var, 7, strlen($var))
                );
            }
        }
        return $potentialStatus;
    }
    public function __get($property)
    {
        return $this->$property;
    }
    public function __set($property,$value)
    {
        $this->$property = $value;
    }
}

AnalyticsData模型
<?php
/**
 * AnalyticsData
 *
 * @Table(name="analyticsData")
 * @Entity
 */
class Model_AnalyticsData
{
    public function __construct()
    {
        // constructor is never called by Doctrine
        $this->created = $this->updated = time();
    }

    /**
     * @var integer $id
     *
     * @Column(name="id", type="integer", nullable=false)
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var integer $campaignrank
     *
     * @Column(name="campaignRank", type="integer", nullable=true)
     */
    private $campaignRank;
    /**
     * @var decimal $cost
     *
     * @Column(name="cost", type="decimal", nullable=true)
     */
    private $cost;
    /**
     * @var integer $impressions
     *
     * @Column(name="impressions", type="integer", nullable=true)
     */
    private $impressions;
    /**
     * @var integer $clicks
     *
     * @Column(name="clicks", type="integer", nullable=true)
     */
    private $clicks;
    /**
     * @var decimal $costperclick
     *
     * @Column(name="costPerClick", type="decimal", nullable=true)
     */
    private $costPerClick;
    /**
     * @var integer $averagecampaignposition
     *
     * @Column(name="averageCampaignPosition", type="integer", nullable=true)
     */
    private $averageCampaignPosition;
    /**
     * @Column(type="integer")
     */
    private $created;
    /**
     * @Column(type="integer")
     */
    private $updated;
    /**
     *
     * Store a reference to the campaign that this relates to
     * @ManyToOne(targetEntity="Model_AnalyticsCampaign", inversedBy="data")
     * @JoinColumn(name="campaignId", referencedColumnName="id")
     */
    protected $campaign;

    public function fromArray(array $array)
    {
        $objects = get_object_vars($this);
        foreach($array as $item => $value)
        {
            if(array_key_exists($item, $objects))
            {
                $this->$item = $value;
            }
        }
    }
    /**
     * @PreUpdate
     */
    public function updated()
    {
        $this->updated = time();
    }
    public function setCampaign($id)
    {
        $this->campaign = $id;
    }

}

我遇到的问题是,它确实添加了子表数据没有问题,但它没有填写我的竞选id字段,这是在AnalyticsData。

当我手动尝试设置ID时,它会显示:

Exception information:
Message: A new entity was found through a relationship that was not configured to cascade persist operations: @. Explicitly persist the new entity or configure cascading persist operations on the relationship.
Stack trace:
#0 /usr/share/php/Doctrine/ORM/UnitOfWork.php(490): Doctrine'ORM'UnitOfWork->computeAssociationChanges(Array, 1)
#1 /usr/share/php/Doctrine/ORM/UnitOfWork.php(505): Doctrine'ORM'UnitOfWork->computeChangeSet(Object(Doctrine'ORM'Mapping'ClassMetadata), Object(Model_AnalyticsData))
#2 /usr/share/php/Doctrine/ORM/UnitOfWork.php(249): Doctrine'ORM'UnitOfWork->computeChangeSets()
#3 /usr/share/php/Doctrine/ORM/EntityManager.php(328): Doctrine'ORM'UnitOfWork->commit()
#4 /home/tom/development/seo.qe.org/application/modules/default/controllers/AnalyticsController.php(64): Doctrine'ORM'EntityManager->flush()
#5 /usr/share/php/Zend/Controller/Action.php(513): AnalyticsController->indexAction()
#6 /usr/share/php/Zend/Controller/Dispatcher/Standard.php(295): Zend_Controller_Action->dispatch('indexAction')
#7 /usr/share/php/Zend/Controller/Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#8 /usr/share/php/Zend/Application/Bootstrap/Bootstrap.php(97): Zend_Controller_Front->dispatch()
#9 /usr/share/php/Zend/Application.php(366): Zend_Application_Bootstrap_Bootstrap->run()
#10 /home/tom/development/seo.qe.org/public/index.php(26): Zend_Application->run()
#11 {main}                
Request Parameters:
array (
  'controller' => 'analytics',
  'action' => 'index',
  'module' => 'default',
)                

有没有人见过这个,如果有,我到底做错了什么?

非常感谢,我将给100万互联网的人可以帮助!

问题是因为我需要将AnalyticsData插入AnalyticsCampaign,然后将AnalyticsCampaign插入AnalyticsData。

我对Doctrine的看法显然完全错了。我需要从物体的角度来思考。因此,当我试图插入CampaignId时,它失败了,因为Doctrine必须与对象而不是ID建立关系。

所以我的代码最终是这样的:
$data = new Model_AnalyticsData();
$data->fromArray($entry);
$data->setCampaign($campaign);
$campaign->data = array($data);
$this->em->persist($campaign);

所以因为$campaign->data是一个ArrayObject,它不会只接受对象,所以你需要先把它放在一个Array中(显然意味着你可以插入尽可能多的子实体)。

原来如此!

所有的功劳都归功于berberlei在freenode IRC上的#doctrine。