parent id for category and subcategory - php

I use L8 And I have a category table ,it has parent_id for my subcategories
categories table
Category model
categoryController
SubCategoryController
categories.blade
sub_categories.blade
In my subcategory-index.blade.php I want to show categories but I just can show them with their id (parent id)
I don't know how to show categories title instead of their id.
I have this migration for categories table :
public function up()
{
Schema::dropIfExists('categories');
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('parent_id')->default(123);
$table->string('title');
$table->longText('description');
$table->tinyInteger('status')->comment('status is 1 when a category is active and it is 0 otherwise.')->nullable();
$table->rememberToken();
$table->softDeletes();
$table->timestamps();
});
}
and this is my category model :
class Category extends Model
{
use HasFactory;
protected $fillable = [
'parent_id','title' , 'description', 'status',
];
public function children(){
return $this->hasMany(Category::class , 'parent_id');
}
public function post(){
return $this->hasMany(Post::class);
}
}
And my subcategory controller :
...
public function index()
{
$parent_id = Category::with('parent_id')->get();
$subcategories = Category::where('parent_id' ,'!=', 123)->get();
return view('admin.subcategories.subcategories-index' , compact('subcategories'));
}
...
And the part for show subcategory title in category-index.blade.php :
<table class="table table-bordered">
<tr>
<th>#</th>
<th>id</th>
<th>title</th>
<th>category</th>
<th>status</th>
<th>operation</th>
</tr>
#foreach($subcategories as $subcategory )
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $subcategory['id'] }}</td>
<td>{{ $subcategory['title'] }}</td>
<td>{{ $subcategory['parent_id']}}</td>
<td>
#if($subcategory['status']==0 or $subcategory['status']==NULL)
inactive
#else
active
#endif
</td>
<td>
<form method="POST" action="{{ route('subcategory.destroy',$subcategory->id) }}">
<a class="btn btn-info" href="{{ route('subcategory.show' , $subcategory->id) }}">show</a>
<a class="btn btn-primary" href="{{ route('subcategory.edit' , $subcategory->id) }}">edit</a>
#csrf
#method('DELETE')
<button type="submit" class="btn btn-danger"> delete</button>
</form>
</td>
</tr>
#endforeach
</table>
Thanks for telling me what to do :>

To get subcategories
$sub_categories = Category::whereNotNull('parent_id')->get();
To get sub-categories with parent
$sub_categories_with_parent = Category::with('parent')->whereNotNull('parent_id')->get();
To fetch categories
$categories = Category::whereNull('parent_id')->get();
To fetch categories with children
$categories_with_childern = Category::with('children')->whereNull('parent_id')->get();
You might have to redefine your relations as well:
public function parent()
{
return $this->belongsTo(Category::class);
}
public function children()
{
return $this->hasMany(Category::class , 'parent_id');
}
In migration define relation as well
$table->foreign('parent_id')->references('id')->on('categories')->onUpdate('cascade')->onDelete('cascade');
Make parent field nullable
$table->unsignedBigInteger('parent_id')->nullable()->default(123);

The line down below is incorrect. Because with() is used to get relational data and parent_id is not a relation name.
$parent_id = Category::with('parent_id')->get();
If your route contains the id or slug of the category, you can use it, but I think it doesn't, because your index function doesn't accept any route parameter. So I assume you are trying to fetch all categories and subcategories. But in this case, the second line of the index function doesn't make sense at all.
If you want to all categories:
$categories = Category::where('parent_id', null)->with('children')->get();
I see you use 123 for top-level categories, and it looks high enough. But nullable is a better practice for that purpose.
If you need a specific category and its subcategories:
// web.php
Route::get('category/{slug}', [CategoryController::class, 'index']);
// CategoryConteroller.php
public function index($slug)
{
$category = Category::where('slug', $slug)->with('children')->get();
}

Related

Laravel get attribute with hasMany

