relations issue with laravel - laravel

I am trying to make games website, so i have one-to-many relation: one category has many games.
in my db, I have games' table and cats' table.
in the games' table I have a column named as 'cat_game_id' which reffers to the category's id, that the game belongs to.
my 'game' model looks like this
`
class Game extends Model {
protected $fillable = array(
'name',
'slug',
'description',
'instruction',
'url',
'cat_game_id',
'created_at',
'updated_at'
);
/*
* A game belongs to a category
*/
public function cat() {
return $this->belongsTo('App\catGame');
}
}
`
and i have another model called 'catGame':
`class catGame extends \Eloquent {
public $timestamps = false;
protected $fillable = array(
'name',
'location',
'slug'
);
/*
* A category has many games
*/
public function games() {
return $this->hasMany('App\Game');
}
}
`
In my index page I want to show the game's name, and next to it the category's name. so I did:
$view->game = Game::where('slug', '=', $slug)->firstOrFail();
$view->cat_name = $view->game->cat->name;
but I get this error:
Trying to get property of non-object
any ideas please?

Related

Laravel Eloquent query relations with 3 levels

I want some help of forming queries on Laravel Eloquent
I have 4 models in my application
Item Model
class Item extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'code', 'name', 'type', 'price', 'cost', 'reorder_level', 'status'
];
public function grnoteitems()
{
return $this->hasMany(Grnoteitem::class);
}
}
Grnote Model
class Grnote extends Model
{
use HasFactory;
protected $fillable = [
'date', 'number', 'warehouse_id','user_id', 'authorized_id', 'approved_id', 'notes'
];
public function grnoteitems()
{
return $this->hasMany(Grnoteitem::class);
}
public function warehouse()
{
return $this->belongsTo(Warehouse::class);
}
}
Grnoteitem Model
class Grnoteitem extends Model
{
use HasFactory;
protected $fillable = [
'grnote_id', 'item_id', 'description', 'packing', 'quantity', 'price', 'total'
];
public function grnote()
{
return $this->belongsTo(Grnote::class);
}
public function item()
{
return $this->belongsTo(Item::class);
}
}
Warehouse Model
class Warehouse extends Model
{
use HasFactory;
protected $fillable = ['name', 'address'];
public function grnotes()
{
return $this->hasMany(Grnote::class);
}
}
Quantity of the item is calculated by multiplying quantity and packing columns in the grnotes table.
Now I want to retrieve all the items with their quantity(quantity * packing) from a particular warehouse.
I tired the below query
$items = Item::withSum('grnoteitems', 'quantity', function($query) use($warehouse, $from, $to){
$query->with('grnote', function($query1) use($warehouse, $from, $to){
$query1->where('warehouse_id', $warehouse->id)
->whereBetween('date', [$from, $to])->get();
})->get();
})->get();
This is working fine. But I don't find any way to get sum of two multiplied columns
I want something like
$items = Item::withSum('grnoteitems', '(quantity * packing)', function($query) use($warehouse, $from, $to){
$query->with('grnote', function($query1) use($warehouse, $from, $to){
$query1->where('warehouse_id', $warehouse->id)
->whereBetween('date', [$from, $to])->get();
})->get();
})->get();
Please help me to solve this.
It's a bit long to write all the code to do this, but my idea would to :
start your query from the wareHouse you want items from
so Warehouse::first() [with grnote [with item]] and custom where stuff
then the data you need to calculate are on the pivot table between Item and Grnote, so I would add withPivot to both relations
in this query order, the pivot value will be appended as a relation to the Item object
I would add a new attribute to the item model. Checking if the pivot attribute is set (so it comes from a query with pivot), calculate the quantity, and append it to the Item instance
You can also loop on the resulting Collection to append your new attribute.

Problem relationship many to many on Laravel

