Reference Relationship ID on CSV import - php

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.

Related

Laravel UpdateOrCreate To Be Different values on Create on Update

Is there something like UpdateOrCreate I can use to have different values on create and on update. Meaning if it’s updating i don’t want it to change a certain column but i want it to insert the first time.
eg
$person = ['name'=> 'John', 'age' => 6, 'joined' => '2017-01-01'];
If John exists update age. If it doesn’t insert age and joined;
People::updateOrCreate(
['name' => $person['name']],
['age' => $person['age'], 'joined' => $person['joined']]
)
will update joined every time and i don't wanna change it.
You can use updateOrNew which doesn't persist it to the database and then check if it is not already in the database you can change the property you want to change.
$record = People::updateOrNew(
['name' => $person['name']],
['age' => $person['age']]
);
if(!$record->exists()) {
$record->joined = $person['joined'];
}
$record->save();
But if you are only trying to get the record if it exists and create it if it doesn't, use firstOrCreate() instead. That won't affect existing records, only return them, and it will create the record if it doesn't exist.
There is no any other option else you can try following:
$person = People::where('name', $name)->first();
if (!is_null($person)) {
$person->update([
'age' => $age
]);
}else{
$person = People::create([
'name' => $name,
'age' => $age,
'joined' => date('Y-m-d')
]);
}

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

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.

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"]]

Basic associative arrays in php. How to fill them

First of all, I'm sorry if this is too easy for many of you... I'm learning as much as I can.
I want to create an array with customers, like:
$customers=["customer A", "customer B", "customer C"];
Then, I want to create an array with some characteristics for every customer in that array. The characteristics are 'City', 'Points' and 'Results'. Each customer has a name (string), not a number.
I would need to change (or update) a characteristic ('points') of all customers of the array when needed with PHP. Something like:
for each $customer in $customers {
$points[$customer]=$points[$customer]+2;
}
I would like to also update the info of only one customer, something like:
$points['Customer C']=$points['Customer B']+3;
Finally, I need to access the characteristics of a give Customer, like:
$i=$points['Customer A']+$result['Customer A'];
I know this is not correct, but how should I proceed in PHP?
How could I eliminate a Customer from the array $Customers (with all its characteristics)? And how could I add a new Customer to $Customers?
Thank you very much for your help. I really appreciate it.
As your question states, assoc array:
$customers = [
'customerA' => [
'points' => 100,
'city' => 'New York',
'results' => 40,
],
'customerB' => [
'points' => 75,
'city' => 'Amsterdam',
'results' => 10,
],
'customerC' => [
'points' => 25,
'city' => 'London',
'results' => 5,
],
];
// Remove customer C
unset($customers['customerC']);
// add customer D
$customers['customerD'] = [
'points' => 50,
'city' => 'Berlin',
'results' => 5,
];
// Update points of customer
$customers['customerA']['points'] += 2; // Adds 2 points
// Update points of customer by another customers points
$customers['customerB']['points'] = $customers['customerA']['points'] + 3;
// Add 2 points to each customer
foreach ($customers as $name => $properties) {
$properties['points'] += 2;
$customers[$name] = $properties;
}
The key within the customers array is the name of your customer and all the properties are within the value of that key.
You were close with your foreach:
foreach ($customers as $customer) {
$points[$customer] = $points[$customer] + 2;
}
You can update a single value like this:
$points['customer A'] = $points['customer A'] + 2;
And you can unset/remove a value like this:
unset($points['customer A']);
$customers = array();
//Adding customers
$customers["Customer 1"]["City"] = "Houston";
$customers["Customer 1"]["points"] = 3;
$customers["Customer 1"]["Results"] = "";
$customers["Customer 2"]["City"] = "Paris";
$customers["Customer 2"]["points"] = 8;
$customers["Customer 2"]["Results"] = "";
//updating characteristics
foreach ($customers as $name=>$customer)
{
$customers[$name]["City"] = "Dallas";
$customers[$name]["points"] = $customers[$name]["points"] + 2;
$customers[$name]["Results"] = "";
}
//Removing customer
unset($customers["Customer 1"]);
You can use multidimensional arrays to hold the data. This will be like how data would be returned from a database request so is a good approach to use.
// Customers array
$customers = [
[
'name' => 'Customer A',
'city' => 'Townville',
'points' => '3',
'results' => '2',
],
[
'name' => 'Customer B',
'city' => 'Blagstonberry',
'points' => '1',
'results' => '4',
],
[
'name' => 'Customer C',
'city' => 'Thorpington',
'points' => '6',
'results' => '3',
],
];
To access or edit specific customer details you will need to get the key for that customer. For example, get the key for Customer A,
$key = array_search('Customer A', array_column($customers, 'name'));
Now to access that customer's city for example, you can use the code,
$customer_a_city = $customers[$key]['city'];
To remove Customer B,
// get the key
$key = array_search('Customer B', array_column($customers, 'name'));
// remove customer
unset($customers[$key]);
Add 2 points to all customers,
foreach ($customers as &$customer) {
$customer['points'] += 2;
}
unset($customer);
Here we are passing by reference using the &. This means we can update the value directly in the foreach loop. It is good practice to unset the variable, in this case $customer so that you don't make any unwanted changes later on.
Characteristics of a particular customer - Customer C,
// get the key
$key = array_search('Customer C', array_column($customers, 'name'));
$i = $customers[$key]['points'] + $customers[$key]['results'];
Add a customer,
$customers[] = [
'name' => 'Customer D',
'city' => 'Dongleville',
'points' => '7',
'results' => '1',
];
Notes
If you search for a key for a customer by name that doesn't exist $key will be false. For example,
// get the key
$key = array_search('MADE UP NAME', array_column($customers, 'name'));
if ($key === false) {
// customer name did not exist
} else {
// do your thing
}
Also if more than one customer has the same name, the first customer key will be returned.
Reference
Passing by reference
Array search
Array column

