unique form validation based on two fields - laravel

I am creating a new record for a table named services including some fields (name, department_id, description) in database. I need unique combination of pair two fields together (name and department_id). How can I validate it for creating and updating functions?
In ServiceRequest:
return [
'params.name' => 'required|unique:services,name and depatment_id',
];
In Service Model:
public function department()
{
return $this->belongsTo(Department::class);
}
In DepartmentModel:
public function services()
{
return $this->hasMany(Service::class);
}
In Route:
Route::apiResource('/services', ServiceController::class)->names([
'store' => 'services_store',
'update' => 'services_update',
]);
Forexample:
when there is a service in a specific department, it gives error!
if there is a record of name = service1 and department_id = 1, user cannot create same record combination of name and department_id again! user allow to create service with (name = service1 and department_id = another_number) or (department_id = 1 and name = another_name) but creating a new record with (name = service1 and department_id = 1) is not allowed

You can use the unique rule this way:
return [
'params.name' => [
'required',
Rule::unique('services', 'name')
->ignore($this->service)
->where('department_id', $this->input('params.department_id'))
],
];
Here you are telling Laravel to check if there is no existing record in the services table that have $this->input('params.name') as name and $this->input('params.department_id') as department_id.
The ->ignore($this->service) is here to make sure we ignore the current service (if we are updating), so it doesn't "find itself" during the validation.
$this->service will be the current instance you are updating (if you setup the routes and controllers correctly, which is another topic).

Related

How do I return the ID field in a related table in Laravel request

I have two related tables and I want to return all fields including the ID (key) field. My query below returns all fields except the ID. how do I return the ID field from one of the tables?
'programmes' => ProgrammeInstances::with('programmes')->get(),
the query below returns Unknown column 'programmes.programme_title' as it is looking for it in the table 'programme_instances'
'programmes' => ProgrammeInstances::with('programmes')->select('programmes.programme_title', 'programmeInstances.id', 'programmeInstances.name', 'programmeInstances.year')->get(),
Laravel provides multiple relationships, one of these is the hasMany() relationship which should return a collection where a User hasMany rows inside of your database
For example, inside your User model :
public function programmes() {
return $this->hasMany(Program::class);
}
Now in your controller, you can do :
public function edit($id) {
$programmes = User::find($id)->with('programmes')->get();
return view('user.edit')->with('programmes', $programmes);
}
And then you can loop over it inside your view
#forelse($programmes->programmes as $program)
// provide the data
#empty
// the user doesn’t have any programmes
#endforelse
a solution i found below - still not sure why ID isnt automatically returned when i get all fields, but works when i specify individual fields:
'programmes' => ProgrammeInstances::with('programmes')
->get()
->transform(fn ($prog) => [
'programme_title' => $prog->programmes->programme_title,
'id' => $prog->id,
'name' => $prog->name,
'year' => $prog->year,
]),

After Update, The data from another Table will be deleted

I Have two different database table named Customers and Change_info_request
customers will request of changing their infomation and it will stored in Change_info_request and me the admin will be the one who will approve for changing information.
after the update the information inside the Change_info_request will transfer to the Customers table and the data inside the Change_info_request will be deleted .
And that's is my problem, i want to do it in the same controller like this
UpdateRequest
public function UpdateRequest(ClientUpdate $request){
$res = Customer::where('id', $request->id)
->update([
'first_name' => $request->new_first_name,
'last_name' => $request->new_last_name,
'birthdate' => $request->new_birthdate,
'gender' => $request->new_gender,
'pending_update_info' => 2,
]);
if($res) {
return response()->wrap($res);
} else {
return response()->wrap(["message" => "something went wrong!"]);
}
}
How will i delete the info from Change_info_request inside this controller ?
Sorry for the wrong grammar and im only a student that studying laravel.
you have id of that row in Change_info_request table right?
i have done this before this was my way:
i store new information in my table called edit-user (just like your Change_info_request ) and when i show them in admin dashboard i have their id!
when admin click on approve button it will send the id of that row to some function!
in function i find the row in edit-user table with id that i have, and replace my new data in my users table (your Customers table) and when i finished replacing data i will delete data from edit-user with that id!
Change_info_request::find('customer_id', $id)->delete();
with id of that row in edit-user(your Change_info_request table) table you can do anything
and of course your in Change_info_request table you should have user_id field
good luck!
Before your if condition, you can add something like:
$del = Change_info_request::find('customer_id', $request->id)->delete();

