move_uploaded_file()要求参数2是有效路径,给定对象


move_uploaded_file() expects parameter 2 to be valid path, object given

我使用Symfony 2.3保存表单POST上传的文件。

这是我在控制器中使用的代码:

$fileDir = '/home2/divine/Symfony/src/App/Bundle/Resources/public/files';
$form['my_file']->getData()->move($fileDir, 'book.pdf');

在水下,Symfony执行以下代码来移动文件:

move_uploaded_file("/tmp/phpBM9kw8", "/home2/divine/Symfony/src/App/Bundle/Resources/public/files/book.pdf");

公共目录具有777个权限。

这是我得到的错误:

"Could not move the file "/tmp/phpBM9kw8" to "/home2/divine/Symfony/src/App/Bundle/Resources/public/files/book.pdf" 
(move_uploaded_file() expects parameter 2 to be valid path, object given)" 

我使用的是PHP 5.3。

更新:

这是执行move_uploaded_file()的代码片段:

// Class: Symfony'Component'HttpFoundation'File'UploadedFile
$target = $this->getTargetFile($directory, $name);
if (!@move_uploaded_file($this->getPathname(), $target)) {
// etc...

$target"变量在此处创建:

protected function getTargetFile($directory, $name = null) {
// Some error handling here...
    $target = $directory.DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name));
    return new File($target, false);
}

$target变量是一个File类。它确实有一个__toString()方法,继承自SplFileInfo:

/**
 * Returns the path to the file as a string
 * @link http://php.net/manual/en/splfileinfo.tostring.php
 * @return string the path to the file.
 * @since 5.1.2
 */
public function __toString () {}

但不知怎么的,__toString方法不起作用。

但不知何故,__toString方法在中不起作用

它是"神奇的方法"之一,当对象在字符串上下文中使用时,它会被自动调用——例如,如果您有'foo' . $object

但我不认为应该在这种情况下工作。因为PHP是松散类型的,所以可以将任何传递到move_uploaded_file中。此时不会自动转换为字符串。然后在内部,函数只检查参数是否是字符串,但不尝试将其转换为字符串——因为这没有什么意义,它可以是任何类型的对象,并且无法判断调用__toString是否会产生有效的文件路径。


你现在可能会想,为什么在错误消息中我们确实看到了路径:

无法将文件"/tmp/phpBM9kw8"移动到"/home2/神圣/Symfony/src/App/Bundle/Resources/public/files/book.pdf"

我的猜测是,当组装错误消息时,会进行字符串串联,因此__toString确实会在这个特定点被调用。


如果你愿意修改Symfony源代码,我认为这应该是一个简单的解决方案,如果你只更改这行

if (!@move_uploaded_file($this->getPathname(), $target)) {

if (!@move_uploaded_file($this->getPathname(), ''.$target)) {

–然后再次出现这样的情况,将调用__toString,因为对象通过将其与字符串(空字符串,因为我们不想篡改结果值)连接而转移到字符串上下文中。)


当然,直接修改框架的文件并不是最推荐的处理方式——在下一次更新之后,我们的更改可能会再次丢失。我建议您检查Symfony错误跟踪器(他们应该有类似的东西),看看这是否已经是一个已知的问题,以及是否存在官方补丁文件;否则将其报告为错误,以便在将来的版本中进行修复。