PHP - "n" number of children in a list - php

This question is in relation to: Group by in Laravel 5
Essentially, what I have have is a series of "Groups" and each group can have a as many child groups as they want. So it could look something like this:
Group 1
Group 1 Child
Group 1's child
Group 1 1's Child
Group 2
At the moment, I am only able to display the group, and their children, using:
<ul>
#foreach($contents as $content)
<li>{{$content->title}}</li>
#if($content->children->count() > 0)
<ul>
#foreach($content->children as $childContent)
<li>{{$childContent->title}}</li>
#endforeach
</ul>
#endif
#endforeach
</ul>
If I want to add more layers of children, I have to code this, with another if statement as well as a foreach statement. Obviously this is not practical when a group has n^3,... number of children.
Is there a dynamic, while-loop approach to solving this problem? Any help would be greatly appreciated!!

What you need is a recursive partial - a one that would load itself as long as there are some more group levels to be displayed.
// list_group.blade.php
<li>
{{ $content->title }}
#if($content->children->count() > 0)
<ul>
#foreach($content->children as $childContent)
#include('list_group', array('content' => $childContent))
#endforeach
</ul>
#endif
</li>
//in your template
<ul>
#foreach($contents as $content)
#include('list_group', array('content' => $content))
#endforeach
</ul>

Related

How can limited span class item list in Laravel

Limit to item list:
More Description from the Pics:
I want to limited max item list at Laravel, As you if select all filter in admin panel, its look like this. So how can limited first 5 item to popular filters ?
<div class="g-attributes">
<span class="attr-title" style="color: orange"><b><i class="icofont-medal"></i> {{$translate_attribute->name ?? ""}}:</b> </span>
#foreach($termsByAttribute as $term )
#php $translate_term = $term->translateOrOrigin(app()->getLocale()) #endphp
<span class="item {{$term->slug}} term-{{$term->id}}" style="color: green" >{{$translate_term->name}}</span>
#endforeach
</div>
You can use the Collection's take() method to grab the first 5 elements:
#foreach($termsByAttribute->take(5) as $term)
Your question isnt very clear, but I am assuming that you want to be able retrieve the last 5 rows of the table, in your controller, you can get the records like this
$termsByAttribute = Table::latest()->take(5)->get();

how to create <ul> thing for each 10 <li> created?