laravel tables with relationship and insertion

I have 4 tables
Customers : with data of customers. this table hasMany(Refunds)
Refunds: with data of various request. this table belongsTo(Customers) AND belongsToMany(Services)
Services: with list of services. this table belongsToMany(Refunds)
Refunds-Services: bridge table for refunds and services
I have a form that must insert datas in the correct table.
public function storeRefunds(RefundsPost $request){
DB::beginTransaction();
$customers = Customers::create($request->all());
$refunds = $customers->refunds()->create([
'date_ref' => request('date_ref'),
'status_ref' => request('stato'),
]);
$tipo = $request->input('tipo', []);
$importo = $request->input('importo', []);
$refunds = Refunds::create($request->all());
for ($i=0; $i < count($tipo); $i++) {
if ($tipo[$i] != '') {
$refunds->services()->attach($tipo[$i], [
'services_id' => $tipo[$i],
'services_amount' => $importo[$i]
]);
}
}
return redirect("/");
}
with this code i can insert all datas in correct tables but i cannot find ID connection in the Refunds table. Two different ID are created in Refunds table. second created id in the Refunds table not connected to any customer (0) but connected to the list of services choosen.
How can i do?
Thx
You need to debug your code. First Refund creates in this line $refunds = $customers->refunds()->create and it's belongs to Customer, second Refund creates here : $refunds = Refunds::create($request->all()); and it's doesn't relate to any Customer, but relates to Service (you do this in for loop). By the way, your tipo input is not multiple (it should be with [] if you expects it can be more than one value) and for loop is senseless in this sutiation.
Delete one of Refunds::createmethods, bring your data to expected view and use createMany() method.
More info in Laravel docs : https://laravel.com/docs/7.x/eloquent-relationships#the-create-method

updateExistingPivot using the primary key instead of the foreign key

