php – 无法在symfony2控制台命令中持久化对象

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了php – 无法在symfony2控制台命令中持久化对象脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
我做了一个简单的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
{
[...]

/**
 * @ORM\OneToMany(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
 *
 * @ORM\Column(name="id",type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string $filename
 *
 * @ORM\Column(name="filename",type="string",length=255)
 */
private $filename;

/**
 * @ORM\ManyToOne(targetEntity="Review",inversedBy="screenshots")
 * @ORM\JoinColumn(name="review_id",referencedColumnName="id")
 */
protected $review;

/**
 * @var integer $priority
 *
 * @ORM\Column(name="priority",type="integer",nullable=true)
 */
protected $priority;

/**
 * @var string $description
 *
 * @ORM\Column(name="description",nullable=true)
 */
protected $description;

/**
 * @Assert\File(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将尝试保留该更改,遇到期望实体的字符串,因此抛出异常.

脚本宝典总结

以上是脚本宝典为你收集整理的php – 无法在symfony2控制台命令中持久化对象全部内容,希望文章能够帮你解决php – 无法在symfony2控制台命令中持久化对象所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。