I need to create every 10 records of the new <ul> to store the rest.
The idea is that every 10 <li> he creates another <ul> block that will contain 10 more and so on.
What is returned from the bank in blade:
As I'm trying to do with the following result now:
Can someone help me?
Via array_chunk() you can split your array into chunks of 10 items (or less if it's the last chunk).
#php
$chunks = array_chunk($category->recursiveChildren, 10);
#endphp
#foreach($chunks as $chunk)
<ul>
#foreach($chunk as $child)
<li>{{ $child }}</li>
#endforeach
</ul>
#endforeach

How to comma separate properties from a Laravel returned object

First, my apologies if the issue has been resolved. I read a lot of similar posts, but not quite the right one for my case.
I am setting up a simple project in Laravel 5.8. I want to create a simple bookstore and I need a book to have multiple authors so each title is followed by the author, or authors - if many - separated by commas and the last one by the word 'and'.
I have set up two Models, 'Author' and 'Book' and their respective tables, as well as a pivot table since they are in a relation belongsToMany. Everything works like a charm, I get my results as expected. However, I cannot get to format the results as I need. In the case of multiple authors, I always get an extra comma in the end. Since I cannot get the commas right I haven't yet tried to add the last 'and' in the case of the last author.
In the case of a single author the solution is easy, I just use a conditional.
However in the case of multiple authors, thing get complicated.
The most popular method to similar problems was the use of implode() in various similar ways. The problem with this method is since Eloquent is using its internal logic to perform the query, when I loop through 'books', there is no author column, just a reference to the pivot table. In addition, the authors' include first name and last name in different columns. So, when I try to manually create an 'implodable()' array by fetching the respective data otherwise, I get double the item size, since each name consists of the first name and theist name. And on top of that, the whole thing runs inside a double loop, making things even more complicated for me.
I am sure there is a simple way around this.
This is a sample of my blade code as of now. Of course the conditionals should be rearranged accordingly when the problem will be solved, to implement the 'and' case:
<ul>
#foreach ($books as $book)
<li>{{ $book->title }} by
#if (count($book->author) == 1)
#foreach ($book->author as $name)
{{ $name->last_name }}
{{ $name->first_name }}
#endforeach
#else
#foreach ($book->author as $name)
{{ $name->last_name }}
{{ $name->first_name }}
{{-- print a comma here if there are other names, or an 'and' if it the last one. Problem seems that it needs to be solved outside the conditional, but how? --}}
#endforeach
#endif
</li>
#endforeach
</ul>
My DB structure:
'authors': 'id', 'last_name', 'first_name','created_at', 'updated_at'
'books': 'id', 'title', 'created_at', 'updated_at'
'author_book': 'id', 'author_id', 'book_id','created_at', 'updated_at'
Expected result:
Title 1, by Author 1
Title 2, by Author 1 and 2
Title 3, by Author 1, 2 and 3
Actual Result:
Title 1, by Author 1
Title 2, by Author 1 and 2 and
Title 3, by Author 1 and 2 and 3 and
If you didn't need the "and" mechanism, then implode with comma would do the job. For "and" mechanism use below code:
<ul>
#foreach ($books as $book)
<li>{{ $book->title }} by
#for ($i = 0; $i < count($book->author); $i++)
{{ $book->author[$i]->last_name }}
{{ $book->author[$i]->first_name }}
#if ($i == count($book->author) - 2)
and
#endif
#if ($i < count($book->author) - 2)
,
#endif
#endfor
</li>
#endforeach
</ul>
added non-breaking-space &nbsp wherever necessary to not get them linked to each other
Delete #if (count($book->author) == 1), if you use foreach inside.
You can't use #else, when before you close condition with #endif.
This #else has wrong construction, use #elseif instead.
If you want check authors count and show extra value, do it inside foreach with $book->author()->count().
What relation u have for book -> author? One book can have many authors or not?
Just display implode(', ', $book->author), based on your actual result you don't need to do complicated checking if/else anymore.
#foreach ($books as $book)
<li>{{ $book->title }} by {{print implode(', ', $book->author)}}</li>
#endforeach

blade templates recursive includes

I have an array of items that represent the file and dir structure of a directory on the server.
The $items array is constructed like this:
Array
(
[folder1] => Array
(
[folder1_1] => Array
(
[0] => filenameX.txt
[1] => filenameY.txt
)
)
[pages] => Array
(
)
[0] => filename.txt
[1] => filename1.txt
)
what we want, is essentially <ul> with <li> for every node.
the resulting HTML should be something like
folder1/
folder1_1/
filenameX.txt
filenameY.txt
pages/
filename_1.txt
filename_2.txt
Now, my question has to do with nested includes with laravel's blade templating engine.
I have a view list.blade.php with the following contents
<div class="listing">
#include('submenu', array('items', $items))
</div>
and I pass it the array like this:
View::make('list')->with('items', $items)
the included template (submenu.blade.php) has the following:
<ul>
#foreach($items as $key=>$value)
#if (is_array($value))
<li>{{$key}}/
#include('submenu', array('items', $value))
</li>
#else
<li>{{$value}}</li>
#endif
#endforeach
</ul>
I #include the same template from within itself but with the new data, in case the $value is an array (directory)
First of all, is this at all possible?
If not, is there another way to achive the desired result?
TIA,
Yes, this is indeed possible.
However, there's an issue in your includes, you have:
#include('submenu', array('items', $value))
It should be:
#include('submenu', array('items' => $value))
It's worth noting also another hidden blade statment, #each. You can use this instead of looping through the array yourself, something like this:
<ul>
#each('item.detail', $items, 'item')
</ul>
Then you create a new blade file named item.detail and pop what you previously had in your loop in that file. It helps to clean up your view from having more and more nested loops.
The data for the item when you are inside your new blade file will be held in the third parameter, in this case $item
Instead of using array, use an eloquent collection. Instead of using #include, use \View::make. It cleans up the code a bit. Here is an example drop down menu for the Foundation 5 framework, using an eloquent model with parent/child relationship:
My model has a parent->child relationship
public function children() {
return $this->hasMany('Category', 'parent_id');
}
I generate my results like so in my controller
$categories = \Category::where('parent_id', '=', '0')->with('children')->get();
Blade template: _partials.dd-menu.blade.php
<ul class="{{$class}}">
#foreach($items as $item)
<?php
$active = $item->id == \Input::get('category') ? 'active' : '';
$hdd = $item->children->count() ? 'has-dropdown' : '';
?>
<li class="{{$hdd}} {{$active}}">
{{$item->name}}
#if ($item->children->count())
{{ View::make('_partials.dd-menu')->withItems($item->children)->withClass('dropdown')}}
#endif
</li>
#endforeach
In your parent blade:
<nav class="top-bar" data-topbar role="navigation">
<ul class="title-area">
<li class="name">
<h1>Categories</h1>
</li>
<!-- Remove the class "menu-icon" to get rid of menu icon. Take out "Menu" to just have icon alone -->
<li class="toggle-topbar menu-icon"><span>Menu</span></li>
</ul>
<section class="top-bar-section">
<!-- Right Nav Section -->
{{ View::make('_partials.dd-menu')->withItems($categories)->withClass('right')}}
</section>
</nav>

Fat Free Framework: how create dynamic menu with submenu

I have this table
id children voce alias pubblicato
11 NULL Chi Siamo chi-siamo 1
12 11 Chi Siamo - Sub chi-siamo-sub 1
So the id 12 is children (submenu) of 11.
With this block i can print the first level of a menu
<repeat group="{{ #result }}" key="{{ #ikey }}" value="{{ #voce }}">
<li>{{ trim(#voce.voce) }}</li>
</repeat>
(result is result of query SQL).
Of course i need to obtain that in my scheme menu will be (pseudo // bootstrap html code)
<li>ID 11 menu
<ul class="dropdown-menu">
<li>Id 12 menu</li>
</ul>
So, in (very!) pseudo code
if (children is not null) {
don't echo </li>
echo <ul class="dropdown">
echo voce where children == parent
}
Thank you very much.
PS If you think that my table need to be edit, don't worry, tell me your best solution!
i did this the following way:
// load page tree
$pages = $model->find();
$pageTree = array();
$pagesByID = array();
foreach($pages as $index => $page)
$pagesByID[$page->_id] = $page->cast();
// reorder to tree
foreach ($pagesByID as &$value)
if ($parent = $value['pid'])
$pagesByID[$parent]['childs'][] = &$value;
else
$pageTree[] = &$value;
$pageTree is now a multi-dimensional array, with child keys, if that page has some childs.

Categories