nested hasmany relationship in laraval-admin - laravel

I am stuck in a nested hasmany relation. Here is a scenario where there are no units entered separately by the user and milestones in this form must be equal to the number of units and each unit can have multiple milestones. I was trying to loop but it is not working.
for($i = 1; $i <= $noOfUnit; $i++){
$form->hasmany('majorMilestone', 'Unit '.$i , function (Form\NestedForm $form) use($visitId, $projectId, $ps2EditId, $i) {
$form->hidden('project_id', 'ProjectId')->default($projectId);
$form->text('major_milestone', "Major Milestone")->prepend(false);
$form->date('scheduled', "Scheduled");
})->setWidth(9, 3);
}
more clarification
for example I have a text input on page one, where user add number of units. On second page I need to capture the completion date an remark in steps for each unit. Then I have looped the number of unit to get the below structure
and I have below model in place to add/modify data
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Step2 extends Model
{
protected $table = 'proj_clearence_bckwrd_frwrd_supply';
public $timestamps = false;
public function majormilestone1()
{
return $this->hasMany(Majormilestone::class,'edit_id')->where('unit_no', '1');
}
public function majormilestone2()
{
return $this->hasMany(Majormilestone::class,'edit_id')->where('unit_no', '2');
}
public function majormilestone3()
{
return $this->hasMany(Majormilestone::class,'edit_id')->where('unit_no', '3');
}
}
but this code is limited to three units only. I need to remove this dependency.
I hope this is clear now.
here is the code for MajorMilestone model.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class Majormilestone extends Model
{
protected $table = 'major_milestone';
protected $fillable = ['project_id', 'edit_id', 'visit_id', 'unit_no', 'major_milestone', 'scheduled', 'anticipated', 'actual', 'remarks'];
public $timestamps = false;
public function step2()
{
return $this->belongsTo(Step2::class,'edit_id');
}
}

Related

How to merge two collection of model and make it as one paginate then send it to the view in Laravel

I want to send two collection model to view and make it as one paginate......but im still confused when i want to paginate as the two collection models
Here's my model RefHoliday.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class RefHoliday extends Model
{
//
public $timestamps = false;
public $incrementing = false;
protected $table = 'refHoliday';
}
second model -- HDHolidayCalendar.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class HDHolidayCalendar extends Model
{
//
public $timestamps = false;
public $incrementing = false;
protected $table = 'Holiday_Calendar';
}
holiday controller
public function index()
{
$refHol = RefHoliday::all();
$HolCal = HDHolidayCalendar::all();
// $paginationRecord = ??
return view('administration.holiday.HolidayMasterList', compact('??'));
}
I try to explore to solve this things but seems not clearly explain...
To merge two collection.
$refHol = RefHoliday::all();
$holCal = HDHolidayCalendar::all();
$data = $refHol->merge($holCal);

laravel where condition with the % operator

today i'm trying to get modulus operator in where laravel clause but i can't get it work and after make some google researches and read the documentation i post this may be some one can help me to get a solution
Produit::has('caracteristique.image', '=', 2)
//->where('(caracteristique.image.caracteristique_id)', '=', 2)
->has('caracteristique.stock')
->where('market_id', Auth()->user()->market->id)
->where(DB::raw('count(`produits`.`caracteristiques`.`images`.`caracteristique_id`)'), '%2', [2])
->get();
i hope to select all products that have a relation with caracteristique table and for each caracteristique i have to find 2 iamge that come from the images table
i make this also
->has('caracteristique.image', '=', 2)
but the problem is this code is not ensure for each caracteristique like i can get 1 product with 2 caracteristique and 3 image but i suppose to have 4 image hope you understand my problem and hope you will help me to find a solution. thank you
here we have the models
produit
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\{
Market,
Caracteristique,
};
class Produit extends Model
{
protected $fillable = ['nom', 'detail', 'rabais', 'statut','demande', 'market_id'];
public function caracteristique()
{
return $this->hasMany(Caracteristique::class);
}
public function market()
{
return $this->belongsTo(Market::class);
}
}
caracteristique
namespace App\Models;
use App\Models\{
Produit,
Stock,
Image,
};
use Illuminate\Database\Eloquent\Model;
class Caracteristique extends Model
{
protected $fillable = [
'produit_id', 'couleur', 'prix', 'quantite', 'size', 'disponible',
];
public function produit()
{
return $this->belongsTo(Produit::class);
}
public function stock()
{
return $this->hasOne(Stock::class);
}
public function image()
{
return $this->hasMany(Image::class);
}
}
image
namespace App\Models;
use App\Models\{
User,
Caracteristique,
};
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
protected $fillable = [
'caracteristique_id', 'user_id', 'nom'
];
public function caracteristique()
{
return $this->belongsTo(Caracteristique::class);
}
public function user(){
return $this->belongsTo(User::class);
}
}
produit can have multiple caracterisque but for each caracteristique it must have 2 images how i can i write this query to avoid query caractristique with one or doesn't have any image please?
and it just say error sql at line one after the %2 condition.

