How to show menu dynamically in Laravel - php

I'm trying to show menu in laravel dynamically.
I have two table, One holds Main Category and other one Holds Sub category
Here is the structure of Category table
----------------------------------
| id | title | slug | type |
| 1 | title1 | slug1 | Android |
| 2 | title2 | slug2 | Android |
| 3 | title3 | slug3 | Android |
| 4 | title4 | slug4 | Ubuntu |
| 5 | title5 | slug5 | Ubuntu |
----------------------------------
Sub Category Structure
-----------------------------------------------
| id | title | slug | category_of|
| 1 | title1 | slug1 | 1 |
| 2 | title2 | slug2 | 1 |
| 3 | title3 | slug3 | 1 |
| 4 | title4 | slug4 | 2 |
| 5 | title5 | slug5 | 1 |
-----------------------------------------------
Here is What I've tried
<?php
$category = App\Models\Menu::where('categories.type', 'Android')
->select('categories.*', 'sub_category.slug as sub_slug', 'sub_category.title')
->join('sub_category', 'sub_category.category_of', '=', 'categories.id')
->get();
?>
#foreach ($category as $value)
<li class="inner-dropdown-item">
<p>
{{ucwords(str_replace('-', ' ', $value->slug))}}
</p>
</li>
<li class="inner-dropdown-item">
{{ucwords(str_replace('-', ' ', $value->sub_slug))}}
</li>
#endforeach
The Problem I'm facing is, it is duplicating main category every time due to foreach loop, for e.g
<li class="inner-dropdown-item">
<p>
Android
</p>
</li>
<li class="inner-dropdown-item">
Calendars
</li>
<!-- /INNER DROPDOWN ITEM -->
<!-- /This Below Android category should not be shown again -->
<li class="inner-dropdown-item">
<p>
Android
</p>
</li>
<li class="inner-dropdown-item">
Database Abstractions
</li>
As you see it is duplicating main category every time sub category is shown. How can i show Main category Once and then all sub category following under it
I have another Template which has different menu HTML Structure
<!-- MENU ITEM -->
<li class="menu-item sub">
<a href="#">
Designer
<!-- SVG ARROW -->
<svg class="svg-arrow">
<use xlink:href="#svg-arrow"></use>
</svg>
<!-- /SVG ARROW -->
</a>
<div class="content-dropdown">
<!-- FEATURE LIST BLOCK -->
<?php $m_des = ''; ?>
#foreach ($design_category as $des_value)
#if($m_des != $des_value->slug)
<div class="feature-list-block">
<a href="{{ Config::get('constants.url.BASE_URL') }}category/{{$des_value->slug}}/">
<h6 class="feature-list-title">{{ucwords(str_replace('-', ' ', $des_value->slug))}}</h6></a>
<hr class="line-separator">
<?php $m_des = $des_value->slug; ?>
#endif
<!-- FEATURE LIST -->
<ul class="feature-list">
<li class="feature-list-item">
{{ucwords(str_replace('-', ' ', $des_value->sub_slug))}}
</li>
</ul>
<!-- /FEATURE LIST -->
</div>
#endforeach
</div>
</li>
<!-- /MENU ITEM -->
It is generating ul and div again and again which causes html errors

