Laravel, Laravel Blade, исключение ошибки генерации, неопределенная переменная $helper, когда я нажимаю вторую ссылку навигации по домашней странице

Я провел рефакторинг своего кода, но даже в этом случае у меня все равно генерируется то же самое исключение ошибки. Я покажу старый код и рефакторинг. Я также приведу сообщение об ошибке, сгенерированное Laravel. в дополнение к коду спагетти, который я получил при устранении ошибки с помощью dd().

У меня есть свои собственные вспомогательные функции, которые я использую. Это класс, который вводится в контроллер домашней страницы в качестве зависимости. Моя вспомогательная функция затем передается в Laravel Blade как переменная с именем helper.

Цель состоит в том, чтобы мои навигационные ссылки изменили цвет на другой цвет, если это выбранная в данный момент и активная ссылка на эту страницу.

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

Я использовал dd() для устранения ошибки. В результате я получил вывод спагетти-кода.

Пример класса Utilities/Helper — моя пользовательская вспомогательная функция


/*
* Original
*/

<?php

namespace App\Utilities;

class Helper
{
  public static function activePage(string $pageUrl): string
  {
    $requestUri = $_SERVER['REQUEST_URI'];
    
    return $requestUri === $pageUrl ? "color=var(--sky)" : "color=var(--mud)";   
  }
}

/*
* Refactored
*/

<?php

namespace App\Utilities;

class Helper
{
  public static function activePage(string $pageUrl): string
  {    
    return Request::is($pageUri) ? "style=color:var(--sky)" : "style=color:var(--mud)";   
  }
}

Пример действия контроллера/домашнего экрана


<?php

namespace App\Http\Controllers;

use App\Http\Controllers\BaseController;
use App\Utilities\Helper;
use Illuminate\View\View;

class Home extends BaseController
{

  public function __construct(
   private Helper $helper,  
  ){}

  public function index(): View
  {
    return view('home', [
      'helper' => $this->helper::class,
    ]);
  }
}

Пример домашней страницы шаблона Laravel Blade


<!-- Original -->

<li class = "nav-links">        
  <a href = "{{ url('/') }}"         style = "{{ $helper::activePage('/') }}">Home</a>
  <a href = "{{ url('/services') }}" style = "{{ $helper::activePage('/services') }}">Services</a>
  <a href = "{{ url('/clients') }}"  style = "{{ $helper::activePage('/clients') }}">Clients</a>
  <a href = "{{ url('/about') }}"    style = "{{ $helper::activePage('/about') }}">About</a>
  <a href = "{{ url('/blog') }}"     style = "{{ $helper::activePage('/blog') }}">Blog</a>
  <a href = "{{ url('/contact') }}"  style = "{{ $helper::activePage('/contact') }}" class = "contact-link">Contact</a>
</li>

<!-- Refactored -->

<li class = "nav-links">        
  <a href = "{{ url('/') }}"         {{ $helper::activePage('/') }}>Home</a>
  <a href = "{{ url('/services') }}" {{ $helper::activePage('/services') }}>Services</a>
  <a href = "{{ url('/clients') }}"  {{ $helper::activePage('/clients') }}>Clients</a>
  <a href = "{{ url('/about') }}"    {{ $helper::activePage('/about') }}>About</a>
  <a href = "{{ url('/blog') }}"     {{ $helper::activePage('/blog') }}>Blog</a>
  <a href = "{{ url('/contact') }}"  {{ $helper::activePage('/contact') }} class = "contact-link">Contact</a>
</li>

<!-- Also tried: no error occurred, but was not able to get the color to change to var(--sky) on the second link -->

<li class = "nav-links">        
  <a href = "{{ url('/') }}" {{ Request::is('/') ? "style=color:var(--sky)" : "style=color:var(--mud)" }}>Home</a>
  <a href = "{{ url('/services') }}" {{ Request::is('/services') ? "style=color:var(--sky)" : "style=color:var(--mud)" }}>Services</a>
  <a href = "{{ url('/clients') }}">Clients</a>
  <a href = "{{ url('/about') }}">About</a>
  <a href = "{{ url('/blog') }}">Blog</a>
  <a href = "{{ url('/contact') }}" class = "contact-link">Contact</a>
