Laravel : Update if exists, If not delete | Relational data - php

I am updating/deleting some form data in database :
The relation is : One to Many: UserService => UserServiceVaccine
I am trying to update the table data if the form have that data, Otherwise remove if form data have not the data :
Current code :
foreach ($request->dog_vaccine_required as $key => $vaccine) {
$serviceVaccination = \App\UserServiceVaccination::updateOrCreate([
'user_service_id' => $id,
'vaccine_id' => $vaccine
],[
'specie' => 'Dog',
'user_service_id' => $id,
'vaccine_id' => $vaccine,
'duration_6' => $request->dog_duration_6[$key],
'duration_12' => $request->dog_duration_12[$key],
'duration_36' => $request->dog_duration_36[$key]
]);
}
It gives me offset exception. if i remove a checkbox.
What should be done.

Do you can try this ?
foreach ($request->dog_vaccine_required as $key => $vaccine) {
$shouldUpdate=isset($request->dog_duration_6[$key])&&
isset($request->dog_duration_12[$key])&&
isset($request->dog_duration_36[$key]);
if ($shouldUpdate){
$serviceVaccination = \App\UserServiceVaccination::updateOrCreate([
'user_service_id' => $id,
'vaccine_id' => $vaccine
],[
'specie' => 'Dog',
'user_service_id' => $id,
'vaccine_id' => $vaccine,
'duration_6' => $request->dog_duration_6[$key],
'duration_12' => $request->dog_duration_12[$key],
'duration_36' => $request->dog_duration_36[$key]
]);
}else{
// Delete
}
}

I think that's a "many to many" relationship between user_service table and vaccine table.
Based on the docs here https://laravel.com/docs/5.6/eloquent-relationships#many-to-many
$serviceVaccinationArray = [];
foreach ($request->dog_vaccine_required as $key => $vaccine) {
$serviceVaccinationArray[$vaccine] = [
'vaccine_id' => $vaccine,
'specie' => 'Dog',
'duration_6' => $request->dog_duration_6[$key],
'duration_12' => $request->dog_duration_12[$key],
'duration_36' => $request->dog_duration_36[$key]
]
}
$userService = UserService::find($id);
$userService->vaccine()->sync($serviceVaccinationArray);
The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table.

Related

tableselect make specific checkbox checked

foreach ($courses as $user) {
$options[$user['uid']] = [
'coursecode' => $user['coursecode'],
'coursename' => $user['coursename'],
'credithours' => $user['credithours'],
'coursetype' => $user['coursetype'],
'building' => $user['building'],
'place' => $user['place'],
'day' => $user['day'],
'time' => $user['time'],
];
}
$form['table'] = [
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#empty' => t('No Courses found'),
'#js_select' => false,
'#attributes' => ['checked' => 'checked'],
];
this code generates all courses I can register is there any way to check specific values as default, I had a problem with making a specific checkbox checked
so anyhelp ?
I'm using drupal 8
//Inside your foreach loop
foreach($courses as $user) {
$default_value[$user['uid']] = 1; // use 1 or 0 as appropriate
}
// now with your table select
$form['table']['#default_value'] = $default_value;
// default_value is not provided with each options, rather an array of default values is provided in the tableselect main array.
Hope this solves your problem.

Array sort menu

