i have services and items table. i have the pivot table as service_item. I am able to store data into my pivot table however i can't get the right syntax to update the pivot table. My code stores a new data when i try to update an existing data.
PS: My code although is able to edit the client's name but not the items that the client bought earlier.
I want to be able to update the item_id and quantity
service_item - pivot.
service_id
item_id
qty
Controller
public function store(Request $request)
{
$service = new Service(array(
'id' => $service_no,
));
$service->save();
$selectedItems = [];
foreach($request->get('item_id') as $key => $id) {
$selectedItems[$id] = ['qty' => $request->get('quantity')[$key]];
}
$service->items()->attach($selectedItems);
}
public function update($id, Request $request)
{
$service = Service::findOrFail($id);
$service->clients->name = $request->get('name');
$service->clients->save();
$selectedItems = [];
foreach($request->get('item_id') as $key => $id) {
$selectedItems[$id] = ['qty' => $request->get('quantity')[$key]];
}
$service->items()->attach($selectedItems);
}
Okay after researching, i was able to solve this using updateExistingPivot
public function update($id, Request $request)
{
$service = Service::findOrFail($id);
$service->clients->name = $request->get('name');
$service->clients->save();
$selectedItems = [];
foreach($request->get('item_id') as $key => $id) {
$selectedItems[$id] = ['qty' => $request->get('quantity')[$key]];
}
$service->items()->updateExistingPivot($item_id, ['quantity' => selectedItems], false);
}
Related
In the admin panel, I have something called Group that an admin can make a group of users so my scheme is:
groups table contains:
id
name
1
group1
group_user table contains:
id
group_id
user_id
1
1
2
2
1
3
My logic is: if a user belongs to a group, that user cannot be added again to the same group:
In update, when I add a user that already exists in group, it added it again:
public function update($id, Request $request)
{
$request->validate([
'name' => 'sometimes|nullable|string',
'user_ids' => 'sometimes|array',
]);
$group = Group::findOrFail($id);
$group->update($request->only('name'));
if ($ids = $request->user_ids) {
$group->users()->attach($ids);
}
return $this->apiRespone(null, 'group updated successfully', null, 200);
}
Just check if user already is in the group before attaching to it:
public function update($id, Request $request)
{
$request->validate([
'name' => 'sometimes|nullable|string',
'user_ids' => 'sometimes|array',
]);
$group = Group::findOrFail($id);
$group->update($request->only('name'));
foreach($request->user_ids as $user_id) {
if (!$group->users()->where('id', $user_id)->exists()) {
$group->users()->attach($user_id);
}
}
return $this->apiRespone(null, 'group updated successfully', null, 200);
}
Update:
To get the list of already existing members, apply this in your loop logic:
$existingUsers = [];
foreach($request->user_ids as $user_id) {
if (!$group->users()->where('id', $user_id)->exists()) {
$group->users()->attach($user_id);
} else {
$existingUsers[] = $user_id;
}
}
// now you can use $existingUsers
I have 3 tables (sales, sales_detail, and bicycle). I don't know how to get back my quantity (sales) to unit balance (bicycle) and then delete the sales_detail entry because I'm going to update new sales.
public function edit(Request $request, $id) {
$sales = Sales::find($id);
$sales_details = SalesDetail::where('sales_id', $id)->get();
$bicycles = Bicycle::where('sales_id', $id)->get();
foreach ($bicycles as $bc && $sales_details as $sd) {
$bc->unit_balance = $sd->quantity + $bc->unit_balance;
//then delete sales_detail
}
return view('sales/edit', array(
'sales' => $sales,
'sales_details' => $sales_details,
'bicycles' => $bicycles
));
}
I suggest the use of Elequents relations in your Models such as 'belongsto' and 'hasmany' to better prepare data. Following this practice would allow you to simplify your queries during development. Your approach is very messy/novice and procedural.
Checkout https://laravel.com/docs/5.8/eloquent-relationships
public function edit(Request $request, $id) {
$sales = Sales::find($id); // get sales where sales_id = 40
$sales_details = SalesDetail::where('sales_id', $id)->get();
return view('sales/edit', array( 'sales' => $sales,
'sales_details' => $sales_details ));
}
public function update(Request $request, $id) {
$sales = Sales::find($id);
$sales_details = SalesDetail::where('sales_id',$id)->get();
foreach ($sales_details as $sales_dtl) {
$bicycle = Bicycle::find($sales_dtl->bicycle_id);
$bicycle->unit_balance = $bicycle->unit_balance + $sales_dtl['quantity'];
$bicycle->save();
$sales_dtl->delete();
}
$this->saveData($sales,$request);
return redirect()->route('sales.index');
}
i get my answer already
I am trying to increase the speed of my queries in Laravel 5.7 and I have the call down to ~2.5 seconds. I am trying to figure out more ways to make it faster and if I could get some help I'd greatly appreciate it.
Thanks
How my data is structured:
Function(Controller):
public function getUserDataTmp(Request $request) {
$input = file_get_contents("php://input");
$request = json_decode($input);
if ($this->authTokenAccess($request) == true) {
$bottomWords = bottom_exterior_word::select('word','sentence','sequence','id','group_id')->where('user_id','=', $request->id)->get();
$emergencyWords = left_exterior_word::select('word','sentence','sequence','id')->where('user_id','=', $request->id)->get();
foreach($bottomWords as $tmp => $key) {
$group_id = $key->group_id;
$bottomWords->user_id = $request->id;
$bottomWords[$tmp]->words = $key->getMainWords($group_id, $request->id);
}
foreach($emergencyWords as $key => $word) {
$emergencyWords[$key]->image = imageModel::select('base64','id')->where('emergency_id','=', $word->id)->first();
}
$data = [
'data' => [
'return' => 'success',
'code' => 'VEDC001',
'response' => 'Successfully Gathered Words',
'main_categories' => $bottomWords,
'emergency_words' => $emergencyWords
]
];
return(json_encode($data));
}
}
getMainWords Function(bottom_exterior_word model):
public function getMainWords($group_id, $id)
{
// return("TEST");
$words = \App\main_word::select('id','group_id','sentence','sequence','word')->where('group_id','=', $group_id)->where('user_id','=', $id)->get();
foreach ($words as $key => $word) {
$words[$key]->image = Image::select('base64','id')->where('word_id','=', $word->id)->first();
}
return $words;
}
Start by refactoring so that you dont query inside a foreach loop
foreach($bottomWords as $tmp => $key) {
$group_id = $key->group_id;
$bottomWords->user_id = $request->id;
$bottomWords[$tmp]->words = $key->getMainWords($group_id, $request->id);
}
I would change the getMainWords function to accepts an array of group id's and use the whereIn clause:
The whereIn method verifies that a given column's value is contained
within the given array:
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
Same treatment for this loop.
foreach($emergencyWords as $key => $word) {
$emergencyWords[$key]->image = imageModel::select('base64','id')->where('emergency_id','=', $word->id)->first();
}
In general minimizing the NUMBER of queries will improve response time.
Old post, would just like to update it though. Since I have first posted this, I have learned a lot more about Laravel and am a lot more experienced with it.
Here is my new function and solution:
Controller:
public function data(Request $request)
{
return response()->success(
[
'emergencywords' => EmergencyWord::with('image')->whereUserId($request->user()->id)->get(),
'categorywords' => CategoryWord::with(['image','words.image'])->whereUserId($request->user()->id)->get(),
]
);
}
Category Word Relationships:
public function image()
{
return $this->hasOne('App\Image','id','image_id');
}
public function words()
{
return $this->hasMany('App\MainWord','category_words_id','sequence');
}
Emergency Word Relationships:
public function image()
{
return $this->hasOne('App\Image','id','image_id');
}
Main Word Relationships:
public function image()
{
return $this->hasOne('App\Image','id','image_id');
}
I have table which have multiple reference to ohter tables like
user
id name email
categories
id title
user_categories
user_id category_id
Here a user will have multiple category associated with him/her
I am able to save these successfully with new records like following
View File:
echo $form->field($package_categories, 'category_id')->dropDownList( ArrayHelper::map(
StudyMaterialCategories::find()->all(), 'id', 'title'),
['multiple' => true]
);
Save New record:
$model = new Packages();
$package_categories = new PackageCategories();
$request = Yii::$app->request;
if ($request->isPost) {
$transaction = Yii::$app->db->beginTransaction();
try {
$post = $request->post();
$model->load($post);
$model->save();
foreach ($post['PackageCategories']['category_id'] as $key => $value) {
$package_categories = new PackageCategories();
$package_categories->category_id = $value;
$package_categories->package_id = $model->id;
$package_categories->save();
}
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
} catch (Exception $ex) {
$transaction->rolback();
Yii::$app->session->setFlash("error", $ex->getMessage());
}
}
Till now It's running successfully.
But I'm stuck when going to update the table. The problem part is dropdown list. How to set multiple selected option as per database if I'm coming with array of object.
Have a look on the following code
$package_categories = PackageCategories::find()
->where('package_id=:package_id', ['package_id' => $id])->all();
if (count($package_categories) < 1) {
$package_categories = new PackageCategories();
}
$request = Yii::$app->request;
if ($request->isPost) {
$transaction = Yii::$app->db->beginTransaction();
try {
$post = $request->post();
$model->load($post);
$model->save();
$package_categories = new PackageCategories();
$package_categories->deleteAll(
"package_id=:package_id",
[':package_id' => $model->id]
);
foreach ($post['PackageCategories']['category_id'] as $key => $value) {
$package_categories = new PackageCategories();
$package_categories->category_id = $value;
$package_categories->package_id = $model->id;
$package_categories->save();
}
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
} catch (Exception $ex) {
$transaction->rolback();
Yii::$app->session->setFlash("error", $ex->getMessage());
}
}
if I try to get first object of the array $package_categories of only able to set selected one option
This is an example code of a model class Permit which has a many to many relationship with Activity through PermitActivity (pivot table model).
Model Class Activity
public class Permit extends \yii\db\ActiveRecord {
public $activities_ids;
...
public function rules() {
return [
...
[['activities_ids'], 'safe'],
...
];
}
...
// Method called after record is saved, be it insert or update.
public function afterSave($insert, $changedAttributes) {
// If this is not a new record, unlink all records related through relationship 'activities'
if(!$this->isNewRecord) {
// We unlink all related records from the 'activities' relationship.
$this->unlinkAll('activities', true);
// NOTE: because this is a many to many relationship, we send 'true' as second parameter
// so the records in the pivot table are deleted. However on a one to many relationship
// if we send true, this method will delete the records on the related table. Because of this,
// send false on one to many relationships if you don't want the related records deleted.
}
foreach($this->activities_ids as $activity_id) {
// Find and link every model from the array of ids we got from the user.
$activity = Activity::findOne($activity_id);
$this->link('activities', $activity);
}
parent::afterSave($insert, $changedAttributes);
}
...
// Declare relationship with Activity through the pivot table permitActivity
public function getActivities(){
return $this->hasMany(Activitiy::className(), ['id' => 'activity_id'])
->viaTable('permitActivity',['permit_id' => 'id']);
}
...
public function afterFind(){
parent::afterFind();
$this->activities_id = ArrayHelper::getColumn($this->activities, 'id');
}
}
This way the model class is the one responsible for creating and updating the relationship using the pivot table.
The most important thing is to have the relationship method declared correctly.
Edit
This is an example of the view using kartikv\widgets\Select2. I don't really know if dropDownList supports multiple select, however Select2 has so many useful features i usually use it over other options.
echo $form->field($model, 'activities')->widget(Select2::classname(), [
'data' => $data,
'options' => [
'placeholder' => '...'
],
'pluginOptions' => [
'allowClear' => true,
'multiple' => true,
],
]);
I have this code inside a function in user-controller. I'm, using Codeigniter.
$name_user = $this->input->post('contact-company');
$company_name = $this->input->post('name-company');
$company_orgnr = $this->input->post('orgnr-company');
$phone_company = $this->input->post('phone-company');
$email_company = $this->input->post('email-company');
//Insert a a new user
$user_info = array(
'username' => $email_company,
'name_user' => $name_user
);
$company_info = array(
'name' => $company_name,
'orgnr' => $company_orgnr,
'phone' => $phone_company,
'email' => $email_company
);
//Insert a new user in db
$query_insertuser = "START TRANSACTION";
//Get sql for inserting a new user
$um = new Usermodel();
$query_insertuser .= $um->getSQLInsert($user_info);
//Get sql for inserting a new company
$cm = new Companymodel();
$query_insertuser .= $cm->getSQLInsert($company_info);
//Get sql for inserting relation between user
//and company (How do I get ID of user and ID of company to use?)
$upm = new Userprofilemodel();
$query_insertuser .= $upm->getSQLInsert();
$query_insertuser .= "COMMIT";
//Do the atual insert
$um->insert($query_insertuser);
It's used for handling a registration through a form. (Validation is done through the form-validation libray)-
Users with username, name_user is stored in a users-table
Companies are stored in a companies-table
Relations between companies and users are stored in a
userprofile-table
I think the code is kind of self-explainatory, but I'm not clear in how to insert the relation in the userprofile-model. I do need the last inserted id for user and the last inserted id for company, but in my code I don't have that because I don't actually insert any users or companies before calling $upm->getSQLInsert();
Or am I doing this incorrectly? Please give me any pointers...
I was obviously not doing this correctly. In case anyone care to bother this is my solution:-)
User-controller (part of it)
//Insert a new user in db
$um = new Usermodel();
$um->startTransaction();
$user_id = $um->insert($user_info);
$cm = new Companymodel();
$company_id = $cm->insert($company_info);
//Insert a new user-profile for newly inserted user
$upm = new Userprofilemodel();
$userprofile_info = array(
'user_id' => $user_id,
'company_id' => $company_id
);
$upm->insert($userprofile_info);
$um->endTransaction();
User-model (part of it)
public function startTransaction() {
$this->db->trans_start();
}
public function endTransaction() {
$this->db->trans_complete();
}
public function insert(array $user_info) {
$this->db->insert('user', $user_info);
return $this->db->insert_id();
}
Company-model (part of it)
public function insert(array $company_info) {
$this->db->insert('company', $company_info);
return $this->db->insert_id();
}
Userprofile-model (part of it)
public function insert(array $userprofile_info) {
$this->db->insert('user_profile', $userprofile_info);
return $this->db->insert_id();
}