I'm making shop online with Laravel. I made Cart with records user_id and product_id with relations hasMany to products. My problem is that I can't get for example product's name or price, I can only get whole array with products and cart data. Can someone tell me how to get it? Maybe there is a problem with a query or just view syntax.
My migration:
public function up()
{
Schema::create('carts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('product_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('product_id')->references('id')->on('products');
});
Here is my controller function:
public function index(Request $request)
{
$query = Cart::with('product')->where('carts.user_id', $request->user()->id);
$query = $query->get();
return view('cart.index', ['cart' => $query]);
}
And view to show cart
#extends('app')
#section('content')
#foreach ($cart as $item)
<form method="" action="{{ route('destroycart', ['id' => $item->id]) }}">
{{ $item['product'] }}
<button class="btn btn-outline-dark">X</button>
</form>
#endforeach
#endsection
Model:
class Cart extends Model
{
use HasFactory;
public function product() {
return $this->hasMany(Product::class, 'id', 'product_id');
}
}
Is there another option for $item['product'] to get only product data?
Forgot to paste what view returns:
[{"id":10,"name":"lklkl","description":"klklkk","img":"przyklad.mo.jpg","price":50,"count":9,"created_at":"2022-05-24T13:13:03.000000Z","updated_at":"2022-05-24T13:13:03.000000Z"}]
I would like to get for example product's name.
You should then also access products, so:
#foreach ($cart as $item)
// Cart stuff here.
#foreach ($item->product as $prod)
// Product stuff here
#endforeach
#endforeach
You can get a single cart in the controller method if you want to display only one cart at a time
public function index(Request $request)
{
return view('cart.index', [
'cart' => Cart::with('product')
->where('user_id', $request->user()->id)
->latest()
->first()
]);
}
Then in your view you can loop over the products in the cart
#extends('app')
#section('content')
<form method="" action="{{ route('destroycart', ['id' => $cart->id]) }}">
#foreach ($cart->product as $product)
<p>{{ $product->name }}</p>
#endforeach
<button class="btn btn-outline-dark">X</button>
</form>
#endsection
Or if you want to show all carts for the currently logged in user then you can do it as
public function index(Request $request)
{
return view('cart.index', [
'carts' => Cart::with('product')
->where('user_id', $request->user()->id)
->latest()
->get()
]);
}
The in the view loop over the carts and with each iteration - loop over the products
#extends('app')
#section('content')
#foreach($carts as $cart)
<form method="" action="{{ route('destroycart', ['id' => $cart->id]) }}">
#foreach ($cart->product as $product)
<p>{{ $product->name }}</p>
#endforeach
<button class="btn btn-outline-dark">X</button>
</form>
#endforeach
#endsection

Tried to using belongsTo in Laravel but its not working

