Как программно привязать файл к ноде.

Главные вкладки

Аватар пользователя viktorbeznosov viktorbeznosov 10 марта 2020 в 10:59

Друзья, есть проблема.

У меня есть робот, который программно создает ноду.
Проблема заключается в том, что я не могу привязать к ноде файл.
Файл лежит в папке /sites/default/files/drivers

Я создаю сущность типа файл, что бы потом передать ноде fid файла

$drivers_directory = $_SERVER['DOCUMENT_ROOT'] . "/rossila_av/sites/default/files/drivers/";
$file_name = '0KPP9_12-12-2019.exe';
$file_path = drupal_realpath($drivers_directory . $file_name);

$file = (object) array(
'uid' => 1,
'uri' => $file_path,
'filemime' => file_get_mimetype($file_path),
'status' => 1,
);

$file_obj = file_copy($file, 'public://drivers');

Почему файл создается функцией $file_obj = file_copy($file, 'public://drivers');
только когда робот находится в корне сайта???

Проблема в том, что $file_obj возвращается false.
Дело в том, что робот находится в папке driverbot и когда я проверяю, что такое 'public://drivers' функцией file_create_url('public://drivers/') - Она возвращает мне http://server2.webisgroup.ru/rossila_av/driverbot/sites/default/files/dr..., в то время, когда папка с файлом лежит уровнем выше в
http://server2.webisgroup.ru/rossila_av/sites/default/files/drivers

Что мне с этим делать??
Есть какие-то функции, создающие сущность типа файл, не использующие конструкцию 'public://drivers'?

Комментарии

Аватар пользователя sergey2812 sergey2812 10 марта 2020 в 14:18

Виктор, приветствую!

Я когда-то сделал модуль по автоматизации импорта товаров от оптовика в свою БД, и в нем есть фрагмент добавления файла изображения в ноду товара. То есть, не важно, что у меня был файл с изображением - все равно ведь файл, и процесс тот же самый - связывания файла с нодой.
Но дело было давно, и я всех деталей уже не вспомню, но дам ответ по двум направлениям, как помню:
1. по твоему коду,
2. приведу пример своего кода
Может быть поможет тебе разобраться в твоей проблеме.

И так по п.1 - по твоему коду:

у тебя - $file_obj = file_copy($file, 'public://drivers');

Я бы внес некоторые изменения, добавил бы слэш, так как пишем в каталог, и разделитель именно слэш, и имя файла:

$file_obj = file_copy($file, 'public://drivers/' . $file_name, FILE_EXISTS_REPLACE);

Это во-первых, а во-вторых: в твоем коде не вижу части кода по передаче в ноду fid файла. А это и есть окончательная стадия всего процесса.

Поэтому переходим к п. 2 к моему варианту из моего модуля.
Например, если нода только создается, то применяем функцию Drupal для подготовки ноды:

// Создаем новую ноду
$node = new stdClass();
$node = (object)array('type' => 'product_viktoria_display'); //мой тип ноды
node_object_prepare($node);
$node->title = $product_name;
....... и т.д. это начальные действия по вписыванию нужных данных в ноду, а дальше, когда дело доходит до передачи в ноду fid файла, то я делал так:
$file = file_save_data($picture, 'public://' . $file_name, FILE_EXISTS_REPLACE); // сохраняем изображение - это очень похоже на твой вариант, только функция другая..
if ($file) //если файл успешно сохранен, то
{
// Добавляем файл изображения к ноде
$node->field_image_product[LANGUAGE_NONE][]['delta'] = $j; // порядок файлов в БД
$node->field_image_product[LANGUAGE_NONE][]['fid'] = $file->fid; // id файла
$node->field_image_product[LANGUAGE_NONE][]['width'] = $width; // ширина картинки
$node->field_image_product[LANGUAGE_NONE][]['height'] = $height; // высота картинки
}
// теперь уже сохраняем ноду с привязанным к ней файлом.
node_save($node);

Если нода уже существует, то надо сначала ее загрузить функцией node_load, записать в нее fid файла, и снова сохранить node_save.

Это все. Удачи!
Сергей.

Аватар пользователя OldWarrior OldWarrior 10 марта 2020 в 14:20

viktorbeznosov wrote:
...Почему файл создается функцией $file_obj = file_copy($file, 'public://drivers');
только когда робот находится в корне сайта???...

Потому что константа Друпала DRUPAL_ROOT (которая используется внутренними функциями Drupal API) определяется в index.php как:

define('DRUPAL_ROOT', getcwd());

Т.е. getcwd() (i.e. Get Curent Work Directory) указывает на рабочую директорию, в которой был выполнен первый PHP-скрипт (в вашем случае это "DOCUMENT_ROOT/rossila_av/driverbot" ). Начнём с того, что ваш робот должен быть технически "оформлен" как модуль Друпала, а не запускаться из папки в корне.

Если же вы запускаете его из корня, то вам просто "крупно везёт" что рабочая директория скрипта совпадает с местонахождением друпаловского index.php (который первым открывается при любом запросе к страницам Друпала) и вы не наблюдаете ошибку.

Если нет, то stream wrapper (используемый в функции file_copy в качестве второго параметра), будет включать в себя путь до папки с вашим роботом.

Возможно, в качестве очень костыльного решения можно попробовать file_save() вместо file_copy(), но тогда стоит убедиться, что объект $file имеет все необходимые поля.

Аватар пользователя charOFF charOFF 10 марта 2020 в 14:41

А что если сделать chdir перед подключением друпала?

<?php
chdir
($_SERVER['DOCUMENT_ROOT'] . "/rossila_av");
define('DRUPAL_ROOT'getcwd());
require_once 
'./includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
?>
Аватар пользователя OldWarrior OldWarrior 10 марта 2020 в 14:51

Кстати - да, можно попробовать.
Лишь бы при этом не отвалились какие-то другие функции этого робота для манипуляции с файлами (ну, мало ли, вдруг там пути относительно текущей рабочей папки - мы же всего скрипта не видим).

Аватар пользователя viktorbeznosov viktorbeznosov 11 марта 2020 в 10:57

Вооооооот!!! Оно самое:))))
Сам бы точно не додумался. 3 дня уже бьюсь головой в монитор!!
Спасибо!!

P.S. Как же я люблю Drupal)))