-
MorganL
-
-
Offline
-
Platinum Member
-
- Posts: 438
- Thank you received: 53
-
Karma: 15
-
|
In J-Cook components, is the method of getting the last saved ID the same as the recommended default
$db->query();
$lastRowId = $db->insertid();
I need to fire a process after the save of a NEW item, and whereas I can usually just determine the existence of data{'id} to see if the record is new or updated, in this instance I absolutely need the ID of the newly created record, with no chance it can accidentally be grabbed from another user who may be doing something on the same part of the component elsewhere
|
Morgan Leecy MCSE
Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
|
-
Romkabouter
-
-
Offline
-
Elite Member
-
- Posts: 310
- Thank you received: 131
-
Karma: 48
-
|
Hi,
I think you should fork the controller for the item (singular)
Copy paste the save function.
In there, there is $result = parent::save();
//Get the model through postSaveHook()
if ($this->model)
{
$model = $this->model;
$item = $model->getItem();
} So, your $item will hold the saved data, you can then user $item->id and that will hold the inserted ID
Using insertid() can lead to problems if you have a lot of activity with users saving items.
You say you need to fire a process after the saving of a new item.
In my opinion iyou can do that in a controller, but maybe in your case this is not possible
|
The following user(s) said Thank You: admin
|
-
MorganL
-
-
Offline
-
Platinum Member
-
- Posts: 438
- Thank you received: 53
-
Karma: 15
-
|
Seriously awesome, you are an amazing asset to J-Cook, brilliant support. Thanks
|
Morgan Leecy MCSE
Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
|
-
MorganL
-
-
Offline
-
Platinum Member
-
- Posts: 438
- Thank you received: 53
-
Karma: 15
-
|
Struggling to get this to work.. here is my model and the ONLY attempt that gets response
$bemodel = CkJModel::getInstance('bidelement', 'MycomponentModel');
$result1 = $bemodel ->save(
array(
'associated_bid' => $data['id'],
'film' => $data['film'],
'global' => 0,
'regional_purchase' => 1,
'territorial_purchase' => 0,
'region' => $region
)
);
$db->query();
$lastRowId = $db->insertid();
This actually returns a value.. but it ALSO refires the save task so I get 2 records. The id returned IS the last ID in the table
I have tried various derivations of rom's suggestion and this just returns null.
What code can I type into the above snippet instead of
$db->query();
$lastRowId = $db->insertid();
That will return the ID of the newely created ID from bidelement
|
Morgan Leecy MCSE
Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
|
-
Romkabouter
-
-
Offline
-
Elite Member
-
- Posts: 310
- Thank you received: 131
-
Karma: 48
-
|
I am going to try this one myself, sounds like a nice challenge.
I will create a testcomponent, but I need some more info.
Can you describe your functionality?
When saving an item, you say you want to fire another process.
Is the other process another screen or something?
|
|
-
MorganL
-
-
Offline
-
Platinum Member
-
- Posts: 438
- Thank you received: 53
-
Karma: 15
-
|
I have a component where a user creates a BID and the first thing they do on creating the bid is save it to get an ID.. thats the easy bit, and this opens up the rest of the form.
One of the things they do is choose the SCOPE of the bid by a checkbox group of regions.
As soon as they click NEXT, the model loops through all the checked boxes and creates a record in the
BIDELEMENT table which is linked to BID via an FK (so if they choose 3 regions, three bidelements are added)
HOWEVER there is a THIRD table which is a XREF which basically allows a user to use the RIGHTS they want against each regions (i.e BIDELEMENT)
1 BID -> x BIDELEMENTS -> x RIGHTS
BIDELEMENTS are created fresh every time (there can be a lot of changes, so I just purge the elements each save and re-add them. Not efficient, but does the job
This means that during the form save the BIDELEMENT is always created afresh, and then the rights that have been ticked are generated against a fresh BIDELEMENT record. I have not done this loop yet, but once I get this id thing sorted, that will not actually be a problem
So the full code AS IT STANDS is (regionchoice is the checkbox group regionschoiuce[]) which works lovely)
NOTE : this ALL works apart from just not grabbing that ID
foreach ($_POST['regionchoice'] as $region) {
$bemodel = CkJModel::getInstance('bidelement', 'MycomponentModel');
$result1 = $bemodel ->save(
array(
'associated_bid' => $data['id'],
'film' => $data['film'],
'global' => 0,
'regional_purchase' => 1,
'territorial_purchase' => 0,
'region' => $region
)
);
$db->query();
$lastRowId = $db->insertid();
// this will eventually also be a loop of the rights to the element
$rdmodel = CkJModel::getInstance('xrightdesired', 'MycomponentModel');
$result2 = $rdmodel ->save(
array(
'associated_bid' => $data['id'],
'bid_element' => $lastRowId,
'right' => 1 //this is just a test figure for now
)
);
// end the loop when defined
}
Maybe you will be able to see the problem without actually coding anything
|
Morgan Leecy MCSE
Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
|
-
Romkabouter
-
-
Offline
-
Elite Member
-
- Posts: 310
- Thank you received: 131
-
Karma: 48
-
|
When seeing this code, I also think I see your problem.
I thought you were not using insertid() anymore, but I see it in your code.
isertid() does not work on DB level, but on table level.
So don't use $db->query();
$lastRowId = $db->insertid();
Instead use $table = JTable::getInstance('bidelement', 'MycomponentTable');
$newid = $table->getDBO()->insertid(),
That will probably fix your problem
|
|
-
MorganL
-
-
Offline
-
Platinum Member
-
- Posts: 438
- Thank you received: 53
-
Karma: 15
-
|
You sir.. are a genius
Worked
|
Morgan Leecy MCSE
Novell / Linux
PHP. MYSQL, Apache, node.js
Coldfusion, JQuery, HTML5
Joomla
|
-
krasy
-
-
Offline
-
Premium Member
-
- Posts: 90
- Thank you received: 8
-
Karma: 5
-
|
Romkabouter wrote:
Hi,
I think you should fork the controller for the item (singular)
Copy paste the save function.
In there, there is $result = parent::save();
//Get the model through postSaveHook()
if ($this->model)
{
$model = $this->model;
$item = $model->getItem();
} So, your $item will hold the saved data, you can then user $item->id and that will hold the inserted ID
Using insertid() can lead to problems if you have a lot of activity with users saving items.
You say you need to fire a process after the saving of a new item.
In my opinion iyou can do that in a controller, but maybe in your case this is not possible
thx hey man that was user useful
Happy Easter! btw
|
|
-
vlemos
-
-
Online
-
Elite Member
-
- Posts: 295
- Thank you received: 41
-
Karma: 21
-
|
Hello Admin / Cooks
I am not sure if this is a bug or my inability to use the save method.
I have a service page which loads a record from a services table. On that same page I have a note textarea which loads an empty body field from a notes table. These fields all play nicely together until I try to save a note. On "Enter", the note body is sent to the server along with the service id and everything works: $note = CkJModel::getInstance('Note', 'BookingsModel');
$result = $note->save(
array(
'service_id' => $sid,
'body' => $body,
)
);
Until we reach: libraries/legacy/model/admin.php /**
* Method to save the form data.
*
* @param array $data The form data.
*
* @return boolean True on success, False on error.
*
* @since 12.2
*/
public function save($data)
{
$dispatcher = JEventDispatcher::getInstance();
$table = $this->getTable();
$context = $this->option . '.' . $this->name;
if ((!empty($data['tags']) && $data['tags'][0] != ''))
{
$table->newTags = $data['tags'];
}
$key = $table->getKeyName();
$pk = (!empty($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');
$isNew = true;
The line: $pk = (!empty($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');
Calls populateState on the note model, which then returns the cid of the service, which is not good! This results in an update once a note with the returned $pk value exists. If I change $pk = null, a new note is inserted as expected.
I can find a solution; however, I am not sure if this is a problem or if I am simply not asking Cook to save my data using the correct tone of voice.
Any feedback would be appreciated. . .
Thanks as always
vlemos
|
|
-
admin
-
-
Offline
-
Administrator
-
-
Chef
- Posts: 3711
- Thank you received: 987
-
Karma: 140
-
|
This is normal because Joomla automatically load the ID from the URL (since ORM you can change that, but not in the controller)
Well, you can do this to solve your problem : $note = CkJModel::getInstance('Note', 'BookingsModel');
$result = $note->save(
array(
//HERE
'id' => 0,
'service_id' => $sid,
'body' => $body,
)
);
|
Coding is now a piece of cake
Last Edit: 09 Jan 2017 12:53 by admin.
The following user(s) said Thank You: vlemos
|
-
vlemos
-
-
Online
-
Elite Member
-
- Posts: 295
- Thank you received: 41
-
Karma: 21
-
|
Thanks Admin, you are the best. . .
Instinctively, I tried 'id' => null and it didn't work so I hacked the State while waiting for feedback. Would not have tried assigning any number tho.
Thanks again
vlemos
|
|
-
vlemos
-
-
Online
-
Elite Member
-
- Posts: 295
- Thank you received: 41
-
Karma: 21
-
|
Hello Cooks
I had the issue of getting the inserted ID a few hours ago. And although this thread is almost a year old I thought it may help if I posted my findings to assist future cooks.
As above, my save routine is called from the "Notes" collection model like: $note = CkJModel::getInstance('Note', 'BookingsModel');
$note->setState('note.id', 0);
$item = $note->save(
array(
"service_id" => $sid,
"body" => $body,
"ordering" => 0,
"created_on" => date("Y-m-d H:i:s")
)
);
This calls the save method on the Item-model, which calls the same method on the Item class model on the admin-side of the component. The component then passes the request to core Joomla.
In other words, my call calls "save" in this sequence, 1 -> 2 -> 3:
1). . . ./components/com_xxxxx/models/note.php
2). . . ./administrator/components/com_xxxxx/classes/model/item .php
3). . . ./libraries/legacy/model/admin.php => JModelAdmin->save()
Joomla actually returns the ID of the inserted record to "item .php", and it is available in the Item state var. The ID is now publicly available and can be accessed via "components/com_xxxxx/models/note.php" as $note->getState('note.id'); /**
* Save an item.
*
* @access public
* @param array $data The post values.
*
* @return boolean True on success.
*/
public function save($data)
{
.
.
.
if (parent::save($data)) {
// For more processing, the ID is available here.
// and $note->getState('note.id') for wider scope.
$inserted_id = $this->getState('note.id');
return true;
}
return false;
}
WARNING: this is not a forked solution! This will only work on the core component files. If you need to move it to your fork-files, it requires a bit more work related to the calls to "parent::". Would be happy to share if someone wants.
Warm regards
vlemos
|
Last Edit: 22 Feb 2017 03:11 by vlemos.
|
|