How can you use Eloquent to find related values two tables away and in a different database?

I am developing a system that extends an existing ERP system, and so is accessing two databases (both on the same MS SQL Server). I am trying to access items on the "Equipment" model (this is a table in the ERP database) through the "EquipmentInstance" model from the "EquipmentType" model (these two are in the new database). They are related as per this diagram:
The three models are as follows:
EquipmentType
namespace App;
use Illuminate\Database\Eloquent\Model;
class EquipmentType extends Model
{
protected $table = 'dbo.EquipmentType';
protected $connection = 'sqlsrv';
protected $primaryKey = 'EquipmentTypeID';
protected $fillable = [
'TypeName',
'ProductManager'
];
public function EquipmentInstance()
{
return $this->hasMany(EquipmentInstance::class,'EquipmentTypeID', 'EquipmentTypeID');
}
public function Equipment()
{
return $this->hasManyThrough(
Equipment::class,
EquipmentInstance::class,
'TypeID',
'PartNum',
'TypeID',
'PartNum'
);
}
}
EquipmentInstance
namespace App;
use Illuminate\Database\Eloquent\Model;
class EquipmentInstance extends Model
{
protected $table = 'dbo.EquipmentInstance';
protected $primaryKey = 'EquipmentID';
protected $keyType = 'string';
protected $connection = 'sqlsrv';
protected $fillable = [
'EquipmentID',
'EquipmentTypeID',
'PartNum'
];
public function Part()
{
return $this->belongsTo(Part::class,'PartNum','PartNum');
}
public function Equipment()
{
return $this->hasMany(Equipment::class,'PartNum', 'PartNum');
}
public function EquipmentType()
{
return $this->belongsTo(EquipmentType::class); /*,'EquipmentTypeID', 'EquipmentTypeID'*/
}
/* public function Attribute()
{
return $this->belongsTo(Equipment::class,'SerialNumber', 'JobNum');
}
public function TechNote()
{
return $this->belongsTo(Equipment::class,'SerialNumber', 'JobNum');
}*/
}
Equipment
namespace App;
use Illuminate\Database\Eloquent\Model;
class Equipment extends Model
{
protected $table = 'ERP.SerialNo';
public $timestamps = false;
protected $primaryKey = 'SerialNumber';
protected $keyType = 'string';
protected $connection = 'epicor';
public function Part()
{
return $this->belongsTo(Part::class,'PartNum','PartNum');
}
public function Customer()
{
return $this->belongsTo(Customer::class,'CustNum', 'CustNum');
}
public function Equipment()
{
return $this->belongsTo(Equipment::class,'SerialNumber', 'JobNum');
}
public function EquipmentInstance()
{
return $this->belongsTo(EquipmentInstance::class,'PartNum', 'PartNum');
}
}
On the EquipmentType Controller I am trying to get all of the Equipment through the EquipmentInstance so for each EquipmentInstance I can display all of the Equipments.
EquipmentType Controller
public function show(EquipmentType $EquipmentType)
{
$EquipmentInstance = $EquipmentType->EquipmentInstance()
->get();
$Equipments = $EquipmentType->EquipmentInstance()->Equipment()
->get();
return view('EquipmentType.show', compact('EquipmentType', 'EquipmentInstance', 'Equipments'));
}
The error message I get is
"BadMethodCallException
Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::Equipment()"
I believe the issue is that (my understanding is rocky) that Eloquent is trying to write one query to access both databases, which is failing. However I am not sure how to proceed.
Any help would be greatly received.
Richard
Update
I have implemented what gbalduzzi suggested in his answer, which almost worked, and I am sure the issue is with my blade implemtention. I have nested two forloops:
#foreach($EquipmentType->EquipmentInstance as $EquipmentInstance)
#foreach($Equipments as $Equipment)
<tr>
<td>{{$EquipmentInstance->PartNum}} - {{$EquipmentInstance->Part->PartDescription}}</td>
<td>{{$Equipment->SerialNumber}}</td>
<td>{{$Equipment->SNStatus}}</td>
<td>{{--{{$Equipment->Customer->LegalName}}--}}</td>
</tr>
#endforeach
#endforeach
Which is displaying the serial numbers (from the Equipment model) for the first EquipmentInstance only and repeating them for all EquipmentInstanced.
Update 2
I have proven that the issue is with first() in the suggested answer, as if I change this to last() the results change as you would expect (see update 1). So my question now is:
Is there an equivelant of first(), last() which is all() or every()?
The problem is not in your database configuration, but in the way you are calling the relationship. Instead of:
$Equipments = $EquipmentType->EquipmentInstance()->Equipment()
->get();
use:
$Equipments = $EquipmentType->EquipmentInstance->first()->Equipment()
->get();
Long answer
In Eloquent, you can use a relationship in 2 ways:
as a magic field (i.e. $EquipmentType->EquipmentInstance). In this case you get as a result an instance of the model EquipmentInstance (also, if you already queried it, it directly returns the value without executing a new query)
as an eloquent query (i.e. $EquipmentType->EquipmentInstance()). Using it as a function, you don't get the model but a RelationShip instance, that is basically an eloquent query and can be chained with other eloquent methods, such as where, orderBy, ecc
So, if you call $EquipmentType->EquipmentInstance()->Equipment() it throws an error because the eloquent query does NOT have the relationship Equipment().
On the other hand, $EquipmentType->EquipmentInstance->Equipment works because it calls Equipment on the actual model instance, that has the Equipment relationship properly defined.

