Laravel 4 Eloquent Two Pivot Table - laravel

My tables
Modelos
id
nome slug
marca_id
Pecas
id
codigo
modelo_peca
modelo_id
peca_id
produtos
id
categoria_id
codigo
nome
categorias
id
nome
slug
I have these models
class Modelo extends Eloquent
{
public function pecas()
{
return $this->belongsToMany('Peca');
}
}
class Peca extends Eloquent {
public function modelos()
{
return $this->belongsToMany('Modelo');
}
public function produtos()
{
return $this->belongsToMany('Produto');
}
}
class Produto extends Eloquent {
public function pecas()
{
return $this->belongsToMany('Peca');
}
}
I´m trying to create a route that pass all the products related to a modelo to a view. What´s wrong?
Route::get('/modelo/{slug?}', function($slug = null) {
if ($slug) {
$id = Modelo::where('slug', $slug)->pluck('id');
$pecas = Modelo::find($id)->pecas;
$produtos = Peca::where('id', $pecas)->get();
}
return View::make('produto.home')->with('produtos', $produtos);

Use eager loading
Off the top of my head (also across the language barrier I'll do my best)
You seem to want all Products (produtos) for a specific page category other taxonomy (may be wrong but you can adjust the code as needed)
The where() method expects three parameters iirc so instead the first query would be $id = Modelo::where('slug', '=', $slug)->pluck('id');
The same would apply to the other where statements.
Full query:
if($slug)
{
$query = Modelo::with('pecas.produto')
->where('slug', '=', $slug)
->get();
$produtos = $query->produto;
}
return View::make('produto.home')->with('produtos', $produtos);
Here I've taken a different approach and eager loaded the relations, I'm not 100 percent sure this is how you want this to be done but it hopefully gives you a foundation for using your relations properly in Eloquent.
You don't need to manually get primary keys and perform multiple queries, check out the Eloquent documentation on the Laravel website.

Related

Why can't laravel/eloquent find certain table?

I'm trying to fetch some data from a table called "category", but laravel is throwing the
"SQLSTATE[42S02]: Base table or view not found" error.
I've tried with other table names like "company" and it works perfectly. Both of these tables exist but one of them can not be found with the same code.
This throws the error:
public static function getCategories()
{
$categories = [];
$cat = DB::table('category')->get();
if (isset($cat)){
foreach ($cat as $category_name){
array_push($categories, $category_name);
}
return json_encode($categories);
}
return null;
}
This works as expected (same code except for the table name string):
public static function getCategories()
{
$categories = [];
$cat = DB::table('company')->get(); //table name changed
if (isset($cat)){
foreach ($cat as $category_name){
array_push($categories, $category_name);
}
return json_encode($categories);
}
return null;
}
The only difference between those two tables is table collation:
company: utf8_general_ci
category: utf8mb4_swedish_ci
Create a model if it you don't have one. Add the following into your category model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'category';
}
Controller
public static function getCategories()
{
$categories = [];
$cat = Category::all();
if (isset($cat)){
foreach ($cat as $category_name){
array_push($categories, $category_name);
}
return json_encode($categories);
}
return null;
}
You're currently using Query Builder, try use eloquent way.
Ok, I found out we had two separate database-servers with almost identical data in them. Both had databases and tables with the same names, but one was missing the category table.
Of course I was connected to the wrong server from laravel after all.
TL;DR: Simple user error in configuration.

How to get top 10 category list in laravel eloquent query

i have three table one is category table and another is product table and one more product_to_category table, and it has only product_id and category_id column.
Now i want to get top 10 categories with maximum number of product, with details of 10 products from each category.
What i wrote is
$result = ProductToCategory::groupBy('category_id')->with(['product',function($q){
$q->take(10);
}])->orderBy('category_id)->take(10);
But this is not working.How to write this query properly
Can anyone please help. ty
Model relations
For Product model
public function category(){
return $this->belongsTo(ProductToCategory::class);
}
For Category model
public function products()
{
return $this->hasMany(ProductToCategory::class);
}
For ProductToCategory model
public function product()
{
return $this->hasMany(Product::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
The most efficient way would be using a raw SQL query because you can't filter products by using eager loading constraint.
But if you want an Eloquent solution anyway, define the relationships:
In the Product model:
public function categories()
{
return $this->belongsToMany(Category::class, 'product_to_category');
}
And in the Category model:
public function products()
{
return $this->belongsToMany(Product::class, 'product_to_category');
}
Then you'll have two options, both have their pros and cons:
1. This code will execute just 2 queries but will use more memory. You could get top ten categories with their products:
$categories = Category::withCount('products')->latest('products_count')->take(10)->with('products')->get();
And then keep only first ten products:
$categories->transform(function($category) {
$topProducts = $category->products->take(10);
unset($category->products);
$category->products = $topProducts;
return $category;
});
2. This solution will create 12 queries but will save the memory:
$categories = Category::withCount('products')->latest('products_count')->take(10)->get();
$categories->transform(function($category) {
$category->products = Product::whereHas('categories', function($q) use($category) {
$q->where('id', $category->id);
})
->take(10)
->get();
return $category;
});
Here is the DB facade version:
$tenPopularTags = DB::table('product_to_category')
->join('category', 'product_to_category.category_id', '=', 'category.id')
->select(DB::raw('count(product_to_category.category_id) as repetition, question_tag.tag_id'))
->groupBy('product_to_category.category_id')
->orderBy('repetition', 'desc')->take(10)
->get();
However I like #Alexey Mezenin way of doing it. Because that is the cleaner way have customized it a bit:
$tenCategories = Category::withCount('products')->orderBy('questions_count', 'DESC')->take(10)->get();
Have used both in my project blog with post and categories relationship and it works!

latest() helper function in laravel

I'm building a small application where I'm having many to many relationship between two models something like this:
class Contact extends Model
{
public function company()
{
return $this
->belongsToMany('App\Company', 'company_contact', 'company_id', 'contact_id')->withTimestamps();
}
}
Now while retrieving this I want only the latest model through the pivot table or you may say relational table, for this I'm trying to implement:
public function getData()
{
$allData = Contact::all();
foreach($allData as $data)
{
$getCompany = $data->company()->latest()->first();
$data->company = $getCompany;
}
return response()->json(['model' => $allData], 200);
}
But I'm unable to retrieve the latest table it is showing the same old value or the first value.
Guide me how can I achieve this.
You can try this :
latest() is a function defined in Illuminate\Database\Query\Builder Class.
public function latest($column = 'created_at')
{
return $this->orderBy($column, 'desc');
}
So, It will just orderBy with the column you provide in descending order with the default column will be created_at
OR
public function getData()
{
$allData = Contact::all();
foreach($allData as $data)
{
$getCompany = $data->company()->orderBy('created_at', 'desc')->first();
$data->company = $getCompany;
}
return response()->json(['model' => $allData], 200);
}
So basically idea is if you are finding the relational data from many to many relation like $data->company() in this question and try to sort this with latest it will sort the company table with created_at sorting desc in order to get relational latest data you need to sort through pivot tables i.e.
$getCompany = $data->company()->withPivot('created_at')->orderBy('pivot_cr‌​eated_at', 'desc')->first();
This is how I achieved the latest relational table.
Note: You must have pivot table in your relation, in this answer created_at is the pivot field I'm using.

Equivalent laravel relationship query for this join

this is my query
$personnel_info = \DB::table('assigns AS a')
->join('boxes AS b','b.id','=', 'a.box_id')
->join('positions AS p','p.id','=', 'b.position_id')
->select('a.id','b.id AS box_id','p.id as position_id','p.title','a.status','a.end_date')
->where('a.personnel_id','=',$personnel_id)
->get();
and this realtionship for boxes:
class Boxes extends Model
{
public function position()
{
return $this->belongsTo('Positions');
}
public function assign()
{
return $this->hasOne('Assigns', 'box_id');
}
}
how to use eloquent query(also realtionship) for replace DB facade query?
i want select some field for tables.without define fileds in boxes model
tnx
Try
$personnel_info = Assign::with('box.position')
->where('personnel_id', $personnel_id)
->get();
Then dd($personnel_info) to see everything that was returned. If you don't like the values, then add your select() clause.

Eloquent where condition based on a "belongs to" relationship

Let's say I have the following model:
class Movie extends Eloquent
{
public function director()
{
return $this->belongsTo('Director');
}
}
Now I'd like fetch movies using a where condition that's based on a column from the directors table.
Is there a way to achieve this? Couldn't find any documentation on conditions based on a belongs to relationship.
You may try this (Check Querying Relations on Laravel website):
$movies = Movie::whereHas('director', function($q) {
$q->where('name', 'great');
})->get();
Also if you reverse the query like:
$directorsWithMovies = Director::with('movies')->where('name', 'great')->get();
// Access the movies collection
$movies = $directorsWithMovies->movies;
For this you need to declare a hasmany relationship in your Director model:
public function movies()
{
return $this->hasMany('Movie');
}
If you want to pass a variable into function($q) { //$variable } then
function($q) use ($variable) { //$variable }
whereBelongsTo()
For new versions of Laravel you can use whereBelongsTo().
It will look something like this:
$director = Director::find(1);
$movies = Movie::whereBelongsTo($director);
More in the docs.
is()
For one-to-one relations is() can be used.
$director = Director::find(1);
$movie = Movie::find(1);
$movie->director()->is($director);

Resources