php – 无法在symfony2控制台命令中持久化对象
发布时间:2020-12-13 22:47:18 所属栏目:PHP教程 来源:网络整理
导读:我做了一个简单的symfony2控制台脚本,它应该将数据从旧模型转换为新模型. 这是它的样子: class ConvertScreenshotsCommand extends Command {[...]protected function execute(InputInterface $input,OutputInterface $output){ $em = $this-getContainer()
我做了一个简单的symfony2控制台脚本,它应该将数据从旧模型转换为新模型.
这是它的样子: class ConvertScreenshotsCommand extends Command { [...] protected function execute(InputInterface $input,OutputInterface $output) { $em = $this->getContainer()->get('doctrine')->getManager(); $output->writeln('<info>Conversion started on ' . date(DATE_RSS) . "</info>"); $output->writeln('Getting all reviews...'); $reviews = $em->getRepository('ACCommonBundle:Review')->findAll(); // Putting all Review entities into an array $output->writeln('<info>Got ' . count($reviews) . ' reviews.</info>'); foreach ($reviews as $review) { $output->writeln("<info>Screenshots for " . $review->getTitle() . "</info>"); if ($review->getLegacyScreenshots()) { foreach ($review->getLegacyScreenshots() as $filename) { // fn returns array of strings $output->writeln("Found " . $filename); $screenshot = new ReviewScreenshot(); // new object $screenshot->setReview($review); // review is object $screenshot->setFilename($filename); // filename is string $em->persist($screenshot); $em->flush(); // this is where it dies $output->writeln("Successfully added to the database."); } } else $output->writeln("No legacy screenshots found."); } $output->writeln('<info>Conversion ended on ' . date(DATE_RSS) . "</info>"); } } 该脚本在$em-> flush()上中断,出现以下错误: [ErrorException] Warning: spl_object_hash() expects parameter 1 to be object,string given in /[...]/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 1324 显然我做错了什么,但无法弄清楚它是什么.提前致谢! **更新** 查看实体映射: class Review { [...] /** * @ORMOneToMany(targetEntity="ReviewScreenshot",mappedBy="review") */ protected $screenshots; /** * Won't be stored in the DB * @deprecated */ private $legacyScreenshots; /** * New method to get screenshots,currently calls old method for the sake of compatibility * @return array Screenshot paths */ public function getScreenshots() { // return $this->getLegacyScreenshots(); // Old method return $this->screenshots; // New method } /** * Get Screenshot paths * @return array Screenshot paths * @deprecated */ public function getLegacyScreenshots() { $dir=$this->getUploadRootDir(); if (file_exists($dir)) { $fileList = scandir($dir); $this->screenshots = array(); foreach ($fileList as $fileName) { preg_match("/(screenshot-d+.*)/",$fileName,$matches); if ($matches) $this->screenshots[]=$matches[1]; } return $this->screenshots; } else return null; } ReviewScreenshot映射: class ReviewScreenshot { /** * @var integer $id * * @ORMColumn(name="id",type="integer") * @ORMId * @ORMGeneratedValue(strategy="AUTO") */ private $id; /** * @var string $filename * * @ORMColumn(name="filename",type="string",length=255) */ private $filename; /** * @ORMManyToOne(targetEntity="Review",inversedBy="screenshots") * @ORMJoinColumn(name="review_id",referencedColumnName="id") */ protected $review; /** * @var integer $priority * * @ORMColumn(name="priority",type="integer",nullable=true) */ protected $priority; /** * @var string $description * * @ORMColumn(name="description",nullable=true) */ protected $description; /** * @AssertFile(maxSize="2097152") */ public $screenshot_file; protected $webPath; UnitOfWork.php /** * Gets the state of an entity with regard to the current unit of work. * * @param object $entity * @param integer $assume The state to assume if the state is not yet known (not MANAGED or REMOVED). * This parameter can be set to improve performance of entity state detection * by potentially avoiding a database lookup if the distinction between NEW and DETACHED * is either known or does not matter for the caller of the method. * @return int The entity state. */ public function getEntityState($entity,$assume = null) { $oid = spl_object_hash($entity); // <-- Line 1324 if (isset($this->entityStates[$oid])) { return $this->entityStates[$oid]; } if ($assume !== null) { return $assume; } // State can only be NEW or DETACHED,because MANAGED/REMOVED states are known. // Note that you can not remember the NEW or DETACHED state in _entityStates since // the UoW does not hold references to such objects and the object hash can be reused. // More generally because the state may "change" between NEW/DETACHED without the UoW being aware of it. $class = $this->em->getClassMetadata(get_class($entity)); $id = $class->getIdentifierValues($entity); if ( ! $id) { return self::STATE_NEW; } switch (true) { case ($class->isIdentifierNatural()); // Check for a version field,if available,to avoid a db lookup. if ($class->isVersioned) { return ($class->getFieldValue($entity,$class->versionField)) ? self::STATE_DETACHED : self::STATE_NEW; } // Last try before db lookup: check the identity map. if ($this->tryGetById($id,$class->rootEntityName)) { return self::STATE_DETACHED; } // db lookup if ($this->getEntityPersister($class->name)->exists($entity)) { return self::STATE_DETACHED; } return self::STATE_NEW; case ( ! $class->idGenerator->isPostInsertGenerator()): // if we have a pre insert generator we can't be sure that having an id // really means that the entity exists. We have to verify this through // the last resort: a db lookup // Last try before db lookup: check the identity map. if ($this->tryGetById($id,$class->rootEntityName)) { return self::STATE_DETACHED; } // db lookup if ($this->getEntityPersister($class->name)->exists($entity)) { return self::STATE_DETACHED; } return self::STATE_NEW; default: return self::STATE_DETACHED; } } 解决方法
我认为问题出在Review :: $screenshots:
您将其映射为OneToMany关联,因此该值应为ReviewScreenshot实体的集合.但方法Review :: getLegacyScreenshots()会将其更改为字符串数组. 您可能正在使用更改跟踪策略DEFERRED_IMPLICIT(这是默认设置).因此,当属性Review :: $screenshots发生更改时,Doctrine将尝试保留该更改,遇到期望实体的字符串,因此抛出异常. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |