大家好!
我在一些原则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 DoctrineCommonCollectionsArrayCollection $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): DoctrineORMUnitOfWork->computeAssociationChanges(Array, 1)
#1 /usr/share/php/Doctrine/ORM/UnitOfWork.php(505): DoctrineORMUnitOfWork->computeChangeSet(Object(DoctrineORMMappingClassMetadata), Object(Model_AnalyticsData))
#2 /usr/share/php/Doctrine/ORM/UnitOfWork.php(249): DoctrineORMUnitOfWork->computeChangeSets()
#3 /usr/share/php/Doctrine/ORM/EntityManager.php(328): DoctrineORMUnitOfWork->commit()
#4 /home/tom/development/seo.qe.org/application/modules/default/controllers/AnalyticsController.php(64): DoctrineORMEntityManager->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。