I am new to laravel.
I have an issue when I am trying to update or create record in DB.
I have a table called DspAccountFee with this columns:
I want to create record of dsp_account_id + screen_type when the combination not exists, and to update if the combination exists.
this is my code: (just tried to update the first row keys of -> dsp_account_id(5187) + screen type (ctv). However nothing changed.
DspAccountFee::updateOrCreate(
['dsp_account_id' => $dsp_account_id, 'screen_type' => 'ctv'],
['pmp_percent' =>$fields['fee_ctv_pmp_percent'], 'omp_percent' => $fields['fee_ctv_omp_percent']]
);
When I print the values before the DB operation they exists:
\Log::info("dsp_account:");
\Log::info($dsp_account_id);
\Log::info("ctv pmp percent:");
\Log::info($fields['fee_ctv_pmp_percent']);
\Log::info("ctv omp percent:");
\Log::info($fields['fee_ctv_omp_percent']);
\Log::info("app pmp percent:");
What I am missing why it is not update the db? Nothing in logs and No exception
this is my method in the model
protected $fillable = array(
'dsp_account_id', 'screen_type'
);
Check the corresponding model and make sure that those columns exist in the
$fillable property. It should look somewhat like this.
protected $fillable = [
'dsp_account_id',
'screen_type',
'pmp_percent',
'omp_percent'
];
Your updateOrCreate syntax looks okay.
To update the updated_at column in your database, you can use the touch() method: you'll need to edit your code to something like this
$foo = DspAccountFee::updateOrCreate([
'dsp_account_id' => $dsp_account_id,
'screen_type' => 'ctv'
],
[
'pmp_percent' => $fields['fee_ctv_pmp_percent'],
'omp_percent' => $fields['fee_ctv_omp_percent']
]);
$foo->touch();
Related
I'm working on a project where I need to update many rows at once per coin Id.
in order to update all coins values, Im getting them all from the API, so for example I have back:
$coinsList= [[id="bitcoin", symbol="btc", name="Bintcoin"],[id="etherium", symbol="eth", name="Etherium"]];
and the database table columns is the following:
**| id | coin_id | symbol | name |**
now, I want to update all values to the database, according to the id only, so this is what I did:
// first get ids from my table
$exist_ids = Coinlist::all('coin_id')->pluck('coin_id')->toArray();
//get all ids to update (to ignore other ids):
$updatable_ids = array_values(array_intersect($exist_ids, $allCoinIds));//result for example is: array("bitcoin","etherium");
//and now, update the database:
Coinlist::whereIn('coin_id', $updatable_ids)
->update([
'symbol' => $coinsList[$key]['symbol'],
'name' => $coinsList[$key]['name'],
'updated_at' => now()
]);
the problem is, I don't have the "$key" in order to update the right row, what am I missing here?
Thanks!
Here is a good way to solve it:
in the beginning, I used this library: https://github.com/mavinoo/laravelBatch
to update many dynamic rows, but it was really slow, then thanks to Yasin, I moved to: https://github.com/iksaku/laravel-mass-update and now it works way better.
the implementation is simple, add a simple code to the Model class, then add:
User::massUpdate(
values: [
['username' => 'iksaku', 'name' => 'Jorge González'],
['username' => 'gm_mtz', 'name' => 'Gladys Martínez'],
],
uniqueBy: 'username'
);
while uniqueBy is the key for the row, and add other columns values to change them dynamically.
I have an application in CakePHP 4 and am having problems saving associated model data. I have read Saving Associated Data in the Cake documentation but it's very unclear how this applies especially in my use-case.
The application has 3 tables which are relevant to this question:
items
sizes
items_sizes_wanted
The application allows users to request items of clothing (items) and the form to input/save such an item has a dropdown of different sizes (sizes). Each size has a unique ID. A user can select one or more size when saving an item. The items_sizes_wanted table is supposed to hold one (or more) rows depending on the sizes the user selected, with the corresponding item ID. For example if they saved sizes 2, 3 and 4 for Item 999 there would be 3 rows in this table:
size_id | item_id
--------|---------
2 | 999
3 | 999
4 | 999
The code has been baked and the associations in the Table classes look ok:
// src/Model/Table/ItemsSizesWantedTable.php
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('items_sizes_wanted');
$this->belongsTo('Items', [
'foreignKey' => 'item_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Sizes', [
'foreignKey' => 'size_id',
'joinType' => 'INNER',
]);
}
The Entity class for the item also looks ok:
// src/Model/Entity/Item.php
// #property \App\Model\Entity\ItemsSizesWanted[] $items_sizes_wanted
protected $_accessible = [
// ...
'items_sizes_wanted' => true,
// ...
];
In the form where the item gets saved (src/templates/Items/add.php) I have used the Form Helper and named it using dot notation:
<?php
// Note that $sizes is an array of key/value pairs from the
// 'sizes' table.
?>
<?= $this->Form->control('items_sizes_wanted.size_id', ['options' => $sizes, 'multiple' => 'multiple']) ?>
When rendered in the browser this produces a valid array syntax name. The <option>'s rendered inside all have valid ID's, i.e. the ones from the sizes table.
<select name="items_sizes_wanted[size_id]" multiple="multiple">
When I save the data in my Controller (src/Controller/ItemsController.php) using the following:
public function add()
{
$item = $this->Items->newEmptyEntity();
if ($this->request->is('post')) {
$item = $this->Items->patchEntity($item, $this->request->getData());
// Edit: some of the entity properties are manually set at this point, e.g.
$item->item_status = 'Wanted';
if ($this->Items->save($item)) {
$this->Flash->success(__('Your item has been listed.'));
}
}
}
The data is saved correctly to the items table and the flash success message, "Your item has been listed." is displayed in the browser.
But - no data is written to items_sizes_wanted.
I'm unsure why this is. The linked docs don't specifically say how the Form Helper should be used, so I'm assuming my syntax for that form field is correct, but it might not be.
If I debug the entity after pressing Save using debug($item); die; in the Controller it has 'items_sizes_wanted' => [ ] even though I selected multiple size options using the form.
Please can somebody help as I'm lost as to what's going wrong here?
Disclaimer: I do not know CakePHP well, but I think I either know the solution, or can at least point you in the right direction.
The reason you're only getting the one selected size, instead of multiple, is because the generated input fields are named items_sizes_wanted[size_id], however, in order for PHP to parse multiple values into an array, they need to be named items_sizes_wanted[size_id][]. When the request parameter ends with [], then PHP will properly parse all request properties into an array.
For example: Here's var_dump($_POST); of a request containing the POST body of items_sizes_wanted[size_id][]=A&items_sizes_wanted[size_id][]=B&items_sizes_wanted[size_id][]=C
array (size=1)
'items_sizes_wanted' =>
array (size=1)
'size_id' =>
array (size=3)
0 => string 'A' (length=1)
1 => string 'B' (length=1)
2 => string 'C' (length=1)
Compare that to a POST body of items_sizes_wanted[size_id]=A&items_sizes_wanted[size_id]=B&items_sizes_wanted[size_id]=C (notice the empty braces at the end of each have been removed):
array (size=1)
'items_sizes_wanted' =>
array (size=1)
'size_id' => string 'C' (length=1)
This is the part where I'm less familiar with CakePHP. I looked over the code
for CakePHP's FormHelper, and based on the template code, I think you need to change your form code in add.php to be something like this (reformatted for readability):
<?php
// Note that $sizes is an array of key/value pairs from the
// 'sizes' table.
?>
<?=
$this->Form->control(
'items_sizes_wanted.size_id',
[
'options' => $sizes,
'multiple' => 'multiple'
'type' => 'selectMultiple'
]
)
?>
Based on the __call() method in FormHelper, You might also be able to write it like this:
$this->Form->selectMultiple(
'items_sizes_wanted.size_id',
[
'options' => $sizes,
'multiple' => 'multiple'
]
);
However, I'm not familiar with the nuances between creating a control($fieldName, $options) and inputType($fieldName, $options), so they might produce different outputs.
I'm currently working in a project in CakePHP 4.x. My project also have many to many associations and it saves ok in the tables, but CakePHP baked it quite differently from yours. Let me show you the differences, maybe it is of some help.
I'll "translate" the names of my entities, tables, etc., to the ones used in your question, ok?
First, a brief: in my project, cake didn't bake models (entity and table) for the relational table. The relational table don't have its own models, and is only refered to in the initialize method from the ItemsTable and WantedSizesTable. There are also minor changes in the Item and WantedSize entities and in the view.
Second, your entity names doesn't comply with Cake's naming conventions, which can lead to many issues. This can even be the cause to the problems you're enduring now. I have changed some names to comply with them, but I'd suggest to you to read it thoroughly: https://book.cakephp.org/4/en/intro/conventions.html.
Third and more important, lets start.
My many-to-many relational mySQL tables doesn't have their own Table models. My SQL does indeed have a items_wanted_sizes table, but the CakePHP project does NOT have corresponding models called ItemsWantedSizesTable nor ItemsWantedSizes. It does have ItemsTable and WantedSizesTable tables and Item and WantedSize entities, and it's all.
Let's see the Table Models. The relational mySQL table items_wanted_sizes is refered only in the tables initialize method of both table models in PHP, like this:
// ItemsTable.php
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('items');
$this->setDisplayField('item_name');
$this->setPrimaryKey('id');
// ...
// Other associations...
// ...
// The relational mysql table only shows here:
$this->belongsToMany('WantedSizes', [
'foreignKey' => 'item_id', // Item Id field from the relational table
'targetForeignKey' => 'wanted_size_id', // Size Id field from the relational table
'joinTable' => 'items_wanted_sizes',
]);
}
The same happens on WantedSizesTable:
// WantedSizesTable.php
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('wanted_sizes');
$this->setDisplayField('wanted_size_name');
$this->setPrimaryKey('id');
// ...
// Other associations...
// ...
// The relational mysql table only shows here:
$this->belongsToMany('Items', [
'foreignKey' => 'wanted_size_id', // Size Id fieldname from the relational table
'targetForeignKey' => 'item_id', // Item Id fieldname from the relational table
'joinTable' => 'items_wanted_sizes',
]);
}
Regarding to the entities models, I also don't have a relational entity model. Both Item and WantedSize entity models refer to each other, but, contrary to your case, they don't refer to the relational table (only to each other):
// src/Model/Entity/Item.php
// #property \App\Model\Entity\WantedSize[] $wanted_sizes // NOT item_wanted_sizes
protected $_accessible = [
// ...
'wanted_sizes' => true, // NOT item_wanted_sizes
// ...
];
Same in WantedSize:
// src/Model/Entity/WantedSize.php
// #property \App\Model\Entity\Item[] $items // NOT item_wanted_sizes
protected $_accessible = [
// ...
'items' => true, // NOT item_wanted_sizes
// ...
];
Now we saw our models, lets jump the add (or edit) action view. With the associations correctly set, I only needed to do this:
// src/templates/Items/add.php
echo $this->Form->control('wanted_sizes._ids', ['options' => $wantedSizes]);
I didn't even needed to tell FormHelper it's a multiselect, because it is in the table configurations.
The HTML generated is quite different from yours (like 404 also answered above):
<select name="wanted_sizes[_ids][]" multiple="multiple" id="wanted-sizes-ids">
<option value="1">Some wanted size...</option>
<!-- ... -->
</select>
This worked perfectly fine for me, saving data in the relational table in mysql.
In Cakephp4 one thing to check. If the entities are not showing the associated data after being patched prior to saving. You can test by dumping the entity after its patched in the controller.The associated data should show there.
$discount = $this->Discounts->patchEntity($discount, $this->request->getData());
dd($discount);
Check the Entity. Is the associated data in the $_accessible array? The fields that you update need to be in this array but also the associated models/tables.
class Discount extends Entity
{
protected $_accessible = [
...
'products' => true,
...
];
}
https://api.cakephp.org/4.0/class-Cake.ORM.Entity.html#$_accessible
I'm trying to get the last inserted id made from create() eloquent in laravel.
Here's my laravel code
$product = ProductModel::create([
'prodCode' => $prodCode,
'prodTitle' => $dataProducts->prodTitle,
'prodDesc' => $dataProducts->prodDesc,
'attachment' => "images/products/".$attachment,
'prodSize' => $dataProducts->prodSize,
'prodCategory' => $dataProducts->prodCategory,
'prodPrice' => $dataProducts->prodPrice,
'created_by' => auth()->user()->id
]);
I will use this last inserted id for another query with the same function.
Is it possible to do it with this way of saving data, or do I need to convert this code to another efficient way?
The create function of a model returns new record.
Very easily:
$product = ProductModel::create([...]);
// last inserted id
$lastInsertedId = $product->$idField;
Well in this case your are doing right !
use print_r($product->id) to see the last inserted id if the field name is id
I am using Laravel 5.5 and I am declaring my model object the following:
$product = new product();
$product->name = $coinArr[$key];
$product->symbol = $symbolArr[$key];
$product->current_price = $priceArr[$key];
///save image to public folder
$fileName = basename($imgArr[$key]);
Image::make($imgArr[$key])->save(public_path('images/' . $fileName));
$product->asset_logo = $fileName;
//$product->updateOrCreate();
App/Product::updateOrCreate($product);
If the product does not exist in the database I would like to create it else just update it.
I tried the following two ways to use the updateOrCreate method. However, I receive the following error for App/Product::updateOrCreate($product);:
Type error: Too few arguments to function Illuminate\Database\Eloquent\Builder::updateOrCreate(), 0 passed in C:\Users\admin\Desktop\Coding Projects\laravel_proj\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php on line 1455 and at least 1 expected
And the following error for $product->updateOrCreate();:
Type error: Too few arguments to function Illuminate\Database\Eloquent\Builder::updateOrCreate()
Any suggestions how to use updateOrCreate with my model object?
I appreciate your replies!
When you use updateOrCreate, you need to choose which attributes are used to determine if the product exists already. The function takes 2 arrays:
product::updateOrCreate([
'name' => $coinArr[$key] //Laravel will check if this model exists by name
],[
'symbol' => $symbolArr[$key] //if exists, will update symbol. if doesnt exist, will create new with this name and symbol
]);
That's not how the updateOrCreate() method works. In the first parameter you put an array with search conditions. If you want to search existing route by name for example, the correct syntax will be:
Product::updateOrCreate(
[
'name' => $coinArr[$key]
],
[
'symbol' => $symbolArr[$key],
'current_price' => $symbolArr[$key],
'asset_logo' => $fileName
]
);
The second parameter is array for creating a new object.
https://laravel.com/docs/5.5/eloquent#other-creation-methods
Part 1: Main Question
On my colours_tab table (PostgreSQL 9.6), I have a column called colours_json_col of type JSONB.
I have the following code in my Laravel controller which creates a new record on the afore-mentioned table:
$colour_rec = new ColoursModel();
$colour_rec -> colours_json_col = ['fruits' => ['apple' => 'pink'] ];
$colour_rec -> update (['colours_json_col->fruits->apple' => 'green']);
$colour_rec -> saveOrFail();
The above code doesn't error or throw an exception, yet after executing it the new record in my database contains the following JSON data:
{"fruits": {"apple": "pink"}}
Obviously, what I want is for the apple to be green, not pink! The documentation here (https://laravel.com/docs/5.5/queries#updates) suggests that I'm doing the right thing in order set it 'green'. Can anyone see what I'm doing wrong?
Part 2: Bonus Question
In order to prevent the above code from erroring, I have had to declare the column colours_json_col as $fillable in the model:
protected $fillable = ['colours_json_col'];
I don't really want to set the column as $fillable if at all possible. Therefore, is there a way to update the value without having to call the update() function?
Answering both parts of the question in one:
$colour_rec = new ColoursModel();
$colour_rec -> colours_json_col = ['fruits' => ['apple' => 'pink'] ];
$colour_rec -> setAttribute ('colours_json_col->fruits->apple', 'green');
$colour_rec -> saveOrFail();
It seems to be an undocumented feature in Eloquent, as far as I can tell.