I think this question is similar to this one, however I also think my use case is slightly different.
I am successfully able to update a pivot table using updateExistingPivot when a single user exists; however instead of referencing the FK on the pivot table, I need to reference the id.
I have three tables: users, roles and role_user.
users
id|name|email
roles
id|title
role_user
id|active|user_id|role_id
For example, if I have two users in my application, the users table would look like:
id: 1|name: foo|email: fooexample#email.com
id: 2|name: bar|email: barexample#email.com
My roles table looks like this:
id: 1|title: fizz
id: 2|title: buzz
id: 3|title: bang
Each user is given 3 roles by default. So my role_user table looks like this:
id: 1|active: true|user_id: 1|role_id: 1
id: 2|active: true|user_id: 1|role_id: 2
id: 3|active: true|user_id: 1|role_id: 3
id: 4|active: true|user_id: 2|role_id: 1
id: 5|active: true|user_id: 2|role_id: 2
id: 6|active: true|user_id: 2|role_id: 3
Because updateExistingPivot looks at the FK to decide what to update, everything works great with a single user. However, when I have duplicate user_id and/or role_id FK's things start to fall apart. Instead of looking at the FK, I need to be able to look at the id in my pivot table.
I am passing my roles to a vue component from my controller like this:
// Get the roles(s) that belong to the user.
$roles = $user->roles
->sortByDesc('title')
->toJson();
I am rendering the list on screen, and when a user clicks a role, they can update it's status:
...
async handleRoleClick(event, role) {
console.log('updating role: ', role);
try {
let response = await axios.patch(`/my-path`, {
active: !this.active,
id: role.pivot.id,
});
// data getting passed is correct.
// active: false
// id: 5 <-- the id of the pivot table, not a FK value
if (response.status === 200) {
console.log('response.data', response.data);
this.active = response.data.role.pivot.active;
console.log('active: ', this.active);
} else {
console.error('Error: could not update role. ', response);
}
} catch (error) {
console.error('Error: sending patch request. ', error);
}
},
...
My update method in my controller looks like this:
$attributes = request()->validate([
'active' => 'required',
'id' => 'required',
]);
// Get the authenticated user.
$user = auth()->user();
// Update the roles' status in the pivot table.
$user->roles()->updateExistingPivot($attributes['id'], $attributes);
// Get the role that was just updated via the relationship.
$role_with_pivot = $user->roles()->where('role_user.id', $attributes['id'])->first();
return response()->json(['role' => $role_with_pivot], 200);
The data I am sending in my request headers is correct. I am not getting any errors, however my pivot table is not getting the values I am passing to it. I assume it's because I am not correctly sending the id. In my example above it would be id: 5. Because there isn't a user_id of 5 or role_id of 5, Laravel isn't sure what to do.
How can I tell Laravel to look at the id of the pivot table, and not a foreign key?
The way I am doing it though seems kind of sketchy. I'd be really interested to see if there is a more "Laravel way" of doing this. Everything else is above is the same, here is what my update method on my controller looks like.
controller
public function update(Request $request, Role $role)
{
$attributes = request()->validate([
'active' => 'required',
'id' => 'required',
]);
// Get the authenticated user.
$user = auth()->user();
// Get the requested role (row) from the pivot table.
$role = $user->roles()->where('role_user.id', $attributes['id'])->first();
// Update the requested role.
$role->pivot->active = $attributes['active'];
// Save the requested role.
$role->pivot->save();
// Get the role that was just updated via it's relationship.
$role_with_pivot = $user->roles()->where('role_user.id', $attributes['id'])->first();
return response()->json(['role' => $role_with_pivot], 200);
}
You should retrieve role id in you View instead of pivot primary key, and use role_id to update pivot table.
As stated your user has multiple roles, but only one combination of role and user id.
async handleRoleClick(event, role) {
console.log('updating role: ', role);
try {
let response = await axios.patch(`/my-path`, {
active: !this.active,
id: role.id, //change this
});
// data getting passed is correct.
// active: false
// id: 5 <-- the id of the pivot table, not a FK value
if (response.status === 200) {
console.log('response.data', response.data);
this.active = response.data.role.pivot.active;
console.log('active: ', this.active);
} else {
console.error('Error: could not update role. ', response);
}
} catch (error) {
console.error('Error: sending patch request. ', error);
}
},
it's late, but might help some artisans in the future.
You may use DB method directly or create a dedicated model/entity for that table.
e.g
DB::table('role_user')->where('id', $id);
or
RoleUser::find($id);

How to get hasMany relation in laravel?

Pls bear with me . I am working on api with laravel :
The Idea is that I have table called ( cards ) this table contain column called ( service_id ) .
this column has relation with table ( services ).
This is cards database structure in image :
image of database
All thing is good with add one service_id , but now I need to make table cards hasMany services
So How can I do it , and the database structure what will be?
this is my old code to add new card :
public function store(Request $request)
{
$validator = \Validator::make($request->all(), [
'user_id' => 'required|unique:cards|exists:users,id',
'service_id' => 'required',
'numPhone' => 'required',
'location' => 'required',
],[],[
'user_id' => '( User id )',
'service_id' => 'service id',
'numPhone' => 'Phone Number',
]);
if ($validator->fails()){
return $this->apiRespone(null,$validator->errors()->all(),'Some input required');
}
$card = Card::create($request->all());
return $this->apiRespone(new cardResource($card),'Add card Successfully',201);
}
I think you need to create pivot table "cards_services" that has column id, card_id, service_id column and used relationship Sync() method of laravel to store/update.
In cards modal
public function services(){
return $this->belongsToMany('App\Models\Service','cards_services', 'card_id', 'service_id');
}
For save it.
$cards->services()->sync([1,2]); //1 and 2 is service ID and $cards is card modal object
here you have service_id in your cards table
so i think it will be easier to implement service hasMany cards and cards belongsTo service
add this in your service model
public function cards(){return $this->hasMany('App\Cards');}
add this in your cards model
public function service(){return $this->belongsTo('App\Service');}
Note: please rewrite path and Model name according to your requirement

Resources