bhuether's avatar

Accessing Model Data in Blade - Or Better Way?

This is related to my previous post about accessing item parameters in a view. I am trying to figure out how to have a view perform some logic in order to apply a style to a menu item. On the page in question there is a guitar lesson being displayed and on the left a menu of lesson categories. I want the category of the lesson to be highlighted. I just am not sure the laravel approach for this. If someone could point me to some examples, that would be great! thanks!

0 likes
3 replies
al0mie's avatar

You can add to model some kind of slug for categories or use it name and after inject to your view some menu manager which will handle activity or anything else of your category item. Example for active class In your template

<li{!! $menuManager->getActivity($category, ' class="active"') !!}>
    <a href="{!! route('category', $category->slug) !!}">{!! category->name !!} </a>
</li>

And in the menu manager

public function getActivity($category, $parameter)
{
    //check current url how as you want. It just extra simple example.
    $url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
    if (strpos($url, $category->slug) !== false) {
        return $parameter;
    } 
}

It's just example how you can do it. Also you can check it directly in views.

Cronix's avatar

retrieve the lesson with the category name/id/whatever. Then in your menu view, add some css class if the menu item category is the same as the lesson->category.

bhuether's avatar

The url does not have the category.

I am trying to reverse engineer how the menu view is passed data. The menu view is

@foreach ($categories as $category)
    <?php $category = $category->present(); ?>

    @if ($category->parent == null)
        <li><a href="{{ $category->url }}">{{ $category->title }}</a></li>

        @foreach ($category->children as $child)
            <?php $child = $child->present() ?>
            <li class="level1"><a href="{{ $child->url }}">{{ $child->title }}</a></li>

            <?php
                /*
                @foreach ($child->children as $grandChild)
                    <?php $grandChild = $grandChild->present() ?>
                    <li class="level2"><a href="{{ $grandChild->url }}">{{ $grandChild->title }}</a></li>
                @endforeach
                */
            ?>

        @endforeach

    @endif

@endforeach

So then I figured I should find where it is being passes $categories, and pass it the category of the current exercise or lesson.

There is no menu controller, but a menu composer:

<?php

namespace App\Http\Composers;

use Illuminate\Contracts\View\View;
use Cache;

class MenuComposer
{
    public function compose(View $view)
    {
        $minutes = 6 * 60;
        $value = Cache::remember('menu-categories', $minutes, function() {
            return \App\Category::with('parent')->with('children')->get();
        });
        $view->with('categories', $value);
    }
}

So it seems this where I should pass data to the menu view. But in this view, I am not sure how to access the data I need.

So I noticed an Items Composer, and I thought maybe that is where lesson and exercise data is available:

<?php

namespace App\Http\Composers;

use Illuminate\Contracts\View\View;
use Exception;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Helpers\QueryString;
use DB;

class ItemsComposer
{
    private $viewData;
    private $searchService;

    public function __construct(\App\Services\SearchService $searchService)
    {
        $this->searchService = $searchService;
    }

    public function compose(View $view)
    {
        $this->viewData = $view->getData();
        $view->with($this->createModel());
    }

    public function createModel()
    {
        $mode = $this->viewData['mode'] ?? 'lessons';

        if ($mode == 'lessons') return $this->getLessons();
        elseif ($mode == 'exercises') return $this->getExercises();
        else throw new Exception('Unknown search mode.');
    }

    private function getLessons()
    {
        $result = $this->searchService->searchLessons($this->viewData);

        return [
            'lessons' => $result['lessons'],
            'mode' => 'lessons',
        ];
    }
    private function getExercises()
    {
        $result = $this->searchService->searchExercises($this->viewData);

        return [
            'exercises' => $result['exercises'],
            'mode' => 'exercises',
        ];
    }
}

Anyway, I then decided to look at exercise view which is passes $exercise, and in controller I see this:

<?php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Input;

class ExerciseController extends Controller
{
    public function getAll(Request $request)
    {
        $query = \App\Exercise::query();

        if ($request->has('title')) {
            $query->where('title', 'like', $request['title']);
        }
        if ($request->has('intro')) {
            $query->where('intro', 'like', $request['intro']);
        }
        if ($request->has('free')) {
            $query->where('free', $request['free']);
        }
        if ($request->has('id')) {
            $query->where('id', $request['id']);
        }
        $query->orderBy('updated_at', 'desc');
        return $query->get()->load('lesson')->load('tags');
    }

    public function get($id)
    {
        $exercise = \App\Exercise::find($id);
        $exercise->load('lesson')->load('tags')->load('files')->load('coverPhoto', 'tabPhoto', 'fretPhoto');
        $exercise->attachKindToFiles();
        return $exercise;
    }

    public function post()
    {
        $exercise = \App\Exercise::create(Input::all());
        isset(Input::all()['tags']) ? $exercise->updateTags(Input::all()['tags']) : '';
        return $exercise;
    }

    public function put($id)
    {
        $exercise = \App\Exercise::find($id);
        $exercise->update(Input::all());
        $exercise->updateTags(Input::all()['tags']);
        $exercise->updateFiles(Input::all()['files']);
        $exercise->load('tags');
        return $exercise;
    }

    public function delete($id)
    {
        \App\Exercise::find($id)->delete();
    }
}

And in exercise view, accessing the category is as $exercise->lesson->category->title

When the item is a lesson, it is a similar call.

Above hasn't completely told me what I need to know but I feel like I am getting close. If an experienced larval developer can take a look at the above and describe what I need to do to get the item category passed to the menu view, I would be greatly appreciative!

thanks, Brian

Please or to participate in this conversation.