im using Laravel 6.2
I want to make a inventory database system. i have 2 modals Produk and Stock.
in that case, i want to input data p_name and sku from ProdukTable and place it into StockTable using Eloquent ORM.
I tried using belongsTo(),
Here's my modal Produk code
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Produk extends Model
{
public $table = 'produk';
protected $primaryKey = 'pid';
protected $fillable = [
'pid',
'p_nama',
'sku',
'p_harga',
'status'
];
}
Here's my modal Stock code
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Stock extends Model
{
public $table = 'stock';
protected $primaryKey = 'sid';
protected $fillable = [
'sid',
'p_nama',
'sku',
'p_stock_min',
'p_stock',
'status'
];
public function produk()
{
return $this->belongsTo('App\Produk', 'pid');
}
}
My StockController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Stock;
use App\Produk;
use RealRashid\SweetAlert\Facades\Alert;
class StockController extends Controller
{
public function index()
{
$datas = Stock::paginate(5); // 5 record per pages
return view('stock.list', compact('datas'));
// $datas = Stock::all();
// return $datas;
}
. . . .
}
My View stock.blade
<div class="body">
<div>
<i class="zmdi zmdi-account-add"></i> Tambah Stock
<a style="margin: 2px;" href="{{ route('stock.index')}}" class="btn btn-primary btn-sm"><i class="zmdi zmdi-refresh"></i></a>
</div>
<div class="col-sm-12">
#if(session()->get('success'))
<div class="alert alert-success">
{{ session()->get('success') }}
</div>
#endif
</div>
<table class="table table-bordered table-striped table-hover dataTable js-exportable">
<thead>
<tr>
<th class="text-center" style="width:5%">#</th>
<th class="text-center" style="width:25%">Nama Produk</th>
<th class="text-center" style="width:10%">SKU Produk</th>
<th class="text-center" style="width:8%">Min. Stock</th>
<th class="text-center" style="width:8%">Stock</th>
<th class="text-center" style="width:10%">Status</th>
<th class="text-center" style="width:10%">Aksi</th>
</tr>
</thead>
<tbody>
#if(!empty($datas) && $datas->count())
#foreach($datas as $data)
<tr>
<th class="text-center">{{ $loop->iteration }}</th>
<td>{{ $data->produk }}</td>
<td>{{ $data->p_nama }}</td>
<td>{{ $data->p_stock_min }}<code> pcs</code></td>
<td>{{ $data->p_stock }}<code> pcs</code></td>
<td class="text-center">{{ $data->status }}</td>
<td class="text-center">
<i class="zmdi zmdi-edit"></i></span>
<i class="zmdi zmdi-delete"></i></span>
</td>
</tr>
#endforeach
#else
<tr>
<td colspan="8">Data tidak ditemukan! Silahkan buat data Stock terlebih dahulu.</td>
</tr>
#endif
</tbody>
</table>
{!! $datas->links() !!}
</div>
Migration Stock
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateStocksTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('stock', function (Blueprint $table) {
$table->bigIncrements('sid');
$table->bigInteger('produk_id')->unsigned();
$table->string('p_nama');
$table->string('sku');
$table->integer('p_stock_min');
$table->integer('p_stock')->nullable();
$table->string('status');
$table->timestamps();
});
Schema::table('stock', function (Blueprint $table) {
$table->foreign('produk_id')->references('pid')->on('produk')
->onDelete('cascade')->onUpdate('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('stock');
}
}
Response when i add data direct from PMA
[{"sid":1,"produk_id":6,"p_nama":"kopi1","sku":"12345678","p_stock_min":20,"p_stock":800,"status":"Aktif","created_at":"2020-11-24 16:37:16","updated_at":"2020-11-24 16:37:16"},
{"sid":2,"produk_id":7,"p_nama":"kopi2","sku":"87654321","p_stock_min":20,"p_stock":600,"status":"Aktif","created_at":"2020-11-24 16:37:16","updated_at":"2020-11-24 16:37:16"}]
i dunno where's my mistake ?
just want to add data p_produk into stock table using select form, and when i select it sku data will be generate as same as data on table Produk.
In your Stock model you should put the foreign key in the belongsTo relation. Edit the method like so:
public function produk()
{
return $this->belongsTo('App\Produk', 'produk_id');
}
Using Laravel conventions the relationship produk should be defined as
public function produk()
{
return $this->belongsTo(Produk::class, 'produk_id', 'pid');
}
To dynamically change the value of sky in the readonly input on create.blade.php based on the option selected by the user in select control showing $produk->p_nama:
Give an id to the readonly input for sku
<div class="form-group">
<label for="sku">SKU:</label>
<input type="text" class="form-control form-control-lg" name="sku" id="skuSelected" readonly/>
</div>
Track the option selected in select control
<select class="form-control select2" name="p_name" onChange="setSku(this);">
#foreach($produks as $produk)
<option value="{{ $produk->pid }}">{{ $produk->p_nama }}</option>
#endforeach
</select>
Handle the change in selection via javascript
<script>
function setSku(sel) {
const sku = sel.options[sel.selectedIndex].text;
document.getElementById('skuSelected').value = sku;
}
</script>
because you are not naming your columns on the laravel naming conventions
you have to define it all by yourself if you want to use this naming like this :
public function produk()
{
return $this->belongsTo('App\Produk', 'pid' , 'id');
}
as belongsTo takes $relatedModel , $foreignKey , $ownerKey in a row

How to paginate and show all records using hasMany in laravel 5.6?

I have two tables one table for general information about the order named orders and a detail table for information like products, notes and delivery date.
Basically, I want to show in the same page the table orders and for each order can be multiple products, notes, dates from the table detail, and also I want to paginate in order to show exactly 20 orders on each page and every product, note, date row with the same id_order.
In conclusion, on each page there are 20 orders from table orders but there can be 40 rows from table detail with products, notes, delivery date, because one order can contain more than one product. in fact I want to use rowspan html in order to show on the same row the detail.
This is my Orders model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class order extends Model
{
public $timestamps = false;
protected $fillable = ['client','number_order','file'];
public function details()
{
return $this->hasMany('App\Detail','orders_id')->orderBy('id', 'desc');
}
}
Detail model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Detail extends Model
{
protected $table = 'detail';
public function order()
{
return $this->belongsTo('Detail','orders_id');
}
}
My controller:
public function index()
{
$orders = Order::first(); //This works only with one record I cant show all records, all() is not working
$orders->setRelation('details', $orders->details()->paginate(10));
return view('orders.index', compact('orders'));
}
View:
<tbody>
#foreach ($orders->details as $detail)
<tr id="{{ $detail->orders_id }}">
<td>{{ $detail->product }}</td>
</tr>
#endforeach
</tbody>
You can use eager load details on order like this
public function index()
{
$orders = Order::with('details')->paginate(20);
return view('orders.index', compact('orders'));
}
In view
<table>
<tbody>
#foreach($orders as $order)
<tr>
<td>{{ $order->created_at }}</td>
<td>... put any order info here</td>
<td>
<label>Order Details:</label>
<table>
#foreach ($order->details as $detail)
<tr id="{{ $detail->orders_id }}">
<td>{{ $detail->product }}</td>
<td>{{ $detail->note }}</td>
</tr>
#endforeach
</table>
<td>
</tr>
#endforeach
</tbody>
</table>

many to many laravel get values

in user class model , i have this
public function projects()
{
return $this->belongsToMany('App\Project');
}
in project class model i have this :
public function users(){
return $this->belongsToMany('App\User');
}
in my projectController i have this :
public function index()
{
$TeamLeader = array();
$posts = Project::orderby('id', 'desc')->with('users')->paginate(5);
return view('Projects.index', compact('posts'));
}
in my view i have this for each :
#foreach ($posts as $post)
<tr>
<td><input type="checkbox" class="checkthis" /></td>
<td href="{{ route('Projects.show', $post->project_id ) }}">{{ $post->project_id }}</td>
<td>{{ $post->name }}</td>
<td>{{ $post->description }}</td>
<td>{{ $post->created_at }}</td>
<td>{{ $user->name}}</td>
<td><p data-placement="top" data-toggle="tooltip" title="Show"><button class="btn btn-primary btn-xs" data-title="Edit" data-toggle="modal" data-target="#show" ><span class="glyphicon glyphicon-pencil"></span></button></p></td>
<td><p data-placement="top" data-toggle="tooltip" title="Delete"><button class="btn btn-danger btn-xs" data-title="Delete" data-toggle="modal" data-target="#delete" ><span class="glyphicon glyphicon-trash"></span></button></p></td>
</tr>
#endforeach
my problem is , in my view i can not get the users name , the realation is many-to-many but iam not getting the names of the users who are involved in the project , the database structure is as you can imagine :
Users has id , name , ......
Projects has id , name , location , user_id , .....
sorry to not mention that earlier but i have this common table also :
Schema::create('project_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('project_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('project_id')->references('id')->on('projects');
$table->timestamps();
});
Actually your tables design is not many to many, It's one to many [User has many Project]
if you want to make many to many relation must make a middle table (pivot table)
take a look at this
This is helpful
Add this to your migrations
Schema::create('project_user', function(Blueprint $table)
{
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')
->on('users')->onDelete('cascade');
$table->integer('project_id')->unsigned()->nullable();
$table->foreign('project_id')->references('id')
->on('projects')->onDelete('cascade');
$table->timestamps();
});
project_user table is derived from the alphabetical order of the related model names, and contains the user_id and project_id columns
Then remove user_id column from your projects table
Finally yo can access the name of users like
$project->users[0]->name
$project->users[0]->name

