I have four models with many to many relationship
Users
-id
-Email
-Password
Student
-id
-Name
-school
---------
Subject
-id
-subname
Topic
-id
-topName
-sub_id
--------
When they broke down produce their respective pivot tables
i.e
-student_user
-id
-student_id
-user_id
-student_subject
-id
-studdent_id
-subject_id
-subject_name
-student_topic
-id
-student_id
-topic-id
-topic_name
-.........
I want to insert them with multiple selecting of the inputs i.e subject and topics must more than one.
What i failed is how to insert them into a data at the same time with such kind of relation since i used for each loop and i failed to figure out what attribute i can use to??
Topics and subjects datas are insided DB inserted already
Help
<table class="table table-striped" id="table_tuition_fee">
<thead>
<tr>
<td><label for="subject">Subject</label></td>
<td><label for="topic">Topic</label></td>
<td><label for="Amount">Amount</label></td>
<td><a class="bg-light btn btn-info addRow" href="#"><i class="fa fa-plus"></i></a></td>
</tr>
</thead>
<tbody>
<tr>
<td>
<select class="form-control subject_selected" name="subject[]" id="subject" data-uid="0">
<option value=" ">---Select Subject---</option>
#foreach($subject_list as $subject)
<option value="{{ $subject->id }}">{{ $subject->SubjectName }}</option>
#endforeach
</select>
</td>
<td>
<select class="form-control topic_selected" name="topic[]" id="topic" data-uid="0">
</select>
</td>
<td>
<input type="text" class="form-control" name="Amount[]" id="Amount"/>
</td>
<td>
X
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td style="border: none"></td>
<td style="border: none"></td>
<td style="border: none"></td>
<td><button class="btn btn-success" id="add_student">SEND</button></td>
</tr>
</tfoot>
</table
class Topic extends Model
{
//
protected $fillable = [
'TopicName'.'Subject_id'
];
public function students(){
return $this->belongsToMany(Student::class)->withTimestamps();
}
public function subject(){
return $this->belongsTo(Subject::class);
}
}
class User extends Authenticatable
{
use Notifiable ,HasRoles;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'FullName'.'EmployeeNumber','password',
];
.
.
.
.
.
public function buyers(){
return $this->belongsToMany(Buyer::class)->withTimestamps();
}
public function students(){
return $this->belongsToMany(User::class)->withTimestamps();
}
}
class Student extends Model
{
//
protected $fillable = [
'FullName'.'School','Combination','Phone','Type','Stream'
];
public function users(){
return $this->belongsToMany(User::class)->withTimestamps();
}
public function subjects(){
return $this->belongsToMany(Subject::class)->withTimestamps();
}
public function topics(){
return $this->belongsToMany(Topic::class)->withTimestamps();
}
}
class Subject extends Model
{
protected $fillable = [
'SubjectName',
];
public function students(){
return $this->belongsToMany(Student::class)->withTimestamps();
}
public function topics(){
return $this->hasMany(Topic::class);
}
}
public function store(Request $request)
{
/*$this->validate($request,[
'FullName' => 'requred|string',
]);*/
$student = new Student();
$student->FullName = $request->input('FullName');
.
.
.
.;
$id = $student->save();
//$user = User::find(auth()->user()->id);
if ($id != 0){
$condition = $request->input('subject');
/*$student->subjects()->create([
'subject_name'=>$request->input('subject')
]);*/
foreach ( $condition as $key => $av){
$data =array([
'subject_id' => $request->input('subject')[$key],
'subject_name' => $request->input('subject')[$key],
'topic_name' => $request->input('topic')[$key],
'Price' => $request->input('Amount')[$key]
]);
$student->subjects()->attach($data);
}
}
return Response()->json($student);
}
I made it my self as follows
public function store(Request $request)
{
$student = new Student();
$student->FullName = $request->input('FullName');
.
.
.
$student->Stream = $request->input('Stream');
$id = $student->save();
if ($id != 0){
$condition = $request->subject; //ACCESS SUBJECT NAME ARRAY subject[]
$condition1 = $request->topic; //ACCESS SUBJECT NAME ARRAY topic[]
foreach ( $condition as $key => $av){
$data =array([
'subject_id' => $request->subject[$key]
]);
$student->subjects()->attach($data);
}
foreach ( $condition1 as $key_topic => $av_topic){
$data2 = array([
'topic_id' => $request->topic[$key_topic],
'Price' => $request->Amount [$key_topic]
]);
$student->topics()->attach($data2);
}
$student->users()->attach(auth()->user()->id);
}
$status = 'Failed To Register' ;
if($student){
$status = 'Student Successfully Added';
}
return redirect()->back()->with('status' ,$status);
}
Related
I'm using AlpineJs and Livewire in an application. I'm new to livewire, Here I want to Update the post name which is showing from a component inside another component. To reuse those I have separated those also there have lots of other features with complex logic.
Problem
The post name isn't changing, Not even fire the wire:model.
#post.table
#foreach ($posts as $index => $post)
<tr>
<td> {{ Str::limit($post->name, 22) }}</td>
<td> {{ $post->description }}</td>
<td> {{ $post->date }}</td>
<td> {{ $post->amount }}</td>
</tr>
<template x-if="some_condition">
<tr>
<livewire:post.post-details :post="$post" :index="$index">
</tr>
</template>
#endforeach
//pagination here
#post.post-details
class PostDetails extends Component
{
protected $post;
public $index;
public function mount($post, $index)
{
$this->post = $post;
$this->index = $index;
}
public function render()
{
return view('livewire.post.post-details', [
'post' => $this->post,
]);
}
}
<div>
<livewire:post.post-name :post="$post" :index="$index">
// Other components are here
</div>
#post.post-name
class PostName extends Component
{
public $post_name;
public $index;
protected $rules = [
'update_post.*.name' => 'required|string',
];
public function mount($schedule_entry, $index)
{
$this->post_name = $post->name;
$this->index = $index;
}
public function render()
{
return view('livewire.post.post-name');
}
public function some_action()
{
//
}
}
<div>
<input type="text" wire:model="update_post.{{ $index }}.name" wire:keydown="some_action" value="{{ $post_name }}">
</div>
If you guys have any better idea to reuse those component feel free to share. Thanks
I have try this two way
https://laravel-livewire.com/docs/2.x/properties#binding-models
https://laracasts.com/discuss/channels/livewire/livewire-save-fields-with-same-name
#foreach($posts as $post)
<tr>
<th scope="row">{{$post->id}}</th>
<td><img src="{{asset('img/') . '/' .$post->file_path}}" width="100px " height="50px" class="img_table"></td>
<td>{{$post->post_name}}</td>
<td>{{$post->name}}</td>
<td>
#if(strcmp($post->status , 'Published') == 0)
<div class="btn btn-success">{{$post->status}}</div>
#else
<div class="btn btn-warning">{{$post->status}}</div>
#endif </td>
<td>{{$post->created_at->diffForHumans()}}</td>
<td>{{$post->slug}}</td>
<td>{{$post->cat->game_category_id}}</td>
<td><i class="far fa-edit"></i></td>
<td><i class="far fa-trash-alt"></i></td>
</tr>
#endforeach
Post Model
protected $table = 'posts';
protected $fillable = [
'post_name',
'post_content',
'name',
'status',
'file_path',
'slug',
'game_category_id'
];
public function cat(){
return $this->belongsTo('App\cat');
}
Cat Model
use HasFactory;
protected $table = 'cats';
protected $fillable = ['name','slug'];
public function post(){
return $this->hasMany('App\post');
}
Relationship model name is false, must be as the name of them Model
please use class Cat::class is better and readable
public function cat(){
return $this->belongsTo(Cat::class);
//return $this->belongsTo('App\Cat');
}
Same for post
public function post(){
return $this->hasMany(Post::class);
}
Change this line:
<td>{{$post->cat->game_category_id}}</td>
to:
<td>{{$post->cat ? $post->cat->game_category_id : ''}}</td>
It first checks if the related cat exists, if it is, then gets the id, else it returns an empty string.
Attempt to read property "game_category_id" on null (View: E:\xampp\htdocs\Blog\resources\views\layout\show.blade.php)
In my Laravel-5.8 project, when an employee logs in I want to display a table as shown below that shows his Leave Balance
I have 3 tables that are applicable
class LeaveCategory extends Model
{
protected $table = 'leave_categories';
protected $fillable = [
'leave_category_name',
];
public function leavecategorydetail()
{
return $this->hasMany('App\Models\LeaveCategoryDetail');
}
}
class LeaveCategoryDetail extends Model
{
protected $table = 'leave_category_details';
protected $fillable = [
'id',
'leave_category_id',
'employment_type_id',
'no_of_days',
];
public function leavecategory()
{
return $this->belongsTo('App\Models\LeaveCategory', 'leave_category_id', 'id');
}
public function employmenttype()
{
return $this->belongsTo('App\Models\EmploymentType', 'employment_type_id', 'id' );
}
}
class LeaveRequest extends Model
{
protected $table = 'leave_requests';
protected $fillable = [
'id',
'employee_id',
'leave_category_id',
'leave_status',
'approved_days',
];
public function employee()
{
return $this->belongsTo('App\Models\Employee','employee_id');
}
public function leavetype()
{
return $this->belongsTo('App\Models\LeaveCategory','leave_category_id');
}
}
As earlier said, the expected result is to have 4 columns (Leave Category
, Applicable Leave, Approved Leave
, Available
)
Controller
public function leave_balance()
{
$userId = Auth::user()->id;
$userCompany = Auth::user()->company_id;
$employmentcategory = Employee::select('employeement_category_id')->where('employee_id', $userId)->where('is_active', 1)->first();
//Leave Category
$leavecategories = LeaveCategory::select('leave_category_name')->where('company_id', $userCompany)->get();
//Applicable Leave
$applicableleaves = DB::table('leave_categories')
->join('leave_category_details', 'leave_category_details.leave_category_id', '=', 'leave_categories.id')
->select('leave_category_details.no_of_days')
->where('leave_categories.company_id', $userCompany)
->where('leave_categories.employment_category_id',$employmentcategory)
->get();
//Approved Leave
$approvedleaves = DB::table('leave_requests')
->select('employee_id','leave_category_id', DB::raw('SUM(approved_days) AS approvedLeave'))
->where('employee_id', $userId)
->where('leave_category_id', $employmentcategory)
->where('leave_status',4)
->groupBy('employee_id', 'leave_category_id')
->get();
//Available
$availableleaves = $applicableleaves - $approvedleaves
$leavebalances = ...
return view('leave-balances')
->with('leavebalances', $leavebalances)
}
How do I combine the four queries in my controller ($leavecategories, $applicableleaves, $approvedleaves, $availableleaves) into $leavebalances and also get a view like
See the leave balance image
<thead>
<tr>
<th width="55%">
Leave Category
</th>
<th width="15%">
Applicable Leave
</th>
<th width="15%">
Approved Leave
</th>
<th width="15%">
leavebalances
</th>
</tr>
</thead>
<tbody>
<!--start foreach-->
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<!--end foreach-->
If there is no field/value for $approvedleaves, it should initialize with 0
Thank you.
bro you can try make the two querys in one like this is not perfect but you get the idea
$all = DB::table('leave_category_details')
->leftJoin('leave_categories', function($join)
{
$join->on('leave_categories.id', '=', 'leave_category_details.leave_category_id');
$join->on('leave_categories.employment_category_id',$employmentcategory);
$join->on('leave_categories.company_id','=', $userCompany);
})
->leftJoin('leave_requests', function($join)
{
$join->on('leave_requests.employee_id', '=', $userId);
$join->on('leave_requests.leave_category_id', $employmentcategory);
$join->on('leave_status',4);
})
->groupBy('leave_requests.employee_id', 'leave_requests.leave_category_id')
->select('leave_category_details.no_of_days','leave_requests.employee_id','leave_requests.leave_category_id', DB::raw('SUM(leave_requests.approved_days) AS approvedLeave'),DB::raw('SUM(leave_requests.approved_days) - leave_category_details.no_of_days AS availableleaves')
->get();
Why get each column in a separate query when you can get them all in one.
I adjusted your controller like so:
public function leave_balance()
{
$userId = Auth::user()->id;
$userCompany = Auth::user()->company_id;
$employmentCategoryId = Employee::where('employee_id', $userId)->where('is_active', 1)->value('employeement_category_id');
//Leave Table
$leaveTable = DB::table('leave_categories as lc')
->join('leave_category_details as lcd', 'lcd.leave_category_id', '=', 'lc.id')
->join('leave_requests as lr', 'lr.leave_category_id', '=', 'lc.id')
->select('lcd.no_of_days as applicableLeaves ','lc.leave_category_name as leaveCategory',DB::raw('SUM(lr.approved_days) AS approvedLeaves'))
->where([
['lc.company_id', $userCompany],
['lc.employment_category_id',$employmentCategoryId],
['lr.employee_id', $userId],
['lr.leave_status',4]
])
->groupBy('leaveCategory', 'applicableLeaves')
->get();
return view('leave-balances')
->with('leaveTable', $leaveTable)
}
$availableleaves can be calculated in the view no need to send it.
Now in your view you display them like this:
<thead>
<tr>
<th width="55%">
Leave Category
</th>
<th width="15%">
Applicable Leave
</th>
<th width="15%">
Approved Leave
</th>
<th width="15%">
leavebalances
</th>
</tr>
</thead>
<tbody>
#foreach ($leaveTable as $tableRow)
<tr>
<td>
{{$tableRow->leaveCategory}}
</td>
<td>
{{$tableRow->applicableLeaves}}
</td>
<td>
#if(!$tabelRow->approvedLeaves->isEmpty()){{$tabelRow->approvedLeaves}}#else 0 #endif
</td>
<td>
{{($tableRow->applicableLeaves - $tabelRow->approvedLeaves)}}
</td>
</tr>
#endforeach
</tbody>
HTML is not my strongest field so your table might not show as wanted but i think its all good.
I'm using Laravel 6 and I want to foreach a hasMany relationship between Layanan Model and Objek Model
Layanan Model
class Layanan extends Model
{
protected $fillable = ['nama_layanan'];
protected $primaryKey = 'layanans_id';
public function objeks()
{
return $this->hasMany(Objek::class);
}
}
Objek Model
class Objek extends Model
{
protected $fillable = ['layanan_id', 'tipe_objeks'];
protected $primaryKey = 'objeks_id';
public function layanan()
{
return $this->belongsTo(Layanan::class);
}
}
Controller.php
class ObjekController extends Controller
{
public function object()
{
$objek = \App\Objek::all();
return view('pages.alat.object.object')->with('data', $objek);
}
}
View
#foreach ($data as $item)
#foreach ($item->layanan as $layanan)
<tr>
<td>{!! $item->objeks_id !!}</td>
<td>{!! $layanan->layanan_id !!},</td>
<td>{!! $item->tipe_objeks !!}</td>
<td>{!! $item->created_at->format('d/m/Y') !!}</td>
<td>{!! $item->updated_at->format('d/m/Y') !!}</td>
</tr>
#endforeach
#endforeach
I get the error
Invalid argument supplied for foreach()
What did I do wrong? Sometimes, it says that 'layanan' is non-object.
class Objek extends Model
{
protected $fillable=[
'layanan_id', 'tipe_objeks'
];
protected $primaryKey = 'objeks_id';
public function layanan() {
return $this->hasMany(Layanan::class,'layanan_id','layanan_id');
}
}
if you put Objek hasMany layanan
then only u can loop over 1 row of Objek
like $data = Objek::find(1(=);
foreach($data as $layanan)
Just update your view as below to add if condition to check wheather relationship values exist for each record.
#foreach ($data as $item)
#if($item->layanan->count())
#foreach ($item->layanan as $layanan)
<tr>
<td>{!! $item->objeks_id !!}</td>
<td>{!! $layanan->layanan_id !!},</td>
<td>{!! $item->tipe_objeks !!}</td>
<td>{!! $item->created_at->format('d/m/Y') !!}</td>
<td>{!! $item->updated_at->format('d/m/Y') !!}</td>
</tr>
#endforeach
#endif
#endforeach
My problem was exactly what you got. I can't loop collection from hasMany relationship.
I'd solved by converting data into object instead of collection.
public function convertToObject($data) {
return json_decode(json_encode($data), FALSE);
}
public function object() {
$objek = \App\Objek::all();
$objek = $this->convertToObject($objek);
return view('pages.alat.object.object')->with('data', $objek);
}
when you define relationship it will take id as PK so good practice define FK and PK like below
class Layanan extends Model
{
protected $fillable=[
'nama_layanan'
];
protected $primaryKey = 'layanans_id';
public function objeks() {
return $this->hasMany('App\Objek', 'layanan_id', 'layanans_id');
}
}
then you need to use IF()
#foreach ($data as $item)
#if(isset($item->layanan)) //// #if($item->layanan && is_array($item->layanan)) or #if(count($item->layanan) > 0)
#foreach ($item->layanan as $layanan)
#endforeach
#endif
#endforeach
UPDATE
as per your relationship if you take data from Objek then use like this
#foreach ($data as $item)
<tr>
<td>{!! $item->objeks_id !!}</td>
<td>{!! $item->layanan->layanans_id !!},</td>
<td>{!! $item->tipe_objeks !!}</td>
<td>{!! $item->created_at->format('d/m/Y') !!}</td>
<td>{!! $item->updated_at->format('d/m/Y') !!}</td>
</tr>
#endforeach
Get user's answer , question in page by user id , i want to display table for each user contains his answers with questions
I tried to create show page and add show function in UserController
Controller :
public function show($id)
{
$user = User::find($id);
$user_id = $user->id;
$survey = \App\Survey::pluck('title', 'id')->toArray();
$answers = \App\Answer::where('user_id','=',$user_id)->get();
return view('users.show', compact('user','survey','answers'));
}
view:
<table class="table">
<thead class="thead-light">
<tr>
<th>{{ __('Question') }}</th>
<th>{{ __('Answers') }}</th>
<th>{{ __('Creation Date') }}</th>
</tr>
</thead>
<tbody>
#foreach($answers as $t)
<tr>
<td> {{ optional($t->survey)->title }} </td>
<td> {{ $t->answer }} </td>
<td> {{$t->created_at}} </td>
</tr>
#endforeach
</tbody>
</table>
Answer model :
class Answer extends Model
{
protected $fillable = ['answer','commentaire','user_id','survey_id','last_ip'];
protected $table = 'answer';
public function survey()
{
return $this->belongsTo('App\Survey', 'survey_id');
}
public function question()
{
return $this->belongsTo(Question::class);
}
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
}
user model :
public function questions()
{
return $this->hasMany(Question::class);
}
public function answers()
{
return $this->hasMany(Answer::class);
}
the tables :
answer :
Survey :
I got empty part for question row
You are performing some queries that you actually don't need.
First get rid of this to lines:
$user_id = $user->id; $survey = \App\Survey::pluck('title', 'id')->toArray();
Then change your query to get your answers:
$answers = \App\Answer::where('user_id','=',$user->id)->with(['survey'])->get();
return view('users.show', compact('user','answers'));
Now in your view you could just do this:
<td> {{ $t->survey->title }} </td>
<td> {{ $t->answer }} </td>
<td> {{$t->created_at}} </td>