phplaravellaravel-bladevite

Laravel, Laravel Blade, Generation Error Exception Undefined Variable $helper when I click the home page navigations second link


I refactored my code, even so, I'm still generated the same Error Exception. I will show the old code and the refactored code. I'll also provided the error message generated by Laravel. in addition to the spaghetti code I received when troubleshooting the error with dd().

I have my own custom made helper functions that I'm using. It's a class and is injected into the home page Controller as a dependency. My helper function is then passed to Laravel Blade as a variable named helper.

The goal is to have my navigation links change to a different color if it is the currently selected and active link to that page.

When I apply the $helper variable to the first link, I get my desired result. However, the $helper variable generates the Undefined Variable $helper Error Exception on all the other links.

I used dd() to troubleshoot the error. I received a output of spaghetti code as a result.

Utilities/Helper class example - my custom helper function


/*
* 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)";   
  }
}

Controller/Home Action example


<?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 Template home page example


<!-- 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>

Image of Error Exception

Laravel Error Message

Laravel Error Code

Generated unformatted spaghetti code when using 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>

After reading the code, is there anything you think would cause an error to occur?


Solution

  • The Solution to Laravel Undefined Variable Error Exception. To keep it very simple. Each controller renders a view. So if you're working on the home page nav links and each controller renders a view for each of those links. You'll receive an Error Exception if you try to echo a variable on the other links and missing the fact that you didn't passed the variable through your other controllers first. I'll provide code examples below.

    Helper Function / Dependency

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

    Controllers

    
    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,
      ]);
    }
    
    

    Laravel Blade / 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>