Laravel - displaying categories by id

For a blog site, I have all the posts & lists of categories displaying on a page though now I need to display the posts for each category on it's own separate page.
Let's say I had a categorie that was 'Javascript' and I wanted only the posts with the category of javascript displayed on a page.
What's the correct code to do this? here's an example, the bold 'javascript' is what needs to be replaced with the correct code.
-- categoriesController.php ---
public function show($id)
{
$post->withCategories($Categories)->$id->($id as **javascript)**
}
--- javascript.blade.php --- ( corresponding view )
<tbody>
#foreach ($categories as $category->$id>**javascript**)
<tr>
<th>{{ $category->id }}</th>
<td>{{ $category->name }}</td>
</tr>
#endforeach
</tbody>
</table>
</div> <!-- end of .col
For example:
post.php model
class Post extends Model
{
protected $primaryKey = 'id';
function withCategories() {
return $this->hasOne('App\Categories', 'id', 'category_id');
}
public function show($id){
Post::with('withCategories')->where('category_id', $id)->get(); //the output of articles of the category
}
}
$id is a parameter of url: site.com/posts/javascript
in posts.blade.php
<table>
<tbody>
#foreach ($posts as $post)
<tr>
<th>{{ $post->id }}</th>
<td>{{ $post->name }}</td>
<td>{{ $post->withCategories->name }}</td> <!-- Category name-->
</tr>
#endforeach
</tbody>
</table>
</div>

Categories