I'm new to Laravel, I'm having this problem:
I have 2 tables, platos and ingredientes, these have a many to many relationship, and for this I use a third table called ingredientes_platos.
To save the relationship many to many I tried with the following:
$platos->ingredientes()->attach($input['ingredientes']);
but it gives the following error:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '151-3' for key 'PRIMARY' (SQL: insert into ingredientes_platos (platos_id, ingredientes_id, norma_bruta) values (151, 3, ))
Looking a bit in the documentation, I could solve with sync instead of attach, but this does not solve my problem, because in addition to saving the id's of the relationship I need to save other attributes in the pivot table.
It is important to note that if I try to save this data in a table other than ingredients_platos, I do not get this problem and the data is saved correctly no matter which method I use.
I appreciate your attention, I hope you can help me.
These are the models for the three tables:
Table Platos:
public $table = 'platos';
protected $dates = ['deleted_at'];
public $fillable = [
'Grupo',
'Nombre',
'Procedimiento',
'Cantidad',
'Unidad',
'Precio'
];
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'Grupo' => 'integer',
'Nombre' => 'string',
'Procedimiento' => 'string',
'Cantidad' => 'integer',
'Unidad' => 'integer',
'Precio' => 'double'
];
/**
* Validation rules
*
* #var array
*/
public static $rules = [
'Grupo' => 'required',
'Nombre' => 'required'
];
public function ingredientes()
{
return $this->belongsToMany(Ingredientes::class);
}
public function grupo_platos()
{
return $this->hasOne('App\Models\Grupo_Platos', 'id', 'Grupo');
}
}
Table Ingredientes:
public $table = 'ingredientes';
protected $dates = ['deleted_at'];
public $fillable = [
'Grupo',
'Nombre',
'Descripcion',
'Kcal',
'Proteinas',
'Grasas',
'Unidad',
'Precio'
];
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'Grupo' => 'integer',
'Nombre' => 'string',
'Descripcion' => 'string',
'Kcal' => 'double',
'Proteinas' => 'double',
'Grasas' => 'double',
'Unidad' => 'integer',
'Precio' => 'double'
];
/**
* Validation rules
*
* #var array
*/
public static $rules = [
'Nombre' => 'required'
];
public function platos()
{
return $this->belongsToMany(Platos::class);
}
}
Table Ingredientes_Platos:
public $table = 'ingredientes_platos';
public $fillable = [
'platos_id',
'ingredientes_id',
'norma_bruta',
'norma_neta',
'unidad_id'
];
public $timestamps = false;
}
Platos Controller:
public function store(CreatePlatosRequest $request)
{
$input = $request->all();
$platos = $this->platosRepository->create($input);
$id = $platos->id;
$ingredientes = $input['ingredientes'];
$norma_b = $input['norma_b'];
$t = sizeof($ingredientes);
$i=0;
for ($i = 0; $i < $t; $i++) {
$pivot = new Ingredientes_Platos;
$pivot->platos_id = $platos['id'];
$pivot->ingredientes_id = $ingredientes[$i];
$pivot->norma_bruta = $norma_b[$i];
$pivot->save();
}
Flash::success('Plato agregado correctamente.');
return redirect(route('platos.index'));
}
If you need one type to "belong" to another type multiple times, and vice versa, then the generic many-to-many relationship probably isn't a good fit for what you're trying to do. Not just because of the primary key constraint, but because you'll have cases in which multiple row results are returned for the relationship, and the many-to-many relationship won't know how to aggregate or group these. You may want to come up with a third type of Model that's something like an "attribute" that has relationships to the other two models and helps you accomplish your goal.
Thank you very much, my problem was solved. It happens that in addition to Laravel, I'm using InfyOM and this was creating a conflict when I was trying to manually add the records to the pivot table, because this line was already responsible for adding the registry to the pivot table: $ dishes = $ this-> dishesRepository-> create ($ input);
// Many to Many relationship in category Model to Post model coding here
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function posts()
{
return $this->belongsToMany('App\Post')->withTimestamps();
}
}
// Many to Many relationship in Post Model to Category model coding here
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function categories(){
return $this->belongsToMany('App\Category')->withTimestamps();
}
}

Many to Many Ajax Laravel 5.2

I have this code.
public function items( $subcategory_id ){
$items = $this->ajax->items( $subcategory_id );
return Response::json([
'success' => 'true',
'items' => $items
]);
}
And the output is:
As you can see the unit_id reference to many to many and you can't manipulate it to get the name of the unit_id in javascript. Do I need to loop it and create my own array or is there a function to do it.
Here is my repository code.
public function items( $subcategory_id ){
$this->modelName = new Subcategory();
return $this->modelName->find( $subcategory_id )->items;
}
My Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Subcategory extends Model
{
protected $table = 'subcategories';
protected $fillable = [
'qty', 'desc', 'unit_price', 'ext_price'
];
public function items(){
return $this->belongsToMany('App\Item', 'item_subcategory', 'subcategory_id', 'item_id')->withTimestamps();
}
}
Use eager loading. This will fetch the a specific Subcategory with its related Items and Units related to those items:
Subcategory::where('id', $subcategoryId)->with('items.unit')->get();

Return count of relation along with parent data

Hello i have two tables in my database:
categories
events
I have a page that displays a list of all categories. However i want to display a count of how many events are in each category next to the category title.
eg.:
comedy (10)
music (5)
The relationship between these two models is one to many, as one category can have zero or more events.
My question is how do i fetch the total number of events for each category along with the category data when i execute this code:
$categories = Category::get();
What i have tried so far:
class Categories extends Model implements SluggableInterface
{
use SluggableTrait;
protected $sluggable = [
'build_from' => 'name',
'save_to' => 'slug',
'on_update' => true,
];
protected $table = 'categories';
public function events() {
return $this->hasMany('App\Models\Events', 'category_id');
}
public function eventsCountRelation() {
return $this->hasMany('App\Models\Events', 'category_id')->selectRaw('id, count(*) as count');
}
public function eventsCountAttribute() {
return $this->eventsCountRelation->count();
}
}
The error i get:
foreach($categories as $categoriy) {
echo $category->name.' ('.$category->events->count().')';
}
Returns something like:
comedy (10)
music (5)
If you want to print it in a view you don't need to load them in the controller.
But if you want to print it as json you need something like this:
$categories = Category::all();
In the Category Model you need to add this:
protected $appends = ['counter'];
public function getCounterAttribute() {
return $this->events->count();
}
Update your class like this:
class Categories extends Model implements SluggableInterface
{
use SluggableTrait;
protected $sluggable = [
'build_from' => 'name',
'save_to' => 'slug',
'on_update' => true,
];
protected $appends = [
'counter'
];
protected $table = 'categories';
public function events() {
return $this->hasMany('App\Models\Events', 'category_id');
}
public function eventsCounterAttribute() {
return $this->events->count();
}
}
You don't need more.

Using properly of eager loading

I have two tables: contracts and contractitems. I want to display all my Contract items and have a search for searching the contractor name.
Contracts
id
contract_code
contractor_name
ContractItems
id
contracts_id
item_name
class ContractItems extends Eloquent {
protected $table = 'ContractItems';
protected $guarded = [ 'id' ];
public $timestamps = false;
public function contract()
{
return $this->hasOne('Contracts', 'id', 'contracts_id');
}
}
$x = ContractItems::with(array('contract' => function($query){
$query->where('contractor_name', 'LIKE' , '%name%');
}))->take(1)->get();
I tried the code above but it is not displaying the correct data.

Resources