There may be a better solution for it. But you can try this. Do order by categories.id then in loop check main category is printed last time or not
<?php
$category = App\Models\Menu::where('categories.type', 'Android')
->select('categories.*', 'sub_category.slug as sub_slug', 'sub_category.title')
->join('sub_category', 'sub_category.category_of', '=', 'categories.id')
->orderBy('categories.id');
->get();
$latest_category = "";
?>
#foreach ($category as $value)
<?php if($latest_category != $value->slug){ ?>
<li class="inner-dropdown-item">
<p>
{{ucwords(str_replace('-', ' ', $value->slug))}}
</p>
</li>
<?php
$latest_category = $value->slug;
} ?>
<li class="inner-dropdown-item">
{{ucwords(str_replace('-', ' ', $value->sub_slug))}}
</li>
#endforeach
EDIT
<div class="content-dropdown">
<!-- FEATURE LIST BLOCK -->
<?php $m_des = '';
$end_div = '';
?>
#foreach ($design_category as $des_value)
#if($m_des != $des_value->slug)
{{$end_div}}
<div class="feature-list-block">
<a href="{{ Config::get('constants.url.BASE_URL') }}category/{{$des_value->slug}}/">
<h6 class="feature-list-title">{{ucwords(str_replace('-', ' ', $des_value->slug))}}</h6></a>
<hr class="line-separator">
<?php $m_des = $des_value->slug;
$end_div = "</div>";
?>
#endif
<!-- FEATURE LIST -->
<ul class="feature-list">
<li class="feature-list-item">
{{ucwords(str_replace('-', ' ', $des_value->sub_slug))}}
</li>
</ul>
<!-- /FEATURE LIST -->
#endforeach
{{$end_div}}
</div>

Related

How to show single array only?

I'm making a recommendation system and I want to show only the top 1 from the recommendation instead of all of it.
this is the code
$movies = mysqli_query($db, "select * from practice");
while ($movie=mysqli_fetch_array($movies))
{
$users=mysqli_query($db,"select username from users where id =$movie[user_id]");
$username=mysqli_fetch_array($users);
$matrix[$username['username']] [$movie['image']] = $movie ['ratings'];
}
$users=mysqli_query($db,"select username from users where id=$_GET[id]");
$username=mysqli_fetch_array($users);
?>
<div class="panel panel-default">
<div class="panel-heading">
<h2>
<a class="btn btn-info" href="index.php"> Back </a>
</h2>
</div>
<div class="panel-body">
<table class="table table-striped">
<th>Clothes</th>
<th>Rating</th>
<?php
$recommendation=array();
$recommendation = getRecommendation($matrix,$username['username']);
foreach($recommendation as $movie => $rating) {
?>
<tr>
<td>
<?php echo "<img src='images/".$movie."' >"; ?>
</td>
<td>
<?php echo $rating ; ?>
</td>
</tr>
<?php } ?>
</table>
</div>
You should use the LIMIT in your sql query.
LIMIT Query
If you need only a specified number of rows from a result set, use a LIMIT clause in the >query, rather than fetching the whole result set and throwing away the extra data.
MySQL sometimes optimizes a query that has a LIMIT row_count clause and no HAVING clause
mysql> SELECT * FROM ratings ORDER BY category;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
| 1 | 1 | 4.5 |
| 5 | 1 | 3.2 |
| 3 | 2 | 3.7 |
| 4 | 2 | 3.5 |
| 6 | 2 | 3.5 |
| 2 | 3 | 5.0 |
| 7 | 3 | 2.7 |
+----+----------+--------+
mysql> SELECT * FROM ratings ORDER BY category LIMIT 1;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
| 1 | 1 | 4.5 |
+----+----------+--------+
https://dev.mysql.com/doc/refman/8.0/en/select.html

Laravel Model Count By Relationship