</li>

Изображение исключения ошибки

Сообщение об ошибке Laravel

Код ошибки Laravel

Сгенерирован неформатированный код спагетти при использовании dd()


Sfdump = window.Sfdump || (function (doc) { doc.documentElement.classList.add('sf-js-enabled'); var rxEsc = /([.*+?^${}()|\[\]/\\])/g, idRx = /\bsf-dump-\d+-ref[012]\w+\b/, keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl', addEventListener = function (e, n, cb) { e.addEventListener(n, cb, false); }; if (!doc.addEventListener) { addEventListener = function (element, eventName, callback) { element.attachEvent('on' + eventName, function (e) { e.preventDefault = function () {e.returnValue = false;}; e.target = e.srcElement; callback(e); }); }; } function toggle(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; if (/\bsf-dump-compact\b/.test(oldClass)) { arrow = '▼'; newClass = 'sf-dump-expanded'; } else if (/\bsf-dump-expanded\b/.test(oldClass)) { arrow = '▶'; newClass = 'sf-dump-compact'; } else { return false; } if (doc.createEvent && s.dispatchEvent) { var event = doc.createEvent('Event'); event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false); s.dispatchEvent(event); } a.lastChild.innerHTML = arrow; s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); if (recursive) { try { a = s.querySelectorAll('.'+oldClass); for (s = 0; s < a.length; ++s) { if (-1 == a[s].className.indexOf(newClass)) { a[s].className = newClass; a[s].previousSibling.lastChild.innerHTML = arrow; } } } catch (e) { } } return true; }; function collapse(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className; if (/\bsf-dump-expanded\b/.test(oldClass)) { toggle(a, recursive); return true; } return false; }; function expand(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className; if (/\bsf-dump-compact\b/.test(oldClass)) { toggle(a, recursive); return true; } return false; }; function collapseAll(root) { var a = root.querySelector('a.sf-dump-toggle'); if (a) { collapse(a, true); expand(a); return true; } return false; } function reveal(node) { var previous, parents = []; while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) { parents.push(previous); } if (0 !== parents.length) { parents.forEach(function (parent) { expand(parent); }); return true; } return false; } function highlight(root, activeNode, nodes) { resetHighlightedNodes(root); Array.from(nodes||[]).forEach(function (node) { if (!/\bsf-dump-highlight\b/.test(node.className)) { node.className = node.className + ' sf-dump-highlight'; } }); if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) { activeNode.className = activeNode.className + ' sf-dump-highlight-active'; } } function resetHighlightedNodes(root) { Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) { strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, ''); strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); }); } return function (root, x) { root = doc.getElementById(root); var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'), options = {"maxDepth":1,"maxStringLength":160,"fileLinkFormat":false}, elt = root.getElementsByTagName('A'), len = elt.length, i = 0, s, h, t = []; while (i < len) t.push(elt[i++]); for (i in x) { options[i] = x[i]; } function a(e, f) { addEventListener(root, e, function (e, n) { if ('A' == e.target.tagName) { f(e.target, e); } else if ('A' == e.target.parentNode.tagName) { f(e.target.parentNode, e); } else { n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target; if ((n = n.nextElementSibling) && 'A' == n.tagName) { if (!/\bsf-dump-toggle\b/.test(n.className)) { n = n.nextElementSibling || n; } f(n, e, true); } } }); }; function isCtrlKey(e) { return e.ctrlKey || e.metaKey; } function xpathString(str) { var parts = str.match(/[^'"]+|['"]/g).map(function (part) { if ("'" == part) { return '"\'"'; } if ('"' == part) { return "'\"'"; } return "'" + part + "'"; }); return "concat(" + parts.join(",") + ", '')"; } function xpathHasClass(className) { return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')"; } a('mouseover', function (a, e, c) { if (c) { e.target.style.cursor = "pointer"; } }); a('click', function (a, e, c) { if (/\bsf-dump-toggle\b/.test(a.className)) { e.preventDefault(); if (!toggle(a, isCtrlKey(e))) { var r = doc.getElementById(a.getAttribute('href').slice(1)), s = r.previousSibling, f = r.parentNode, t = a.parentNode; t.replaceChild(r, a); f.replaceChild(a, s); t.insertBefore(s, r); f = f.firstChild.nodeValue.match(indentRx); t = t.firstChild.nodeValue.match(indentRx); if (f && t && f[0] !== t[0]) { r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]); } if (/\bsf-dump-compact\b/.test(r.className)) { toggle(s, isCtrlKey(e)); } } if (c) { } else if (doc.getSelection) { try { doc.getSelection().removeAllRanges(); } catch (e) { doc.getSelection().empty(); } } else { doc.selection.empty(); } } else if (/\bsf-dump-str-toggle\b/.test(a.className)) { e.preventDefault(); e = a.parentNode.parentNode; e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className); } }); elt = root.getElementsByTagName('SAMP'); len = elt.length; i = 0; while (i < len) t.push(elt[i++]); len = t.length; for (i = 0; i < len; ++i) { elt = t[i]; if ('SAMP' == elt.tagName) { a = elt.previousSibling || {}; if ('A' != a.tagName) { a = doc.createElement('A'); a.className = 'sf-dump-ref'; elt.parentNode.insertBefore(a, elt); } else { a.innerHTML += ' '; } a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children'; a.innerHTML += elt.className == 'sf-dump-compact' ? '▶' : '▼'; a.className += ' sf-dump-toggle'; x = 1; if ('sf-dump' != elt.parentNode.className) { x += elt.parentNode.getAttribute('data-depth')/1; } } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) { a = a.slice(1); elt.className += ' sf-dump-hover'; elt.className += ' '+a; if (/[\[{]$/.test(elt.previousSibling.nodeValue)) { a = a != elt.nextSibling.id && doc.getElementById(a); try { s = a.nextSibling; elt.appendChild(a); s.parentNode.insertBefore(a, s); if (/^[@#]/.test(elt.innerHTML)) { elt.innerHTML += ' ▶'; } else { elt.innerHTML = '▶'; elt.className = 'sf-dump-ref'; } elt.className += ' sf-dump-toggle'; } catch (e) { if ('&' == elt.innerHTML.charAt(0)) { elt.innerHTML = '…'; elt.className = 'sf-dump-ref'; } } } } } if (doc.evaluate && Array.from && root.children.length > 1) { root.setAttribute('tabindex', 0); SearchState = function () { this.nodes = []; this.idx = 0; }; SearchState.prototype = { next: function () { if (this.isEmpty()) { return this.current(); } this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0; return this.current(); }, previous: function () { if (this.isEmpty()) { return this.current(); } this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1); return this.current(); }, isEmpty: function () { return 0 === this.count(); }, current: function () { if (this.isEmpty()) { return null; } return this.nodes[this.idx]; }, reset: function () { this.nodes = []; this.idx = 0; }, count: function () { return this.nodes.length; }, }; function showCurrent(state) { var currentNode = state.current(), currentRect, searchRect; if (currentNode) { reveal(currentNode); highlight(root, currentNode, state.nodes); if ('scrollIntoView' in currentNode) { currentNode.scrollIntoView(true); currentRect = currentNode.getBoundingClientRect(); searchRect = search.getBoundingClientRect(); if (currentRect.top < (searchRect.top + searchRect.height)) { window.scrollBy(0, -(searchRect.top + searchRect.height + 5)); } } } counter.textContent = (state.isEmpty() ? 0 : state.idx + 1) + ' of ' + state.count(); } var search = doc.createElement('div'); search.className = 'sf-dump-search-wrapper sf-dump-search-hidden'; search.innerHTML = ' 
 0 of 0</span>

Есть ли, по вашему мнению, после прочтения кода что-либо, что может привести к возникновению ошибки?

Этот вопрос похож на: Как получить текущий URL-адрес внутри оператора @if (Blade) в Laravel 4?. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.

OMi Shah 21.07.2024 07:13

В вспомогательном классе «Helper» добавьте dd($requestUri); перед возвратом в статический метод «activePage», чтобы отладить то, что происходит с вашим пользовательским вспомогательным классом.

INDIAN2020 21.07.2024 10:58

В вашем public function index() это return не reutrn, 2-й в 'helper' => $this->helper::class,, удалите ::class

Mr. Kenneth 22.07.2024 03:14

Предполагается, что переполнение стека — это место, куда вы можете обратиться, если у вас есть вопросы или проблемы по программированию, на которые вам нужны ответы… но я испытываю отрицательные голоса и негатив… это платформа, которая помогает людям, или платформа, которая унижает людей?… только что это такое…

Mr. Daniels 22.07.2024 09:13

@Mr.Daniels Голосование «вниз» означает, что вопрос недостаточно хорошо изучен, а также то, что еще говорит подсказка для стрелки вниз. Они не предназначены для того, чтобы быть негативными, но указывают на то, что вопрос можно улучшить. Это четко описано в справочном центре: stackoverflow.com/help/why-vote

Daedalus 23.07.2024 01:00

@Daedalus Вопрос к вам: вы сделали что-нибудь, чтобы помочь коллеге-программисту решить вопрос или проблему, которая у него возникла… или вы использовали свое время только для того, чтобы критиковать? И из-за этого, как вы думаете, это побудит людей захотеть использовать эту платформу, когда у них возникнут вопросы, или пойти куда-нибудь еще, потому что основные пользователи этой платформы несут ответственность за создание токсичной среды для других пользователей? Другими словами, я рассматриваю этот опыт как токсичную среду, которую вы и другие участники этой платформы создаете. Stack Overflow не был создан для того, чтобы критиковать людей только потому, что у них есть вопросы.

Mr. Daniels 23.07.2024 17:57

@Daedalus Потратьте некоторое время, чтобы просмотреть мой пост и показать, что вы действительно хотите помочь пользователям на этой платформе. Я нашел время, чтобы предоставить подробную информацию и объяснения. Прошло уже больше 2 дней, вместо того, чтобы избивать людей... где помощь?

Mr. Daniels 23.07.2024 18:12

@Mr.Daniels Никаких избиений не произошло. Голосование против не является критикой; они являются показателем качества. Я не критиковал ваш пост или вас, я попытался помочь вам понять, как работает платформа. Если вы хотите, чтобы я раскритиковал ваш пост, то он недостаточно хорошо изучен, поскольку статическое свойство ::class Magic возвращает строку, а не экземпляр класса. Люди пытались помочь вам; они уже указали на недоразумение ::class и предложили отладку. Кто-то даже дал ответ, каким бы неверным он ни был. Никто вас не оскорбил и никто не был злым.

Daedalus 23.07.2024 20:52

@Mr.Daniels Во-вторых, где вы определили свой класс в сервисном контейнере? Я вижу, что класс определен, но не зарегистрирован. Наконец, считали ли вы, что возвращаете не представление от контроллера, а ответ? Хотя я использую laravel в течение довольно долгого времени, я никогда не указываю возврат как представление, а как объект ответа, поэтому у меня недостаточно опыта в этом отношении, чтобы сказать, изменит ли ваше ограничение возврата поведение или нет. .

Daedalus 23.07.2024 20:53

@Daedalus Вы правы насчет ::class. Согласно документации PHP, ::class возвращает полное пространство имен в виде строки. Вы правы в отношении того, что мой класс не зарегистрирован в сервисном контейнере Laravel. Документация Laravel предоставляет несколько способов визуализации представления. Представление может передаваться через маршрутизатор без необходимости использования контроллера. В документации Laravel также указано, что один из их самых простых контроллеров возвращает представление. Это означает, что Laravel не очень самоуверен в этом отношении. Вы можете вернуть ответ или просмотр, я еще не изучил последствия этого.

Mr. Daniels 23.07.2024 22:35

@Daedalus После того, как я внесу предложенные вами изменения, и ошибки больше не будет… Я опубликую решение в этой теме.

Mr. Daniels 23.07.2024 22:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
3
11
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы никогда не используете $_SERVER в Laravel.

Прочтите всю страницу документации. Это часть стандартной функциональности Laravel.

<a href = "{{ url('/') }}" style = "@if (request()->is('/'))
 ... 
@else 
 ...
@endif">Home</a>

Для изучения Laravel рекомендуется начать с использования Breeze.

https://github.com/laravel/breeze/blob/2.x/stubs/default/resources/views/comComponents/nav-link.blade.php

https://github.com/laravel/breeze/blob/2.x/stubs/default/resources/views/layouts/navigation.blade.php

<x-nav-link :href = "route('dashboard')" :active = "request()->routeIs('dashboard')">
    {{ __('Dashboard') }}
</x-nav-link>

В настоящее время распространенный способ использования Laravel — использование компонента Blade.

Я использую специальные вспомогательные функции для своего проекта. Мои помощники будут использоваться для взаимодействия с интерфейсом Laravel Blades. Я придерживаюсь Vite и Laravel Blade. Я не использую компоненты. Вам нужно найти лучший способ помочь людям понять, о чем вы говорите... ваши примеры совсем не помогли.

Mr. Daniels 21.07.2024 07:23
Ответ принят как подходящий

Решение проблемы с ошибкой неопределенной переменной Laravel. Чтобы это было очень просто. Каждый контроллер отображает представление. Итак, если вы работаете над навигационными ссылками на домашней странице, и каждый контроллер отображает представление для каждой из этих ссылок. Вы получите исключение ошибки, если попытаетесь отобразить переменную в других ссылках и упустите тот факт, что вы сначала не передали переменную через другие контроллеры. Ниже я приведу примеры кода.

Вспомогательная функция/зависимость


class helper
{
  public static function pleaseHelp(string $param): string
  {
    return // your code
  }
}

Контроллеры


namespace App\Controllers;

use App\Utilities\Helper;

// The variable 'set' works on the rendered home page and the home nav link.
// It will not work on the other nav links without causing the Error Exception.
 
class Home
{
  public function __construct(
    private Helper $pleaseHelp,
  ){}
  
  public function index(): View
  {
    return view('home', [
      'set' => $this->pleaseHelp,
    ]);
  }
}

// In order to get your nav links working on the other pages, you'll need
// to inject your Helper Dependency into your other controller class.
  
class About
{
  // Helper Dependency here...

  return view('about', [
    'set' => $this->pleaseHelp,
  ]);
}

class Contact
{
  // Helper Dependency here too...

  return view('contact', [
    'set' => $this->pleaseHelp,
  ]);
}

Ларавел Блейд/html


// Link about & contact can now read the variable $set and load the page without error
<nav>
  <a href = "{{ url('/') }}" class = "{{ $set::pleaseHelp('/') }}">Home</a>
  <a href = "{{ url('about') }}" class = "{{ $set::pleaseHelp('about') }}">About</a>
  <a href = "{{ url('contact') }}" class = "{{ $set::pleaseHelp('contact') }}">Contact</a>
</nav>

А как насчет регистрации вашего помощника в сервисном контейнере?

Daedalus 26.07.2024 01:23

@Daedalus Что мне показалось интересным, так это то, что после нескольких тестов я проверил, нужен ли сервисный контейнер. Оказывается, в этом случае сервисный контейнер не требуется. Я могу без проблем использовать свою зависимость от помощника. Моя теория заключается в том, что, зная, что каталог приложений уже загружен, ваши пользовательские классы могут быть зарегистрированы косвенно. только не цитируйте меня по этому поводу.

Mr. Daniels 26.07.2024 05:11

Другие вопросы по теме