Ответ 1
Введение
Я думаю, что это в основном связано с тем, что вы работаете с Phar::TAR
файлами, потому что
file_put_contents("phar://./test.tar/foo.txt", "hello world");
^
|+---- Note this tar
Возвращает
Предупреждение: file_put_contents (phar://./test.tar/foo.txt): не удалось открыть поток: не удается создать phar './test.tar', расширение файла (или комбинацию) не распознано или каталог не существует
Пока
file_put_contents("phar://./test.phar/foo.txt", "hello world"); // Works file
^
|+---- Note This phar
Возвращает
//No Errors
Знать проблему
Если вы посмотрите на подробный пример в документе PHP, это была известная проблема для прошлого 2 years
и приведенный пример следующие
Пример
$p = new PharData(dirname(__FILE__) . '/phartest.zip', 0, 'phartest', Phar::ZIP);
$p->addFromString('testfile.txt', 'this is just some test text');
// This works
echo file_get_contents('phar://phartest.zip/testfile.txt');
// This Fails
file_put_contents('phar://phartest.zip/testfile.txt', 'Thist is text for testfile.txt');
$context = stream_context_create(array(
'phar' => array(
'compress' => Phar::ZIP
)
));
// This Fails
file_put_contents('phar://phartest.zip/testfile.txt', 'Thist is text for testfile.txt', 0, $context);
// This works but only with 'r' readonly mode.
$f = fopen('phar://C:\\Inetpub\\wwwroot\\PACT\\test\\phartest.zip\\testfile.txt', 'r');
Рабочая альтернатива
Не используйте .tar
или .zip
имеет свой файл extension
, но установите сжатие, как показано в PHP DOC
Что я имею в виду?
$context = stream_context_create(array(
'phar' => array(
'compress' => Phar::GZ //set compression
)
));
file_put_contents('phar://sample.phar/somefile.txt', "Sample Data", 0, $context);
^
|= Use phar not tar
Совет
Я действительно думаю, что вы должны придерживаться PharData
реализуемо и доказано, что оно работает. Единственный способ сделать
Я должен использовать file_put_contents
Затем напишите свою собственную обертку и зарегистрируйте ее с помощью stream_wrapper_register
, вот простой Prof of Concept
stream_wrapper_register("alixphar", "AlixPhar");
file_put_contents('alixphar://phar.tar/test/foo.txt', 'hey');
^
|+-- Write with alixphar
echo file_get_contents('alixphar://phar.tar/test/foo.txt'),PHP_EOL;
echo file_get_contents('phar://phar.tar/test/foo.txt'),PHP_EOL;
Выход
hey <----- alixphar
hey <----- phar
Примечание. Этот класс не должен использоваться в процессе производства... Это просто пример и не удалось выполнить некоторые тестовые примеры
class AlixPhar {
private $pos;
private $stream;
private $types;
private $dir;
private $pharContainer, $pharType, $pharFile, $pharDir = null;
private $fp;
function __construct() {
$this->types = array(
"tar" => Phar::TAR,
"zip" => Phar::ZIP,
"phar" => Phar::PHAR
);
// your phar dir to help avoid using path before the phar file
$this->dir = __DIR__;
}
private function parsePath($path) {
$url = parse_url($path);
$this->pharContainer = $url['host'];
$this->pharType = $this->types[pathinfo($this->pharContainer, PATHINFO_EXTENSION)];
if (strpos($url['path'], ".") !== false) {
list($this->pharDir, $this->pharFile, , ) = array_values(pathinfo($url['path']));
} else {
$this->pharDir = $url['path'];
}
}
public function stream_open($path, $mode, $options, &$opened_path) {
$this->parsePath($path);
$this->stream = new PharData($this->dir . "/" . $this->pharContainer, 0, null, $this->pharType);
if (! empty($this->pharDir))
$this->stream->addEmptyDir($this->pharDir);
if ($mode == "rb") {
$this->fp = fopen("phar://" . $this->pharContainer . "/" . $this->pharDir . "/" . $this->pharFile, $mode);
}
return true;
}
public function stream_write($data) {
$this->pos += strlen($data);
$this->stream->addFromString($this->pharDir . "/" . $this->pharFile, $data);
return $this->pos;
}
public function stream_read($count) {
return fread($this->fp, $count);
}
public function stream_tell() {
return ftell($this->fp);
}
public function stream_eof() {
return feof($this->fp);
}
public function stream_stat() {
return fstat($this->fp);
}
}