How to store a variable in an array?

I have data from a form submission stored in a variable called $post_data. When I do print_r($post_data); I get the following array:
Array
(
[element_3] => John Doe
[element_2] => john#example.com
[element_14] => City
[element_15] => Country
[form_id] => 1
[submit] => Submit
);
I want to store some of the fields in another array to pass to another script. Will my code below work? If not, how do I fix it?
$submitted_data = array(
'Fields' => array(
array(
'Key' => 'Name',
'Value' => $post_data['element_3']
)
array(
'Key' => 'Email',
'Value' => $post_data['element_2']
)
)
)
Also, a PHP noob question, do I need another comma (,) in between the Name and Email array?
Thanks!
I'm not exactly sure why you would want to do this, but depending on the field name you can consider using loops to help automate the entire process.
$field_map = array(
'element_3' => 'Name',
'element_2' => 'E-mail',
'element_14' => 'City',
'element_15' => 'Country'
);
$submitted_data = array('fields' => array());
foreach ( $field_map as $key => $label)
{
$submitted_data['fields'][] = array(
'key' => $key, // e.g. element_2
'label' => $label, // e.g. E-mail
'value' => $post_data[$key] // e.g. john#example.com
);
}
This separates the storage/mapping of key/label pairs from the part which processes it, making it easier to maintain and modify in the future.
Another way might be (depending on how "fixed" the second script is, if you can alter it).
$submitted_data['Name']=$post_data['element_3'];
$submitted_data['Email']=$post_data['element_2'];
To get a result more like the one in your question:
$submitted_data['Fields']['0']['Key']='Name';
$submitted_data['Fields']['0']['Value']=$post_data['element_3'];
$submitted_data['Fields']['1']['Key']='Email';
$submitted_data['Fields']['1']['Value']=$post_data['element_2'];

Categories