This function is not in the Laravel documentation, I have found it in the source code however I am not completely sure how it should be used. For example, if I am working with products, I want to either insert or update a product in the database based on its UPC. If a product with the same UPC exists, update it with the new values. If not, insert the new values as a new product. How should this be done using this function?
Thank you!
Insert or update a record matching the attributes, and fill it with values.
updateOrInsert(array $attributes, array $values = [])
https://laravel.com/api/master/Illuminate/Database/Query/Builder.html#method_updateOrInsert
DB::table('products')->updateOrInsert(
[
'upc' => $request->get('upc'),
],
[
'upc' => $request->get('upc'),
'name' => $request->get('name'),
'vendor' => $request->get('vendor'),
'description' => $request->get('description')
]
);
Related
I have a table that has a column called "items", but not all rows have it, so I want to scan all rows that have "items".
Something like:
$resposta = $clientDB->scan(array(
'TableName' => 'tableName',
'Key' => [
'items' => ['S' => 'exists']
]
));
But I can't figure out how to do it...
The table has 10000 rows, but only 10 of them have "items", and I want to get only these 10 rows.
Edit:
As Seth Geoghegan pointed below, it was necessary create a global secondary indexes on the attribute i wanted to filter.
I ended up here:
$params = [
'TableName' => 'tableName',
'FilterExpression' => "attribute_exists(items)"
];
OR
$params = [
'TableName' => 'tableName',
'FilterExpression' => 'items != :null',
'ExpressionAttributeValues' => [
':null' => null,
],
];
But both didnt worked... First one seens necessary ExpressionAttributeValues to be setup and the second the php stop working with no error logs.
This is a perfect use case for global secondary indexes (GSI)!
You can create a GSI on the items attribute. Items with the items attribute defined will get projected into the GSI. Importantly, items that do not contain this attribute will not be in the index. You could then query the GSI and retrieve the items you're after.
Well, after some effort, i found a way though:
$resposta = $clientDB->scan(array(
'TableName' => 'tableName',
'FilterExpression' => "attribute_exists(items)"
));
After i created another global secondary index (GSI) for "items" (pointed by Seth Geoghegan), i just needed to add in the scan function the FilterExpression the "attribute_exists(items") and it worked.
I am using CakePHP 2.9.1, have 2 tables in a HABTM relationship, I want to save the header record and save many associations in one go, but the child record is already existing, I seem to be able to save the data using a hardcoded list but not using a variable, I'm sure it's something silly I'm doing, I'm running inside a plugin, the model I want to link too is in the main code.
The child record must not be altered because it's handled by the main system, I'm just extending it's functionality by linking to it in our plugin.
// Header Record
class templatedoc extends TemplateModuleAppModel
{
public $useTable = 'templatedocs';
public $hasAndBelongsToMany = [
'Servicetemplate' => [
'className' => 'Servicetemplate',
'joinTable' => 'templatedocs_to_servicetemplates',
'foreignKey' => 'templatedoc_id',
'associationForeignKey' => 'servicetemplate_id',
'unique' => true,
'dependent' => false, // We don't want to delete the Service Template by mistake!
]
];
}
Here is my save, this works:
$this->templatedoc->create ();
$data = [
'templatedoc' => [
'warning_adjust' => $prioritywarn,
'summary' => $summary,
],
'Servicetemplate' => [
1,2,3,10 // Dynamic data needed here!
]
];
$result = $this->templatedoc->SaveAll ($data);
But I can't have the "Servicetemplate" hardcoded, I've tried passing an array inside that array and removing it, imploding an array to make a comma separated list all I end up with is the header 'templatedoc' record being created but nothing in my link table
Only thing I can think is a difference is that the hardcoded list are int values, by data is coming from the database so will be an int inside a string, but I can't see that being an issue.
Any ideas what I'm doing wrong? Sorry if it's something completely stupid.
What I had to do in the end was store the items forcing an int, when associating in my foreach loop.
$items[] = (int) $id
Then this worked:
$this->templatedoc->create ();
$data = [
'templatedoc' => [
'warning_adjust' => $prioritywarn,
'summary' => $summary,
],
'Servicetemplate' => [
$items // Dynamic data needed here!
]
];
$result = $this->templatedoc->SaveAll ($data);
Seems very fussy it has to be type int, adding here in case someone else gets caught out, would love to know if there is a better solution.
I want to change field name and while fetching record from database
Ex.
$query = $formsElements->find('all')
->where(['Forms.slug' => 'allergy'])
->contain(['Forms'=>['fields'=>['id', 'name']], 'Elements']);
Above is my query and in same query i want to change name of "id" field as form_id.
Can you guys please suggest better ways to handle this without virtual field.
Thanks
you can use an alias, the manual says
You can set aliases for fields by providing fields
as an associative array:
So all you have to do is:
->contain([
'Forms'=>[
'fields'=>[
'form_id' => 'id',
'name'
]
],
'Elements'
]);
I know the Question title is a bit murky, but here's what I'm trying to do:
I'm retrieving a list of groups that a user belongs to from a third party api. In some cases, the user will be an 'admin' for a group and other times, just a 'member'.
Specifics aside, I'm calling a method on my api class from my controller that hits the api, retrieves the user's groups, decides if they are an 'admin' or not, then returns an array of arrays with each group's information including a 'role' key that denotes whether or not they are an 'admin'. So my returned array looks something like this:
[
0 => [
'unique_id' => 1243657,
'name' => 'Group1',
'city' => 'Bluesville',
'state' => 'IN',
'role' => 'admin'
],
1 => [
'unique_id' => 4324567,
'name' => 'Group2',
'city' => 'New Curtsbourough',
'state' => 'WI',
'role' => 'member'
],
2=> [
'unique_id' => 87463652,
'name' => 'Group3',
'city' => 'Samsonite',
'state' => 'MN',
'role' => 'member'
]
]
Now, I need to take those groups and store them in the database, which I'm doing by checking first that the group doesn't exist in the database, then adding it if needed. Of course, I'm leaving off the role, as it is only relevant to the current user.
Next, I need to connect the current user to these groups that were just retrieved. I have a pivot table set up that currently holds the user_id and group_id.
The question is, how to best handle this. Before I decided that I needed to know whether or not a member was an 'admin' or not, I simply had my 'createGroups' method return an array of primary keys to me, then passed that array to a call to
$user->groups()->sync($array_of_ids);
However, with the added 'role' information, it's not as cut and dry.
Basically, at this point in the lifecycle, I have access to an array of groups that contains a field 'role'. My thinking says to add a 'role' field to the pivot table, which would then contain 'user_id', 'group_id' and 'role'. This means I'll not only need the $groups array with the retrieved groups, but the ids of those groups as they pertain to my database.
I could make something work, but I'm afraid it would be extremely messy and inefficient.
Thoughts anyone??
Ok, as happens many times on Stackoverflow, I've come to a solution for my own question. I'm posting so that in the off-chance someone stumbles upon my question needing to do something similar, they can at least see how one person handled it.
According to the Laravel docs, if you want to sync relationships with an added column, you need to call sync in the following way:
$user->groups()->sync([
1 => ['role' => 'admin'],
2 => ['role' => 'member'],
3 => ['role' => 'member']
]);
So before I could sync, I needed an array that resembled the array that is being passed to 'sync'.
Since I had an array of 'groups' that included a field called 'role' for each group, I created a 'createGroups' method that basically looped over the $groups array and called the 'insertGetId' method that Laravel provides. This method persists the object to the database and returns the primary key of the created record. For my 'createGroups' method, I did the following:
public function createGroups($groups)
{
$added = array();
foreach($groups as $group){
$id = $this->createGroup($group);
$added[$id] = ['role' => $group['role']];
}
return $added;
}
So as I'm inserting 'groups' into the database, I'm building up the array that is needed by the 'sync' method. Since the 'createGroup' method uses Laravel's 'insertGetId' method, it returns the primary key for that group. Then I use that id as the key to the array. After all groups are inserted, my 'added' array that is returned to my controller, looks like this:
[
1 => ['role' => 'admin'],
2 => ['role' => 'member'],
3 => ['role' => 'member']
]
which is exactly what the 'sync' method needs to do it's thing.
Happy coding!
I am making an online shopping cart, and I having huge issues pushing add to cart to items
$collection->update(
array('session' => $_SESSION["redi-Shop"],
array('$push'=>
array('items'=> $_POST["item"])
)));
When the customer selects their first item to add to the cart it works fine
$collection->insert(
array('session' => $_SESSION["redi-Shop"],
'status' => "cart",
'items' =>$_POST['item']));
but after the first item is added it does not allow me to add any more.
Please any advice would be helpful.
When you insert it the first time, the items field is not array (probably a string).
According to the mongodb $push doc :
The operation will fail if the field specified in the $push statement
is not an array.
Change your insert operation to :
$collection->insert(
array(
'session' => $_SESSION["redi-Shop"],
'status' => "cart",
'items' => array($_POST['item'])
));
Then run your update query.