my route in web.php
Route::post('delete_master_cuti', [CompanyMasterCutiController::class, 'delete_master_cuti'])->name('delete_master_cuti');
my model in App\Models, I've added the company_id and year to be for the primary key
class CompanyMasterCuti extends Model
{
use HasFactory;
protected $table = 'company_master_cuti';
protected $fillable = [
'company_id', 'year', 'cuti', 'created', 'created_by', 'modified', 'modified_by',
];
protected $guarded = [];
protected $keyType = 'string';
public $timestamps = false;
protected $primaryKey = ['company_id', 'year'];
public $incrementing = false;
public function company() {
return $this->belongsTo('App\Models\Company', 'company_id', 'id');
}
}
my code in controller
public function delete_master_cuti(Request $request) {
$master_cuti = CompanyMasterCuti::where($request->company_id)->where($request->year);
$master_cuti->delete();
toast('Successfull', 'success');
return redirect()->route('master-cuti.index');
}
index.blade.php, in this code i just added company_id, i also don't know how to call year.
<a href="javascript:void(0)" data-id="{{ $m_cuti->company_id }}" onclick="$('#master_cuti_ids').val($(this).data('company_id')); $('#deleteModalBu').modal('show');">
<i class="badge-circle badge-circle-light-secondary bx bxs-trash font-medium-1 text-danger my-1"></i>
</a>
form action to delete function delete data in index.blade.php
<form id="form-edit" action="{{ route('delete_master_cuti') }}" method="POST">
#csrf
<div class="modal-body">
<input type="hidden" id="master_cuti_ids" name="company_id">
<div class="row no-gutters">
<div class="col-md-6">
<button type="submit" class="btn btn-danger ml-1" style="width: 100%">
<i class="bx bx-check d-block d-sm-none"></i>
<span class="d-none d-sm-block">Delete</span>
</button>
</div>
</div>
</div>
</form>
I want to delete data based on company_id and year but for now all the same company_id is deleted, I want the data to be deleted according to what the user chooses, not all company_ids. is there any solution for my problem?
there is a workaround and you should override the Model method
protected function setKeysForSaveQuery($query)
{
$query
->where('company_id', '=', $this->getAttribute('company_id'))
->where('year', '=', $this->getAttribute('year'));
return $query;
}
After reading a lot I found this
https://blog.maqe.com/solved-eloquent-doesnt-support-composite-primary-keys-62b740120f
This worked for me to delete a record with 2 primary keys like you.
Related
I want to delete data based on company_id and year from my database.
sample data content
my route in web.php
Route::post('delete_master_cuti/{company_id}/{year}', [CompanyMasterCutiController::class, 'delete_master_cuti'])->name('delete_master_cuti');
my model in App\Models, I've added the company_id and year to be for the primary key
class CompanyMasterCuti extends Model
{
use HasFactory;
protected $table = 'company_master_cuti';
protected $fillable = [
'company_id', 'year', 'cuti', 'created', 'created_by', 'modified', 'modified_by',
];
protected $guarded = [];
protected $keyType = 'string';
public $timestamps = false;
protected $primaryKey = ['company_id', 'year'];
public $incrementing = false;
public function company() {
return $this->belongsTo('App\Models\Company', 'company_id', 'id');
}
}
my code in controller. when I return the results of the $master_cuti data I get the last data I entered, not the data I selected
public function delete_master_cuti(Request $request) {
$master_cuti = CompanyMasterCuti::where($request->company_id)->where($request->year);
$master_cuti->delete();
toast('Successfull', 'success');
return redirect()->route('master-cuti.index');
}
in index.blade.php I have defined the data to be deleted based on the selected company_id and year
<a href="javascript:void(0)" onclick="$('#company_id','#year').val($(this).data(['company_id','year'])); $('#deleteModalBu').modal('show');">
<i class="badge-circle badge-circle-light-secondary bx bxs-trash font-medium-1 text-danger my-1"></i>
</a>
form delete modal
<form id="form-edit" action="{{ route('delete_master_cuti', [$m_cuti->company_id, $m_cuti->year] ) }}" method="POST">
#csrf
<div class="modal-body">
<input type="hidden" id="company_id" name="company_id">
<input type="hidden" id="year" name="year">
<div class="row no-gutters">
<div class="col-md-6">
<button type="button" class="btn btn-light-secondary" data-dismiss="modal"
style="width: 100%;">
<i class="bx bx-x d-block d-sm-none"></i>
<span class="d-none d-sm-block">CANCEL</span>
</button>
</div>
<div class="col-md-6">
<button type="submit" class="btn btn-danger ml-1" style="width: 100%">
<i class="bx bx-check d-block d-sm-none"></i>
<span class="d-none d-sm-block">DELETE</span>
</button>
</div>
</div>
</div>
</form>
I want to delete data based on the company_id and year I chose, but why is the deleted data the last time I entered? how to solve my problem? anyone, help me.
Have you check the response from "public function delete_master_cuti(Request $request)" by return $request->all(), whether company_id & year in method?
you must specify the column name (company_id and year) in the query. for example :
public function delete_master_cuti(Request $request) {
$request->validate([
'company_id' => 'required',
'year' => 'required'
]);
$master_cuti = CompanyMasterCuti::where('company_id',$request->company_id)->where('year', $request->year);
$master_cuti->delete();
toast('Successfull', 'success');
return redirect()->route('master-cuti.index');
}
and add softDelete in your model and add deleted_at column in your database table
use Illuminate\Database\Eloquent\SoftDeletes;
class CompanyMasterCuti extends Model
{
use HasFactory, SoftDelte;
...
}
and you can add the code in your blade file for show validation error
#if(count($errors) > 0)
<div>
<ul>
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
</ul>
</div>
#endif
I am new developer, and I seem to be stuck on handling arrays in laravel. I am using Laravel 8, and I cant seem to solve this situation.
I am building an internal recruitment site, where once a manager posts a job, employees will be able to apply to those specific jobs. I have defined the table in the database to have the "applicants" as an array consisting of the user_id's. However, I seem to not be able to add more than one array to it.
Below is my Recruitment Model
class Recruitment extends Model
{
use HasFactory;
protected $fillable = [
'title',
'salary',
'term_start',
'term_end',
'deadline',
'details',
'status',
'applicants',
];
public function user(){
return $this->belongsTo("\App\Models\User");
}
protected $casts = [
'applicants' => 'array'
];
}
Next is my migration (I am using text format, because the DB on the server is older and does not support json)
public function up()
{
Schema::create('recruitments', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->decimal('salary', 10, 2);
$table->date('term_start');
$table->date('term_end');
$table->date('deadline');
$table->longText('details');
$table->string('status');
$table->text('applicants')->nullable();
$table->timestamps();
});
}
Here is my blade
<div class="container">
<div class="row">
<div class="card col-sm-12 py-3">
<div class="card-header border d-flex justify-content-between align-items-center">
<h3 class="w-75">{{ $job->title }}</h3>
<div class="w-25">
<p class="my-0 my-0">Created at: <span class="text-info">{{ $job->created_at }}</span></p>
<p class="my-0 my-0">Last updated at: <span class="text-primary">{{ $job->updated_at }}</span></p>
</div>
</div>
<div class="card-body">
// display job details here
<form action="{{ route('add-applicant', ['id' => $job->id ]) }}" method="POST" class="col-sm-12 d-flex justify-content-center align-items-center">
#csrf
<input type="text" name="user_id" id="user_id" value="{{ Auth::user()->id }}" hidden>
<button type="submit" class="btn btn-success w-25">Apply</button>
</form>
</div>
</div>
</div>
</div>
and lastly my controller
public function addApplicant($id, Request $reqst){
$job = Recruitment::find($id);
$user[] = $reqst->user_id;
$job->applicants = $user;
$job->save();
return redirect()->back();
}
While this controller will be able to save an array, it unfortunately overwrites the already existing one (let's say a second user applied). When I try to use an array_push, it does nothing, and I still end up with just one value in the array.
Sorry this was a bit of a read, but I appreciate any help I cen get with this. Thanks
Try in
public function addApplicant($id, Request $reqst){
$job = Recruitment::find($id);
$job->applicants = $reqst->user_id;
$job->save();
return redirect()->back();
}
and in Recruitment model should have
public function user()
{
return $this->belongsTo(User::class, 'applicants');
}
and migration file
$table->integer('applicants')->nullable();
I have a component called project-form and in that again I am calling another component called search-users. The problem is that I am unable to set the $members property in ProjectForm from nested component i.e search-users.
As I can understand $members must be looking to set in SearchUsers.php but I want that must be set in ProjectForm.php so I could save in db.
project-form.blade.php
<form wire:submit.prevent="submit">
<input wire:model="name"/>
<input wire:model="category"/>
<input wire:model="target_date"/>
#livewire('search-users')
</form>
ProjectForm.php
<?php
namespace App\Http\Livewire;
use App\Models\Project;
use Livewire\Component;
class ProjectForm extends Component
{
public string $name = '';
public string $category = '';
public string $target_date = '';
public array $members = [];
protected $rules = [
'name' => 'required',
'category' => 'required',
'target_date' => 'required',
];
public function submit(){
$validated = $this->validate();
Project::create($validated);
toastr()->success('Project Created Successfully');
}
public function render()
{
return view('livewire.project-form');
}
}
search-users.blade.php
#foreach($users as $user)
<label class="list-group-item ps-0 border-0 d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<img alt="{{ $user->name }}" src="{{ url('storage/'.$user->avatar) }}" width="35" class="me-3 rounded-circle mx-auto d-block">
{{ $user->name }}
</div>
<input class="form-check-input me-1" wire:model.defer="members" type="checkbox" value="{{ $user->id }}">
</label>
#endforeach
As already suggestes by #Qirel you should use Livewire events.
In your search components you could emit an event memebersFound and passing the members from your search as parameter (see Livewire Passing parameters in events) like this
$this->emit('membersFound', $membersFound);
Then, in your ProjectForm component you should listen for this event
protected $listeners = [
'membersFound' => 'addMembers'
];
public function addMembers(array $members)
{
$this->members = $members;
}
For our Task attributes we have the following: task_id as primary key, user_id, stage_id and project_id as foreign keys, completed as boolean and a description. Our goal is to display the tasks under a project and by checking the checkbox right next to them, it should mark them as complete. The problem is in our database the 'complete' status doesnt change. We are using PhpMyAdmin. We have a separate controller called ProjectTasksController for handling the logic and a form in our show.blade.php view for sending the request. Any help would be greatly appreciated.
#extends('layouts.app')
#section('content')
<div class="display-3">{{$project->name}}</div>
<a class="nav-link" href="/projects/{{$project->project_id}}/edit"><i class="material-icons">edit</i></a>
#if ($project->image)
<div class="row">
<div class="col-12">
<img src="{{ asset('storage/' . $project->image) }}" alt="...." class="img-thumbnail">
</div>
</div>
#elseif(!$project->image)
no image
#endif
#if ($project->tasks->count())
<div>
#foreach ($project->tasks as $task)
<div>
<form method="POST" action="/tasks/{{$task->task_id}}">
{{method_field('PATCH')}} {{-- #method('PATCH') --}}
#csrf
<label class="checkbox {{$task->completed ? 'is_complete' : ''}} " for="completed">
<input type="checkbox" name="completed" onChange="this.form.submit()" {{$task->completed ? 'checked' : ''}} >
{{$task->description}}
</label>
</form>
</div>
#endforeach
</div>
#endif
#endsection
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Task;
class ProjectTasksController extends Controller{
public function update(Task $task)
{
$task->update([
'completed' => request()->has('completed')
]);
return back();
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
protected $guarded = [];
protected $primarykey = ['task_id'];
protected $fillable = ['user_id','stage_id','project_id','completed','description'];
public function stage(){
return $this->belongsTo(Stage::class);
}
public function user(){
return $this->belongsTo(User::class);
}
public function project(){
return $this->belongsTo(Project::class);
}
}
{
_method: "PATCH",
_token: "ljiwu8bEtAkRqSUOXllmaRbSujavHNYNRJR5TMcy",
completed: "on"
}
Route::patch('/tasks/{task_id}', 'ProjectTasksController#update');
Your controller method was not correct, hint of Task $task is just a instance of Task not the collection or a single Model.And you have not specify your Request $request to get this work request()->has('completed') in method arguments.You need to edit your method in following way:
public function update(Request $request,$task_id)
{
Task::find($task_id)->update([
'completed' => $request->has('completed')
]);
return back();
}
Note: $request->has('completed') will return Boolean; if you want exact value,then you need to retrieve as $request->get('completed')
If you want to use route model binding the name of your parameter in the update function should match the route parameter:
Route::patch('/tasks/{task}', 'ProjectTasksController#update');
Replace protected $primaryKey = ['task_id]'; with protected $primaryKey ='task_id' in the Task model. It should be a string, not an array.
I have a page(admin.blade.php) that needs to display an amount. There is a button('change') present in the page, which calls upon a modal that takes an input. This modal is present inside the form whose action calls the 'change-goal' route which in turn gets the changeGoal function from the controller.
My admin.blade.php contains the form,modal and is as:
<a class="btn btn-primary" data-toggle="modal" data-target="#moneyModal">
<span class="glyphicon glyphicon-money glyphicon-white"></span>change</a>
<div class="modal fade" id="moneyModal" role="dialog">
<div class="modal-dialog">
<form method="post" action="change-goal">
{{csrf_field()}}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Change Goal</h4>
</div>
<div class="modal-body">
<p>Please enter a new goal.</p>
</div>
<div class="modal-body">
<input class="form-control" name="newGoal" id="newGoal">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button id="save" type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</form>
</div>
</div>
My controller is as:
public function changeGoal(Request $data) {
$newGoal =DB::table('user')->whereColumn('goal')->get();
$newGoal->updateGoal($data->goal);
return view('admin',compact('newGoal'));
}
My user model is:
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'goal'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function updateGoal($goal){
$this->goal = $goal;
$this->save();
}
I would like to display the value for newGoal on the admin.blade.php page. Currently I have {{ $newGoal }} written, but its giving me an error saying Undefined variable: newGoal .
I'm guessing the problem is within the controller.
How would I be able to save the value entered in that modal/form so
that I can see it every time I visit the page.
Also, here's the table in case its needed:
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email');
$table->string('password');
$table->integer('goal')->default(10000);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Would really appreciate the help.
EDIT:
My adminmanagement.blade.php (formerly admin.blade.php) is:
<p>Total Donations: <br> ${{ $price }}</p>
<p>Our Goal: {{ $newGoal }}</p>
<a class="btn btn-primary" data-toggle="modal" data-target="#moneyModal">
<span class="glyphicon glyphicon-money glyphicon-white"></span>change</a>
<div class="modal fade" id="moneyModal" role="dialog">
<div class="modal-dialog">
<form method="post" action="change-goal">
{{csrf_field()}}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Change Goal</h4>
</div>
<div class="modal-body">
<p>Please enter a new goal.</p>
</div>
<div class="modal-body">
<input class="form-control" name="newGoal" id="newGoal">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button id="save" type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</form>
</div>
</div>
web.php has:
Route::group(['middleware' => 'auth'], function () {
Route::get('/home', 'PagesController#getAllVideos')->name('/home');
Route::post('change-goal','PagesController#changeGoal')->name('change-goal');
Controller:
public function getAllVideos(){
$videos = Video::all();
$price = DB::table('donor')->sum('amount_donated');
return view('adminmanagement',compact(['videos','price']));
}
public function changeGoal(Request $data){
$newGoal = $data->input('newGoal');
auth()->user()->update([
'goal' => $newGoal
]);
return view('adminmanagement', compact('newGoal'));
}
User model:
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'goal'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function updateGoal($goal){
$this->goal = $goal;
$this->save();
return $this;
}
}
Based on your comments and your code, your input field is newGoal and not goal. Your user fetching query is wrong with the whereColumn condition missing the value. You're complicating a simple operation.
As per your comments all you need to do is update the goal of the logged in user (admin) and return the new goal value. Do this
public function changeGoal(Request $request)
{
$newGoal = $request->input('newGoal');
auth()->user()->update([
'goal' => $newGoal
]);
return view('admin', compact('newGoal'));
}
Edit : Based your comments. You should do this to keep things simple.
public function getAllVideos()
{
$videos = Video::all();
$price = DB::table('donor')->sum('amount_donated');
$goal = auth()->user()->goal;
return view('adminmanagement', compact('videos', 'price', 'goal'));
}
public function changeGoal(Request $data)
{
auth()->user()->update([
'goal' => $data->input('newGoal')
]);
return redirect('/home');
}
Change $newGoal to $goal in your view.
<p>Total Donations: <br> ${{ $price }}</p>
<p>Our Goal: {{ $goal }}</p>
inside model
public function updateGoal($goal){
$this->goal = $goal;
$this->save();
return $this;
}
and inside your controller
public function changeGoal(Request $data) {
$oldGoal =DB::table('user')->whereColumn('goal')->get();
$newGoal = $oldGoal->updateGoal($data->goal);
return view('admin',compact('newGoal'));
}