I have the following array to show menu's based on the order the user specified.
The array is as follows:
$menuArray = [
'Main Street' => [
['/index.php', 'Home'],
['/city.php', $cityData[$user->city][0]],
['/travel.php', 'Travel'],
['/bank.php', 'Bank'],
['/inventory.php', 'Inventory'],
['/dailies.php', 'Dailies'],
],
'Activities' => [
(!$my->hospital) ? ['/hospital.php', 'Hospital'] : [],
(!$my->hospital && !$my->prison) ? ['/crime.php', 'Crime'] : [],
['/missions.php', 'Missions'],
['/achievements.php', 'Achievements'],
],
'Services' => [
['/hospital.php', 'Hospital'],
['/prison.php', 'Prison'],
['/search.php', 'Search'],
],
'Account' => [
['/edit_account.php', 'Edit Account'],
['/notepad.php', 'Notepad'],
['/logout.php', 'Logout'],
]
];
I have a column menu_order stored in the database, which has a default value of 0,1,2,3,4, but this can change per user as they will be able to change their menu to their likes.
What I'd like to achieve:
0 => Main Street
1 => Activities
2 => Services
3 => Account
4 => Communication
To get the menu order, I do
$menuOrder = explode(',', $user->menu_order);
But I'm not sure how to handle the foreach for displaying the menu.
Here's one way to do it -- use replacement rather than a sorting algorithm.
Code: (Demo)
$menuArray = [
'Main Street' => [],
'Activities' => [],
'Services' => [],
'Account' => []
];
$lookup = [
0 => 'Main Street',
1 => 'Activities',
2 => 'Services',
3 => 'Account',
4 => 'Communication'
];
$customsort = '4,2,1,3,0';
$keys = array_flip(explode(',', $customsort)); convert string to keyed array
//var_export($keys);
$ordered_keys = array_flip(array_replace($keys, $lookup)); // apply $lookup values to keys, then invert key-value relationship
//var_export($ordered_keys);
$filtered_keys = array_intersect_key($ordered_keys, $menuArray); // remove items not on the current menu ('Communication" in this case)
//var_export($filtered_keys);
$final = array_replace($filtered_keys, $menuArray); // apply menu data to ordered&filtered keys
var_export($final);
Output:
array (
'Services' =>
array (
),
'Activities' =>
array (
),
'Account' =>
array (
),
'Main Street' =>
array (
),
)
And here's another way using uksort() and a spaceship operator:
$ordered_keys = array_flip(array_values(array_replace(array_flip(explode(',', $customsort)), $lookup)));
uksort($menuArray, function($a, $b) use ($ordered_keys) {
return $ordered_keys[$a] <=> $ordered_keys[$b];
});
var_export($menuArray);
As a consequence of how your are storing your custom sort order, most of the code involved is merely to set up the "map"/"lookup" data.
You could try something like this to produce the menu:
function display_menu($menus, $m) {
if (!isset($menus[$m])) return;
echo "<ul>";
foreach ($menus[$m] as $item) {
if (!count($item)) continue;
echo "<li>{$item[1]}\n";
}
echo "</ul>";
}
$menuMap = array(0 => 'Main Street',
1 => 'Activities',
2 => 'Services',
3 => 'Account',
4 => 'Communication');
$menuOrder = explode(',', $user->menu_order);
foreach ($menuOrder as $menuIndex) {
$thisMenu = $menuMap[$menuIndex];
display_menu($menuArray, $thisMenu);
}
Small demo on 3v4l.org

loop on foreach with distinct ?

