• Почему могут не отображаться Торговые предложения в списке товаров?

    @photosho Автор вопроса
    Проблема решена.

    =)
    Помимо прочего, нужно было установить параметр "PRODUCT_DISPLAY_MODE" (Схема отображения = Расширенный).
    Ответ написан
  • Почему font-face отказывается загружать шрифт с другого сайта?

    @photosho Автор вопроса
    Пропустил в консоли такое сообщение:

    "Запрос из постороннего источника заблокирован. Причина: отсутствует заголовок CORS «Access-Control-Allow-Origin»". Решилось добавлением следующего правила в .htaccess сайта, откуда берется шрифт:

    Header set Access-Control-Allow-Origin 'http:site2.ru'


    А "site2.ru" - соответственно, сайт, который этот шрифт пытается установить.
    Ответ написан
  • Почему не выводится список заказов в Личном кабинете?

    @photosho Автор вопроса
    Проблема решена. В файле "/catalog/controller/checkout/cartweb.php", в методе "save_cart" был закомментирован блок "if ($this->customer->isLogged()) {...}", в котором и устанавливалась эта переменная.
    Ответ написан
  • Не могу найти указанный ключ формы?

    @photosho Автор вопроса
    Всем спасибо за полезные советы. Проблема в итоге была в другом: форма подключена при помощи разметки, в обход ModX.
    Ответ написан
  • Как автоматически получить значение свойства Файл?

    @photosho Автор вопроса
    Можно автоматически обработать свойства в зависимости от типа:

    $props = $item->getProperties();
    
    foreach ($props as $key => $prop) {
        if ($prop['PROPERTY_TYPE'] == 'F')
            $result[$key] = CFile::getPath($prop['VALUE']);
    
        else $result[$key] = $prop['VALUE'];
    }
    Ответ написан
  • Как организовать отправку цели Я.Метрики при регистрации пользователя?

    @photosho Автор вопроса
    Решил задачу при помощи блокировки отправки формы кнопкой "submit" и отправки ее самостоятельно посредством ajax-запроса. Хотя, вариант из комментариев к вопросу кажется более жизнеспособным, если нужны именно "реальные" пользователи, подтверждающие свою учетную запись, а не отслеживание самого процесса регистрации. Зависит от задачи и того, что хотят от вас специалисты по рекламе.

    Опишу здесь свой вариант решения.

    1. "/template_name/components/bitrix/system.auth.registration/template_name/template.php"

    Здесь поставил на "submit button" событие onclick:

    onclick = "registerSubmit(event);"

    2. В основном файле скрипта (или в любом другом, загружающемся на странице):

    function registerSubmit(event) {
    	event.preventDefault();
    
    	var form = jQuery(event.target).closest('.registration-form');
    
    	if (form.length) {
    		form.find('[name="USER_EMAIL"]').val(form.find('[name="USER_LOGIN"]').val());
    
    		BX.ajax.post(
    			form.attr('data-ajax'),
    			form.serialize(),
    			function(result) {
    				var parent;
    
    				result = jQuery(result);
    
    				if (result.attr('id') == 'bx_incl_area_1') {
    					yaCounter52684615.reachGoal('LK');
    					location.href = '';
    				}
    				else {
    					/*
    						Обработка действий в случае неудачной попытки регистрации,
    						в этом случае в result приходит разметка формы с текстом ошибок.
    					*/
    				}
    			}
    		);
    	}
    
    	return false;
    }


    То же - и для авторизации, за исключением, что путь к шаблону компонента другой и некоторые изменения в самой функции. Некоторые действия, возможно, специфичны для конкретно моего решения и установленного шаблона - не знаю, какие изменения в шаблоны были внесены до меня. Эта строка:

    form.find('[name="USER_EMAIL"]').val(form.find('[name="USER_LOGIN"]').val());


    Заполняет невидимый input "USER_EMAIL" данными из input'а "USER_LOGIN" (туда пользователь, как ни странно, вводит свой email-адрес). Она может быть не нужна в стандартном (или любом другом) шаблоне.

    Но суть остается прежней: получаем форму-родителя кнопки "submit", на которую нажали, смотрим, чтобы все необходимые для регистрации поля были заполнены, сериализуем форму и посылаем post-запросом на требуемый адрес (у меня этот адрес был записан в "data-ajax"). Если все прошло успешно - перезагружаем страницу, а если нет - выполняем другие действия. Например, заменяем содержимое родителя формы тем, что пришло от сервера. Код в этой секции намеренно удалил, потому что он-то уж точно был специфичным.

    Для определения, прошло ли все успешно, смотрим, что возвращает сервер в обоих случаях, ищем различия между двумя результатами и так проверяем. У меня при успешной регистрации сервер возвращает пустой "div" с "id = bx_incl_area_1".
    Ответ написан
  • Как реализовать двухсоставное свойство инфоблока?

    @photosho Автор вопроса
    Комментарий Никита Ермиличев оказался полезен, но в данном вопросе помогла активация настройки "Выводить поле для описания значения" свойства инфоблока. Ссылка, таким образом, записывается в массив "DESCRIPTION" при считывании свойства.
    Ответ написан
  • Где в компоненте "bitrix:catalog.comments" задается шаблон комментария?

    @photosho Автор вопроса
    Проблема была нестандартная, может быть, кому-нибудь пригодится ее описание. На сайте производится смена шаблона, и основным шаблоном установлен старый, тогда как для конкретной страницы со списком комментариев установлен новый шаблон.

    Внутри "catalog.comments/template/ajax.php" есть строки, подключающие компонент, загружающий комментарии посредством ajax-запроса:

    $APPLICATION->IncludeComponent(
    			'bitrix:catalog.comments',
    			'',
    			$commParams,
    			null,
    			array('HIDE_ICONS' => 'Y')
    		);


    Здесь не указано имя шаблона. Пытался указать, передав тот шаблон компонента, с которым я его подключаю, но Bitrix выводит сообщение: "Cannot find template 'name' of page ''" - вот этот пустой параметр "page" меня смутил. Подозрения оказались верными: видимо, если параметр "page" (или что это) не установлен, то шаблон компонента ищется в папке с шаблоном сайта, установленным по умолчанию.

    Если в комментариях кто-нибудь подскажет, как избежать этого, не устанавливая новый шаблон по умолчанию, буду очень благодарен.
    Ответ написан
  • Почему некоторые заказы не помечаются как оплаченные?

    @photosho Автор вопроса
    Проблема была в том, что неверно задавалась стоимость заказа при его создании (заказ создавался вручную) - не учитывалось количество товара. В результате, значения полей "Сумма заказа" и "Оплата > Стоимость > Сумма к оплате" были разными.
    Ответ написан
  • Почему не меняется флаг оплаты после успешной оплаты заказа?

    @photosho Автор вопроса
    Вопрос решен установкой галочки "Автоматически оплачивать заказ при получении успешного статуса оплаты" в настройках обработчика платежной системы.
    Ответ написан
  • Почему не заполняется наименование контрагента при экспорте заказов из Bitrix?

    @photosho Автор вопроса
    Разобрался, следовало настроить Профили обмена: "Магазин > Настройки > Интеграция с 1С > Профили обмена".
    Ответ написан
  • Как реализовать такую связь в Laravel?

    @photosho Автор вопроса
    Пока сделал следующим образом. В модель "Film" добавил метод "getLinks":

    public function getLinks() {
    		$query = \DB::table('LINKS')->select('id_b')->where('id_a', '=', $this->id);
    		$query = \DB::table('LINKS')->select('id_a')->where('id_b', '=', $this->id)
    			->union($query);
    		$ids = $query->get();
    		$buf = [];
    		foreach ($ids as $id) {
    			array_push($buf, $id->id_a);
    		}
    		$links = Film::whereIn('id', $buf)->get();
    		$this->links = $links;
    		return $this;
    	}


    Так произвожу выбор из базы данных:

    $object = Film::find($id)->getLinks();

    В общем, все работает правильно, но идеи по упрощению кода (а главное, - по оптимизации) все еще принимаются.
    Ответ написан
  • Почему нет доступа к папке Sessions?

    @photosho Автор вопроса
    Проблема решена. Оказалось, что сайт сначала разрабатывался на одном компьютере, и потом был скопирован на другой, причем в файле "/bootstrap/cache/config.php" почему-то выводился путь к старой папке OpenServer'а: "D:\OpenServer" (в которой изначально создавался сайт), и по этой причине искомый файл не мог быть найден. Не знаю, что это за файл, но его удаление решило проблему.
    Ответ написан
  • Как передать в свою директиву Blade значение переменной?

    @photosho Автор вопроса
    Пока решил проблему следующим кодом:

    Blade::directive('date', function($expression) {
      return '<?php echo Carbon\Carbon::ФУНКЦИЯ(' . $expression . '); ?>'
    });


    То есть, добавляю путь к классу прямо перед выводом функции. Буду признателен за комментарии к данному способу - является ли он правильным/оптимальным и не принесет ли лишних проблем.
    Ответ написан
  • Как использовать расширение директив Blade в Laravel 5?

    @photosho Автор вопроса
    Вопрос решен. Проблема была, во-первых, в версии Laravel - насколько я понял, метод "directive" доступен только с версии 5.1 - обновление помогло. А, во-вторых, - в кешированных файлах на сервере. Очистка кеша (не путать с очисткой кеша в браузере) решила эту часть проблемы.
    Ответ написан
  • Почему метод getAttribute не записывает свойства класса?

    @photosho Автор вопроса
    Во всем разобрался. Почему-то думал, что "get*Attribute" вызывается после считывания значения поля из базы данных, но, на самом деле, эта функция вызывается при попытке считать значение поля из объекта ($post->user_id).

    Следовательно, в таком варианте:

    public function getUserIdAttribute($value) {
      $this->author['name'] = User::find($value)->username;
      $this->author['id'] = $value;
      return $value;
    }


    Если просто считать значение свойства $author, оно все еще не будет установлено, оно установится после вызова свойства $user_id ($post->user_id). Следовательно, проблема решается установкой функции преобразования для свойства $author:

    protected $author = [];
    
    public function getAuthorAttribute() {
    	$this->author['id'] = $this->user_id;
    	$this->author['name'] = User::find($this->author['id'], ['username'])->username;
    	return $this->author;
    }
    Ответ написан
  • Почему для сохранения сессии требуется перезагрузка страницы?

    @photosho Автор вопроса
    При каждом обновлении страницы создается 2 записи Cookie: "XSRF-TOKEN" и "laravel_session". При обычном AJAX-запросе на авторизацию больше Cookie не создается. При AJAX-запросе с последующим перенаправлением PHP-скрипта на любую страницу - в браузере появляется еще одна запись Cookie. Все записи привязаны к корневой директории сайта ("/").

    Притом, после такого запроса страница, с которой была произведена авторизация, получает ответ на свой POST-запрос с кодом "302" + какой-то удачный GET-запрос с того адреса, куда было произведено перенаправление PHP-скрипта.

    Не знаю, насколько это правильно, но из всего перечисленного делаю вывод, что финальное перенаправление PHP-скрипта нужно для обновление записи Cookie в браузере (каким образом - пока не знаю), а значит, и подтверждения авторизации. Без этой записи в Cokie пользователь не мог считаться авторизованным, и простая перезагрузка страницы в браузере, будто бы, "удаляла авторизацию". Почему пользователь при этом считался авторизованным в той же сессии - пока тоже не знаю, возможно, информация о нем как-то кешировалась в переменных на сервере.

    Решил проблему следующим образом. Так как после перенаправления PHP-скрипта на сервере открытой странице с формой авторизации возвращался GET-запрос, сделал вывод, что страница, на которую идет перенаправление, все еще связана с нашей AJAX-функцией. Поэтому перенаправление в PHP-скрипте поставил на страницу "/login/final/", где записал единственную строку:

    echo json_encode(['redirect' => 'update']);

    Как и предвидел: этот массив после выполнения скрипта возвратился браузеру, и по значению "update" параметра "redirect" браузер обновляет текущую страницу. Авторизация работает.

    Всем спасибо за помощь, совет "заглянуть в Cookie" направил меня по нужному пути.
    Ответ написан
  • Почему массив POST пустой?

    @photosho Автор вопроса
    Итак, проблема была в отсутствующем в запросе параметре "X-XSRF-TOKEN" (причем, именно так, а не "X-CSRF-TOKEN", как можно было подумать). Это одна. Вторая - в шифровании этого параметра, но ее до конца понять не удалось.

    С каждым POST-запросом этот параметр должен передаваться на сервер, поэтому, на jQuery будет такой код:

    jQuery.ajaxSetup({
        headers: {'X-XSRF-TOKEN': jQuery('meta[name="csrf-token"]').attr('content')}
    });


    Здесь мы получаем значение параметра "csrf-token" из мета-тегов страницы. А записываем их туда, например, в основном файле представления:

    <meta name="csrf-token" content="{{ csrf_token() }}"/>


    Но даже если все это сделать, сервер все равно будет умирать с сообщением "DecryptException". Информацию об этой проблеме нашел вот здесь. Правда, в итоге сделал вторым способом, так как в первом необходимость добавлять параметр каждому контроллеру показалась страшной.

    То есть, я открыл файл "app/Http/Middleware/VerifyCsrfToken.php" и добавил в него такой код:

    use Symfony\Component\Security\Core\Util\StringUtils;
    ...
    protected function tokensMatch($request) {
    	$token = $request->session()->token();
    	$header = $request->header('X-XSRF-TOKEN');
    	return StringUtils::equals($token, $request->input('_token')) ||
    		($header && StringUtils::equals($token, $header));
    }


    Функцию, конечно же, внутрь класса.

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