Custom attribute crashing on toJSON

I am trying to determine which position the order is in to generate a order id, but this crashes laravel, nothing in the logs, just a 500 error in the browser:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Load extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $guarded = ['id', 'created_at', 'updated_at'];
protected $appends = ['order_no'];
public function workorder()
{
return $this->belongsTo('App\WorkOrder', 'work_order_id');
}
public function getOrderNoAttribute()
{
$count = 1;
foreach ($this->workorder->loads as $load) {
if ($load->id == $this->id) {
break;
}
$count++;
}
return $this->workorder->id . "-" . $count;
}
}
When I changed it to return just an integer it worked, so I am almost certain it is the relation access causing the issue. Is there a way to do this that is better?
Generally while defining calculated attributes, dependence on relationship should be avoided. So one way to achieve what you are trying is (as you mentioned solved) is to get all loads having the same work_orderid and proceed with it.
public function getLoadCountAttribute ()
{
$id = $this->work_order_id;
return static::where('work_order_id', $id)->count();
}
Another way, more logical I guess, would be to define a relationship and eager load
//define a relation in your Load model
public function load_count ()
{
return count($this->workorder->loads)
//-1 if you want to exclude the current load from count
;
}
//Then use Load::with('load_count') to eager load the load_count
//You may also use global scope
Yet another way would be to define a static function on Workorder model, which will accept an id and return the load_count
//Workorder model
public static function getLoadCount($id)
{
$workorder = static::findOrFail($id);
return count($workorder->loads);
}
Hope this helps.

How can define a custom price based on other product attributes Laravel

I am working on a webshop where the products are tires (car tires)
I've deciced to go with Laravel as PHP framework.
I want to return a price in my model, the price is not static but is based on other values in the model. (the thickness of the weel)
How can I make a function in my controller or model which checks for other values for the specific tire.
I think I should make it in the model or controller but don't know how to do this.
I suppose one way of doing would be the following:
App\Models\Tires.php
<?php
namespace App\Models\Tires;
use Illuminate\Database\Eloquent\Model;
class Tires extends Model {
protected $connection = 'mysql';
protected $primaryKey = 'id';
protected $table = 'tires';
protected $fillable = array(
'brand',
'model',
'thickness,
'price'
);
public $timestamps = true;
}
App\Http\Controllers\TiresController.php
<?php
namespace App\Http\Controllers;
use App\Models\Tires;
use App\Functions\CalcTires;
class TiresController extends Controller
{
public function customPrice()
{
$findtires = Tires::all();
foreach ($findtires as $_findtires)
{
$calcprice = new CalcTires($_findtires->thickness);
$_findtires->price = $calcprice->getCustomPrice();
$_findtires->save();
}
}
}
App\Models\Functions\CalcTires.php
<?php
namespace App\Models\Functions;
class CalcTires {
var $price;
function __construct($thickness) {
if ($thickness >= 15 && $thickness <= 20)
{
$this->price = 50;
}
elseif ($thickness >= 21 && $thickness <= 25)
{
$this->price = 60;
}
}
function getCustomPrice() {
return $this->price;
}
}
This is adding an extra "Price" column to your table model and also utilizing a function to do the price calculation and lastly saving it back to your database.
Of course you could always pre-calculate all this yourself and save yourself the trouble before importing the data into your database.

Resources