I have a probleme with a array.
In my array that has 15,000 rows, I have columns with associated names and values ​​(sku).
I need to show all the names and make a separate on it if the sku is equal or not to the sku that is present on my product page
Exemple : array = [ 'code' => 'name1' ,
'sku' => '123456',
'code' => 'name1',
'sku' => '456789',
'code' => 'name2',
'sku' => '4565999']
etc ..........
if sku equals sku or not in my page product, i want to show the code with distinct on this .
First you need an array of arrays structure like this:
$arr = [
[ 'code' => 'name1', 'sku' => '123456' ],
[ 'code' => 'name2', 'sku' => '456789' ],
[ 'code' => 'name3', 'sku' => '4565999' ],
.
.
.
Then you can filter your array like this:
$existing_items_on_array = array_filter($arr,
function($item) use ($existing_items_on_page){
return array_search($item["sku"], $existing_items_on_page) !== false;
});
Or better (you still need to structure an array like on first solution):
I assume your SKU's are unique. Why not make them array keys?
$item_codes = [];
foreach($arr as $item){
$item_codes[$item["sku"]] = $item["code"];
}
then you would be accessing any element's code like this:
echo $item_codes[$product["sku"]]

how to save the array values as each record in mysql database

How can I save the following array values in my sql table?
Array (
[0] => "/path/to/file/file_name1.jpeg"
[1] => "file_name1.jpeg"
)
Array (
[0] => "/path/to/file/file_name2.jpeg"
[1] => "file_name2.jpeg"
)
Following is my table structure,
id - int - auto inc
path - varchar(200)
name - varchar(50)
Thanks in Advance.
You can insert an array of data with insert() method:
$data = [
['path' => '/path/to/file/file_name1.jpeg', 'name' => 'File 1'],
['path' => '/path/to/file/file_name2.jpeg', 'name' => 'File 2'],
['path' => '/path/to/file/file_name3.jpeg', 'name' => 'File 3'],
];
Model::insert($data);
Or:
....
DB::table('some_table')->insert($data);
You can use foreach and create method as:
foreach ($array as $key => $value) {
ModelName::create(['path' => $value[0], 'name' => $value[0]]);
}
Remember to add path and name in your model's fillable attribute.
You can add multiple values with the following
$data = array(
array('name'=>'value', 'path'=>'value'),
array('name'=>'value', 'path'=>'2048'),
//...
);
Model::insert($data);
You can find more here
https://laravel.com/docs/5.3/queries#inserts

Reference Relationship ID on CSV import

I have 2 models that I want to populate by a CVS import. The first model is a list of Retail Stores and the second model is the Retail Stores corresponding locations.
This is the CSV import:
name,email,website,street_number,street_address,city,country,postcode,latitude,longitude
"Example name",info#example.com,10,"random street",amsterdam,netherlands,4000,52.666,4.3333
The RetailStores.php model will need these values:
name,
email,
website
The LocationStores.php model will need these values:
street_number,
street_address,
city,
country,
postcode,
latitude,
longitude
I will extract the data from the CSV file inside a foreach loop and attaching them to an empty array variable, from here will use some Eloquent to populate the database. Below is how I do this:
$file = Input::file('csv_file');
$data = $this->retailer->processCsv($file);
$retailers = [];
$locations = [];
foreach ($data as $value) {
$retailers[] = array(
'user_id' => Auth::user()->id,
'name' => $value['name'],
'email' => $value['email'],
'website' => $value['website'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
$locations[] = array(
'retailer_id' => $value['retailer_id'], // ISSUE HERE
'street_number' => $value['street_number'],
'street_address' => $value['street_address'],
'city' => $value['city'],
'state' => $value['state'],
'country' => $value['country'],
'country_code' => $value['country_code'],
'postcode' => $value['postcode'],
'latitude' => $value['latitude'],
'longitude' => $value['longitude'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
Retailer::insert($retailers);
Location::insert($locations);
}
As noted above I have 2 separate models the Retailers and Locations. I need to reference the Retailer ID in the $locations array. For now I have one option which is to have users enter the relevant retailer store id for each location in the CSV file, but people are well.... you know.
However considering that the CSV file will supply a "Store Name" for each location it has, is there not a way to reference an increment ID for each unique store name within the array? for example if the CSV table had these values:
Fruit,info#fruit.com,www.fruit.com,1,"apple street",etc
Fruit,info#fruit.com,www.fruit.com,120,"pear parkway",etc
Fruit,info#fruit.com,www.fruit.com,350,"orange avenue",etc
Meat,info#meat.com,www.meat.com,33,"Steak street",etc
Meat,info#meat.com,www.meat.com,33,"Chicken Road",etc
When getting these values within the foreach loop, is there a way one could give an increment ID for each of the repeated Store names which would thus reference the relevant store to its location?
Any advice, greatly appreciated.
You could store the retailer name in a way where it's easy to check if a particular name is in the retailer array already, and grab the ID out if it is. Something like this:
foreach ($data as $value) {
$retailer_name = $value['name']; // for clarity
// is the retailer name in the retailers array already?
if (isset($retailers[$retailer_name])){
// get the ID
$retailer_id = $retailers[$retailer_name]['user_id'];
} else { // otherwise add a new one
$retailer_id = Auth::user()->id; //store the ID for use in Locations
// use retailer name for the key of the array, so it's easily findable later
$retailers[$retailer_name] = array(
'user_id' => $retailer_id,
'name' => $value['name'],
'email' => $value['email'],
'website' => $value['website'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
}
$locations[] = array(
'retailer_id' => $retailer_id, // add either the new or existing ID
'street_number' => $value['street_number'],
'street_address' => $value['street_address'],
'city' => $value['city'],
'state' => $value['state'],
'country' => $value['country'],
'country_code' => $value['country_code'],
'postcode' => $value['postcode'],
'latitude' => $value['latitude'],
'longitude' => $value['longitude'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
);
Retailer::insert($retailers);
Location::insert($locations);
}
You then have an array with strings as keys for $retailers, though, and if that's a problem for insertion, you'll have to make a separate array for retailers or change it to numeric keys before you insert.

Categories