Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Can';t在symfony2控制台命令中持久化对象_Php_Symfony_Console_Doctrine - Fatal编程技术网

Php Can';t在symfony2控制台命令中持久化对象

Php Can';t在symfony2控制台命令中持久化对象,php,symfony,console,doctrine,Php,Symfony,Console,Doctrine,我制作了一个简单的symfony2控制台脚本,用于将数据从旧模型转换为新模型。 下面是它的样子: class ConvertScreenshotsCommand extends Command { [...] protected function execute(InputInterface $input, OutputInterface $output) { $em = $this->getContainer()->get('doctrine')->getManag

我制作了一个简单的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>");
 }
 }
很明显我做错了什么,但我不知道是什么。提前谢谢

**更新**

查看实体映射:

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;
}
查看Creenshot地图:

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", type="string", 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;
    }
}
/**
*获取实体相对于当前工作单元的状态。
*
*@param对象$entity
*@param integer$假定状态为未知状态(未管理或删除)。
*可以设置此参数以提高实体状态检测的性能
*通过潜在地避免数据库查找,如果新的和分离的
*对于方法的调用方来说是已知的或不重要的。
*@return int表示实体状态。
*/
公共函数getEntityState($entity,$ASSUBE=null)
{
$oid=spl\u object\u hash($entity);//EntityState[$oid])){
返回$this->entityStates[$oid];
}
如果($假定!==null){
返回$ASTATE;
}
//状态只能是新的或分离的,因为托管/删除状态是已知的。
//请注意,您无法记住_entityStates中的新状态或分离状态,因为
//UoW不保存对此类对象的引用,并且可以重用对象哈希。
//更一般地说,因为在UoW不知道的情况下,状态可能在新建/分离之间“改变”。
$class=$this->em->getClassMetadata(get_class($entity));
$id=$class->GetIdentifierValue($entity);
如果(!$id){
返回self::STATE_NEW;
}
开关(真){
案例($class->isIdentifierNatural());
//检查版本字段(如果可用),以避免数据库查找。
如果($class->isVersioned){
返回($class->getFieldValue($entity,$class->versionField))
?self::STATE_DETACHED
:self::STATE_NEW;
}
//db查找之前的最后一次尝试:检查标识映射。
if($this->tryGetById($id,$class->rootEntityName)){
返回self::STATE_DETACHED;
}
//数据库查找
如果($this->getEntityPersister($class->name)->存在($entity)){
返回self::STATE_DETACHED;
}
返回self::STATE_NEW;
案例(!$class->idGenerator->isPostInsertGenerator()):
//如果我们有一个预插入生成器,我们不能确定是否有一个id
//确实意味着实体存在。我们必须通过
//最后的手段:数据库查找
//db查找之前的最后一次尝试:检查标识映射。
if($this->tryGetById($id,$class->rootEntityName)){
返回self::STATE_DETACHED;
}
//数据库查找
如果($this->getEntityPersister($class->name)->存在($entity)){
返回self::STATE_DETACHED;
}
返回self::STATE_NEW;
违约:
返回self::STATE_DETACHED;
}
}

我认为问题在于
评论::$screenshots

您将其映射为OneToMany关联,因此该值应该是
ReviewScreenshot
实体的集合。但是方法
Review::getLegacyScreenshots()
会将其更改为字符串数组


您可能正在使用更改跟踪策略(默认)。因此,当属性
Review::$screenshots
发生更改时,条令将尝试保持该更改,在需要实体的地方遇到字符串,因此抛出异常。

行号是什么?还是第1324行?您应该显示mapping ACCommonBundle:Review以及谢谢您的输入,我已经更新了我的问题谢谢Jasper,我不知道默认情况下条令会持久化实体,即使没有明确的$em->persist()。我已经将GetLegacyScreenshots()方法的内容粘贴到这个控制台脚本中,这是一种有点脏的方法,但在我的例子中做得很好。对不起,我创建了一个类型:默认的更改跟踪策略是DEFERRED_IMPLICIT(而不是DEFERRED_EXPLICIT)。我已经相应地编辑了我的答案。当使用默认的更改跟踪策略(DEFERRED\u IMPLICIT)时,您仍然必须对新(非托管)实体显式调用
$em->persist()
。但是,当您调用
$em->flush()
时,会自动检查从数据库(托管)中获取的实体的更改。后者会导致你的问题。
/**
 * 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;
    }
}