Неверное имя файла шрифта (imagettfbox)

Этот вопрос задавали снова и снова, но я не мог найти правильный ответ на свою проблему... В качестве небольшого примечания: весь код работал отлично, прежде чем мы переместили файл класса из /application/lib/class в /library. /сорт ...

Я пытался играть с GDFONTPATH, относительными, абсолютными путями с расширением файла и без него, но безрезультатно. Вот некоторые из линий, которые мы пробовали до сих пор:

putenv('GDFONTPATH=' . realpath(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'fonts'));
/*1*/  $FontName = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.basename($FontName,'.ttf');
/*2*/  $FontName = '\pChart\fonts\\'.basename($FontName);
/*3*/  $FontName =basename($FontName);
$coords = imagettfbbox($FontSize, 0, $FontName, $Text);

Несколько комбинаций этих попыток также были использованы безрезультатно. Меня очень раздражает эта проблема, поскольку #1, когда echo'ed дает полный путь, который открывает правильный файл шрифта, если скопировать/вставить в проводнике Win.

Это может помочь узнать абсолютный путь к файлу с ошибкой и путь к имени шрифта...

C:\wamp\www\application_bundle\Library\pChart\class\pImage.class.php
C:\wamp\www\application_bundle\Library\pChart\fonts\arialuni.ttf

Мы сталкиваемся с этой проблемой на всех платформах разработки (Win, Mac и Linux) PHP 5.3.13.

Спасибо за помощь.

Изменить: кажется, что файл не найден / сервер не ищет нужную папку ... Если бы кто-то мог помочь устранить проблему, указав, как выяснить, какой путь пытается открыть GD, это действительно помогло бы.


person Salketer    schedule 05.07.2013    source источник
comment
Вы пробовали косую черту, верно? PHP в Windows понимает и то, и другое, но что-то глубоко в GD может и не понимать.   -  person Charles    schedule 06.07.2013
comment
Я не думал, что это будет иметь значение ... Я пробовал, но безрезультатно.   -  person Salketer    schedule 08.07.2013
comment
Сегодня мы попытались использовать другой шрифт, обновить файлы библиотеки и до сих пор никаких изменений.   -  person Salketer    schedule 08.07.2013
comment
@Salketer Вы проверили, имеет ли шрифт правильные разрешения, то есть gd разрешено его читать?   -  person Leri    schedule 08.07.2013
comment
@PLB спасибо за вашу мысль, но да, мы думали об этом.   -  person Salketer    schedule 08.07.2013
comment
@Salketer Очень сложно (боюсь, даже невозможно) решить эту проблему, потому что мы не можем воспроизвести ошибку, но я могу сказать, что бы я сделал в этой ситуации. На вашем месте я бы сел и записал каждую мелочь (даже если вы думаете, что это не связано с проблемой), которая изменилась с рабочей версии, а затем проанализировал бы шаг за шагом.   -  person Leri    schedule 08.07.2013


Ответы (4)


Мы придумали, как заставить его работать.

Короче говоря, мы включали файл класса, а затем вызывали методы для записи текста. Мы делали что-то вроде этого:

$classPath = 'pChart/';
include($classPath.'/class/pImage.class.php');
//... inside the pImage.class we passed font like this: $FontName = $classPath.'/fonts/arialuni.ttf';
imagettfbbox($FontSize, 0, $FontName, $Text)

Что бы мы ни делали до или после, это не работало... Пока мы не изменили $classPath на

$classpath = '../library/pChart/';

Обратите внимание, что они (или должны) указывать точно на ту же папку, что и код, выполняемый из файла в корне библиотеки.

Мы пытались выяснить, почему абсолютные пути не работали, но не смогли воспроизвести ошибку в изолированной среде, так что с нашей архитектурой что-то не так.

Спасибо за ваше время всем.

person Salketer    schedule 08.07.2013

Я знаю, что на это ответили и приняли, но я не видел, чтобы кто-нибудь вмешивался в то, почему это решение сработало и что изначально было неправильным.

Краткое описание проблемы

Текущий рабочий каталог устанавливается в момент, когда php получает запрос, и все относительные пути разрешаются на основе текущего рабочего каталога, а не каталога файла, на который ссылается путь.

Подробное описание проблемы

Относительные пути в php разрешаются на основе текущего рабочего каталога.

В целях тестирования вы всегда можете увидеть текущий рабочий каталог, вызвав getcwd.

Это значение изначально получено в HTTP-запросе как каталог, содержащий файл, который веб-сервер изначально передал запрос в php.

Так, например, если вы перейдете на http://www.mydomain.com/index.php, текущий рабочий каталог будет таким же, как корень документа ($_SERVER["DOCUMENT_ROOT"])

Для запроса CLI cwd — это каталог, в котором вы находитесь, когда выполняете команду. Итак, если я нахожусь в /home/orangepill и запускаю /usr/bin/php /path/to/file.php, cwd будет /home/orangepill.

Это вызывает проблему для относительных ссылок на файлы во включенных файлах.