I have an eCommerce site with a Product model and a ProductCategory model. I currently show products on the page from the Product model but would like to be able to get a list of all the categories with products in the current model and how many products are in each category. I can get the overall count but can't figure out how to get the list of categories being shown and how many results per category have been returned.
Product Model
Product_ID
Product_Name
Product_Description
Category_ID (Many-To-1: ProductCategory.Category_ID
ProductCategory Model
Category_ID
Category_Name
Currently, I access the results in the blade using...
#foreach($products->chunk(3) as $row)
<div class="item-row">
#foreach($row as $product)
<div class="item item-thumbnail" style="height: 250px;">
<a href="product_detail.html" class="item-image">
#if(empty($product->Images{0}->original_image))
<img style="width: 100px; height: 100px;"
src="https://example.com/100x100/d3d3d3/fff.gif&text=No+Image"
alt="" />
#else
<img style="width: 100px; height: 100px;"
src="https://cdn.example.com.au/products/{{$product->id}}/{{$product->Images{0}->original_image}}"
alt="" />
#endif
</a>
<div class="item-info">
<h4 class="item-title">
<a href="/store/{{$category->alias}}/{{$product->alias}}">
{{$product->product_name}}
</a>
</h4>
<p class="item-desc"> </p>
#if(empty($product->special_price))
<div class="item-price">
${{$product->normal_price}}
</div>
#else
<div class="item-price">
${{$product->special_price}}
</div>
<div class="item-discount-price">
${{$product->normal_price}}
</div>
#endif
</div>
</div>
#endforeach
</div>
#endforeach
And would like to be able to generate a list of all the categories with products displayed as...
#foreach($products->categories as $category)
<li>
{{$category->category_name}} ({{$category->count}})
</li>
#endforeach
All from within the same model.
Additional
If it helps clarify I don't want the model to change drastically in that I still want to be able to access the products in the model from the blade template as is currently done but would like to also be able to pull a list of categories such as the below example...
| Product_ID | Product_Name | Category_ID |
| ---------- | ------------ | ----------- |
| 1 | Product 1 | 1 |
| 2 | Product 2 | 1 |
| 3 | Product 3 | 2 |
| Category ID | Category Name |
| ----------- | ------------- |
| 1 | Category 1 |
| 2 | Category 2 |
And wind up with the following table on my page to show the product categories being shown in the results...
| Category Name | # Products |
| ------------- | ---------- |
| Category 1 | 2 |
| Category 2 | 1 |
It would be super helpful if you provided the code where you query the products and categories.
But here's essentially what you need to do. You need to make use of ->withCount(..):
$products = Product::with([
'categories' => function ($query) {
// Adds count of category-related products
$query->withCount('products as count');
},
])->get();
And then this would work in your view:
#foreach($products as $product)
#foreach($product->categories as $category)
<li>{{$category->category_name}} ({{$category->count}})</li>
#endforeach
#endforeach

Making a category menu with its subcategories getting data from DB and PHP?

I am willing to do a dropdown (or a list, it doesn't matter) with categories and subcategories getting directly the data from the database.
The order should be:
CATEGORY 1
-- Subcategory 1
-- Subcategory 2
-- Subcategory 3
-- ...
CATEGORY 2
-- Subcategory 1
-- ...
...
And so on even adding future categories and subcategories.
I am using MVC and this is my code this far:
View:
<?php foreach ( $datoCategorias as $categorias ) { ?>
<div class="col">
<div class="dropdown">
<button class="col btn btn-secondary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<?php echo $categorias['NAME'] ?></button>
<div class=" col dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="index.php?controller=products&action=category&id="></a>
</div>
</div>
</div>
<?php } ?>
Index.php:
if ($_GET['action'] == "category") {
$controller = new productos_controller();
$controller->category();
}
Controller:
function category() {
$categorias = new productos_models();
$datoCategorias=$categorias->get_categorias();
require_once("views/products.php");
}
Model:
public function get_categorias(){
$categorias=$this->db->query("select * from CATEGORY;");
while($listaCategorias=$categorias->fetch_assoc()){
$this->cats[]=$listaCategorias;
}
return $this->cats;
}
Database table CATEGORY:
| ID | NAME | PARENTCATEGORY |
| 1 | CAT1 | null |
| 2 | CAT2 | null |
| 3 | CAT3 | null |
| 4 | SUB1 | 1 |
| 5 | SUB1 | 2 |
The problem is: How I should do the foreach or foreach'es to make the result look like the order I said before because I only managed to show the category's name.

Laravel 5.4 Nested Loop with Grouped dataset

"Filters" table looks like following:
id | group | label | value
----+----------+-------------------+----------------
12 | deadline | 1 to 3 days | 1 AND 3
14 | price | Any | 0
15 | price | Less than 1000 | 0 AND 1000
16 | price | 1000 to 10000 | 1000 AND 10000
22 | location | Any | 0
23 | location | New York | newyork
24 | location | California | california
25 | location | Alabama | alabama
I need to show chunk of "label" under the "group".
My controller:
public function index(){
$filters = Filters::all();
return view('frontend.request', compact('filters'));
}
My view has:
<?php foreach ($filters as $filter) { ?>
<div class="panel panel-default">
<b>{{ $filter->group }}</b>
<div id="collapseOne1" class="panel-collapse collapse in">
<div class="panel-body">
<div class="checkbox">
<label><input type="checkbox" name="{{ $filter->group }}" value="{{ $filter->any }}">{{ $filter->label }}</label>
</div>
</div>
</div>
</div>
<?php } ?>
I want to show all labels under the group within one box and so on. The above codes create different boxes for each label which is not right.
I believe, its got to be nested loop but I'm having difficult writing it on Laravel. Any idea how it should be?
Note: This thread gives partial answer but we don't know chunk size in my case: Laravel 5.1 - Nested Loop - Blade Templating
You could use Laravel's groupBy() collection method;
https://laravel.com/docs/5.4/collections#method-groupby
Controller:
public function index(){
$filters = Filters::all();
$groups = $filters->groupBy('group');
return view('frontend.request', compact('groups'));
}
View:
#foreach ($groups as $group => $filters)
<div class="panel panel-default">
<b>{{ $group }}</b>
#foreach($filters as $filter)
<div id="collapseOne1" class="panel-collapse collapse in">
<div class="panel-body">
<div class="checkbox">
<label><input type="checkbox" name="{{ $filter->group }}" value="{{ $filter->any }}">{{ $filter->label }}</label>
</div>
</div>
</div>
#endforeach
</div>
#endforech

Bootstrap 3 multi column dynamic block loop

Bootstrap is by default designed for Row-based designs (horizontal), like the following:
+-------------+ +--+
| 1 | | |
| | | |
+-------------+ | |
| 2 | | |
| | | |
+-------------+ | |
| 3 | | |
| | | |
+-------------+ | |
| 4 | | |
| | | |
+-------------+ +--+
I can easily do that by doing the following:
<div class="container">
<div class="row">
<div class="col-md-10">
<div class="row">
<div class="col-md-12">POST</div>
<div class="col-md-12">POST</div>
<div class="col-md-12">POST</div>
</div>
</div>
<div class="col-md-2">Sidebar</div>
</div>
</div>
I can repeat (dynamic loop) the number of blog posts within the left area.
But if I'm going to do something like the following, where all the blog posts are on the left in Two columns, and the looping makes the layout Vertical (not in Bootstrap's concept) what can I do then? How can I implement this?
+-----+ +-----+ +--+
| 1 | | 2 | | |
| | | | | |
+-----+ +-----+ | |
| 3 | | 4 | | |
| | | | | |
+-----+ +-----+ | |
| 5 | | 6 | | |
| | | | | |
+-----+ +-----+ | |
| 7 | | 8 | | |
| | | | | |
+-----+ +-----+ +--+
I know the HTML is:
<div class="container">
<div class="row">
<div class="col-md-10">
<div class="row">
<div class="col-md-6">Left</div>
<div class="col-md-6">Right</div>
</div>
<div class="row">
<div class="col-md-6">Left</div>
<div class="col-md-6">Right</div>
</div>
</div>
<div class="col-md-2">Widget</div>
</div>
</div>
But I'm confused with the dynamic part. I can guess that, it can be achieved by something like:
<?php for( $i=0; $i<10; $i++ ) { ?>
<?php if( $i==0 ) echo '<div class="row">'; ?>
<div class="col-md-6"><?php echo 'post #'. $i; ?></div>
<?php if( $i==2 ) echo '</div><!--/.row-->'; ?>
<?php } ?>
But isn't it a lengthy process? How can I achieve such a Vertical loopy layout using Bootstrap 3?
Either don't output these inner .rows and simply use .col-md-6 instead of .col-md-12 in the first example,
or,
output the inner starting rows <div class="row"> if i is even (i % 2 == 0) and the ending rows </div> when i is odd (i % 2 == 1).

Categories