Возьмем этот пример.

  1. Клиент переходит на www.mydomain.com

  2. Apache имеет index.php, установленный в директиве DirectoryIndex, и apache находит файл index.php в корне документа. Текущий рабочий каталог установлен в корень документа.

  3. /index.php содержит строку include "library/myclass.php"; $_SERVER["DOCUMENT_ROOT"]."/library/myclass.php" существует и все хорошо

  4. myclass.php содержит строку include("myclass_helper.php");, которая разрешается в $_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php". (помните, что относительные ссылки разрешаются относительно текущего рабочего каталога)

  5. $_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php" не существует на самом деле в $_SERVER["DOCUMENT_ROOT"]."/library/myclass_helper.php"

Вы, вероятно, что-то, но подождите ... Я испытал различное поведение в своих сценариях при включении в включение. Причина этого в том, что языковые конструкции include и require (наряду с парой других команд файловой системы) пытаются включить относительные пути из каждого из путей, указанных в директиве include path php. Таким образом, в приведенном выше примере, если каталог библиотеки вне корня документа существует в путях включения, тогда все будет работать так, как ожидалось.

Полное решение для запроса файлов относительно текущего файла состоит в том, чтобы структурировать пути включения с помощью контекстной константы __DIR__. Таким образом, вы должны использовать include __DIR__."/myclass_helper.php"; (include dirname(__FILE__)."/myclass_helper.php в средах до PHP 5.3), и во время выполнения это эффективно преобразует ваш относительный путь в абсолютный путь на основе местоположения файла, выполняющего включение.

Для общих включаемых каталогов у меня есть привычка указывать несколько часто используемых местоположений для использования с относительными ссылками файловой системы. Например

define ("APPLICATION_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/application");
define ("LIBRARY_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/library");
define ("CONFIG_PATH", APPLICATION_PATH."/etc/";

Это дает вам много опорных точек для включения путей относительно них.

person Orangepill    schedule 13.07.2013
comment
Спасибо за ваш ответ. Это заслуживает некоторого внимания. Но здесь проблема не должна быть такой же, как описано... Включение файла относительно включаемого пути работает. Файл pChart был правильно включен, используя только «pChart/», поскольку он находится в библиотеке, но шрифт можно было бы найти, только если мы включили файл, используя «../library/pChart». Если я все еще что-то упустил, это не имело для нас смысла. - person Salketer; 15.07.2013
comment
Это указывало бы на то, что текущий рабочий путь был каталогом, имеющим общий родитель с каталогом библиотеки. Где находится путь к файлу php, который первым обработал запрос apache. - person Orangepill; 15.07.2013
comment
index.php, который получил запрос, должен был получить этот путь от родителя библиотеки: ./app1/www/ - person Salketer; 15.07.2013

Вы сбросили $FontName перед этим фрагментом кода, чтобы отладить его значение?

В любом случае, если вы уже установили GDFONTPATH, вам не нужно использовать какой-либо путь к $FontName, в этом случае вы можете просто использовать имя шрифта (arialuni.ttf или даже просто arialuni ) или максимум basename() функции, как в примере №3.

Ваш putenv() вызов может быть просто putenv('GDFONTPATH=' . realpath('../fonts')).

Попробуйте это, чтобы увидеть, работает ли это:

putenv('GDFONTPATH=' . realpath('../fonts'));
$FontName = 'arialuni.ttf'; // note that I'm using font name directly
$coords = imagettfbbox($FontSize, 0, $FontName, $Text); 

Обновление 1

Пожалуйста, скиньте свой GDFONTPATH и скажите, что он печатает. Добавьте, что после вашего вызова putenv() ваш код выдаст ошибку с искомым GDFONTPATH:

 trigger_error(sprint('GDFONTHPATH = %s', getenv('GDFONTPATH')), E_USER_ERROR);
person Paulo Freitas    schedule 05.07.2013
comment
Спасибо за ответ, к сожалению не помогло :( - person Salketer; 08.07.2013
comment
Пожалуйста, прочитайте мое обновление ответа, позвольте мне попытаться понять, что происходит. :) - person Paulo Freitas; 08.07.2013

Можно также просто попытаться указать ссылку относительно корневого каталога. У меня была такая же проблема («Недопустимое имя шрифта файла», функция «...»), и я исправил ее так же в основном файле, где инициализируется pChart:

$myPicture->setFontProperties(array("FontName"=>$_SERVER['DOCUMENT_ROOT']."/files/lib/pChart/fonts/verdana.ttf"));

Решил проблему для меня. Эта строка ИСПОЛЬЗУЕТСЯ быть такой:

$myPicture->setFontProperties(array("FontName"=>"fonts/verdana.ttf"));

который - я не знаю почему - спровоцировал сегодня ошибку.


Обратите внимание, что это решение не очень элегантно, поскольку оно основано на том факте, что ваша папка pChart на самом деле находится где-то вроде

http://myHomepage.com/files/lib

, что означает, что он не работает с относительными каталогами.

person phil294    schedule 23.09.2014