How to get insert id after save to database in CodeIgniter 4 - php

I'm using Codeigniter 4.
And inserting new data like this,
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$userModel->save($data);
Which is mentioned here: CodeIgniter’s Model reference
It's doing the insertion.
But I haven't found any reference about to get the inserted id after insertion.
Please help! Thanks in advance.

This also works.
$user= new UserModel();
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$user->insert($data);
$user_id = $user->getInsertID();

I got a simple solution after researching on the core of the CI 4 framework.
$db = db_connect('default');
$builder = $db->table('myTable');
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$builder->insert($data);
echo $db->insertID();
Hope they'll add a clear description on the docs soon.

There are three way to get the ID in ci4:
$db = \Config\Database::connect();
$workModel = model('App\Models\WorkModel', true, $db);
$id = $workModel->insert($data);
echo $id;
echo '<br/>';
echo $workModel->insertID();
echo '<br/>';
echo $db->insertID();

In fact, what you did is correct.
You did it in the best and easiest way and following the Codeigniter 4 Model usage guide.
You just missed: $id = $userModel->insertID;
Complete code using your example:
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$userModel->save($data);
$id = $userModel->insertID;
That's it. You don't need all this code from the examples above nor calling database service or db builder if you're using codeigniter's models.
Tested on CodeIgniter 4.1.1 on 3/19/2021

To overcome this, I modified system/Model.php in the save() method---
$response = $this->insert($data, false);
// add after the insert() call
$this->primaryKey = $this->db->insertID();
Now, in your models, you can just reference "$this->primaryKey" and it will give you the needed info, while maintaining the data modeling functionality.
I'm going to submit this over to the CI developers, hopefully it will be added in.

For CI4
$settings = new SettingsModel();
$settingsData = $settings->find(1);
<?php namespace App\Models;
use App\Models\BaseModel;
class SettingsModel extends BaseModel
{
protected $table = 'users';
protected $primaryKey = 'id';
}
$settings->find(1); will return a single row. it will find the value provided as the $primaryKey.

hi guys in my case i use ci model to save data and my code is :
$x=new X();
$is_insert= $x->save(['name'=>'test','type'=>'ss']);
if($is_insert)
$inserted_id=$x->getInsertID()

I'm using mysql for my database then I ran this inside my seeder
$university = $this->db->table('universities')->insert([
'name' => 'Harvard University'
]);
$faculty = $this->db->table('faculties')->insert([
'name' => 'Arts & Sciences',
'university' => $university->resultID
]);
Look at code line 6
$university->resultID
variable $university here is type object of CodeIgniter\Database\MySQLi\Result class
Corect me if I'm wrong or any room for improvements

I had the same problem but, unfortunately, the CI4 documentation doesn't help much. The solution using a builder woks, but it's a workaround the data modeling. I believe you want a pure model solution, otherwise you wouldn't be asking.
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$id = $userModel->save($data);
Trying everything I could think of I decided to store the result of the save method to see if returned a boolean value to indicate if the saving was sucessful. Inspecting the variable I realized it returns exactly what I wanted: the lost insertID.
I believe CodeIgniter 4 is quite an easy and capable framework that does a decent job in shared hosts where other frameworks can be a little demanding if you're learning but lacks the same fantastic documentation and examples of CI3. Hopefully, that's only temporary.
By the way, you code works only if you are using the $userModel outside the model itself, for example, from a Controller. You need to create a model object like:
$userModel = New WhateverNameModel();
$data = [any data];
$userModel->save($data);
Alternatively, if you are programming a method inside the model itself (my favorite way), you should write
$this->save($data);

Related

Laravel firstOrCreate not merging the search entry

There's plenty of other questions surrounding this where people were using it wrong, but I'm confident I have the proper syntax and it's just leaving out the search term by the time it makes it to sql.
I've done 2 iterations. One where I add the 'sub' again and one where I don't
protected function upsertUser( $profile ) {
$sub = $profile['sub'];
$email = $profile['email'];
$name = $profile['name'];
Log::stack(['single'])->critical(compact("sub", "email", "name"));
return User::firstOrCreate(compact("sub"), ['sub' => $profile['sub'], 'email' => $profile['email'] ?? '', 'name' => $profile['name'] ?? '']);
}
protected function upsertUser( $profile ) {
$sub = $profile['sub'];
$email = $profile['email'];
$name = $profile['name'];
Log::stack(['single'])->critical(compact("sub", "email", "name"));
return User::firstOrCreate(compact("sub"), ['email' => $profile['email'] ?? '', 'name' => $profile['name'] ?? '']);
}
In both cases, sub just doesn't make it to the creation failing with:
A message showing that it doesn't even try to insert 'sub'
Logging the array shows that it contains the desired data.
Now I had come across a post where someone suggested that it was mass assignment protection stopping me from adding sub. I don't think it's related, but I tried to add
protected $fillable = [
'name',
'email',
'sub',
];
To the users model but it did not help. I do not want to allow nullable, because I need that data.
So this was terrible. I'm following along with this Auth0 sample app guide and in this sample they have a users model. I think this is default to laravel.
App/models/users != App/user
I had to make sub fillable on that "model" it's not even a traditional model it extends Auth\User

Php unit test problem with create customer

Im having some problems with my unittest.
My unittest works perfect if the test is about to get anything from my datbase table.
But if I should create example a customer, im having isuses with how I should do that.
Here is an example of my getCustomer test:
Try something like this:
<?php
$controller = new Veosoft_Controller();
$_REQUEST = [
'displayName' => 'meh',
'firstname' => 'Kristian',
'lastname' => 'Pedersen',
];
$controller->createCustomer();
// then somehow get the last insert ID?
$customer = $controller->getSpecificCustomer($customerId);
$this->assertEquals($customer->id, $customerId);
$this->assertEquals($customer->firstname, $firstName);
$this->assertEquals($customer->lastname, $lastName);
Of course it would be better if you just mocked the DB class itself?

Return object base on request uri

so I have this modular web application that has doctrine2 intergrated with zend framework 1.12.
So I want to return one object base on the request uri, for example: url/api/people/1, which return the person one base on their id.
*side note, I can return all objects of people, I just want to select one object once the user enter's a number.
What I have tried, was to grab the parameter from the url and just pass it through the find function, but doctrine doesn't understand these numbers passed through the uri, and believes they're actions.
if($this->getRequest()->isGet())
{
$request = $this->getRequest();
$id = $request->getParam('peopleId');
$em = $this->getEntityManager();
$peopleRepo = $em->getRepository('API\Entity\People');
$people = $peopleRepo->find(3); //$id goes into find function
$resultArray[] =
[
'id' => $people->getId(),
'firstname' => $people->getFirstName(),
'lastname' => $people->getLastName(),
"food" => $people->getFavoriteFood()
];
echo json_encode($resultArray, JSON_PRETTY_PRINT);
var_dump($people);
*****EDIT*****
So I have added code that I can manually find one person, but I want to do that through the url, how can I achieve this?
Try:
$peopleRepo = $em->getRepository('API\Entity\People')->findBy(array('id' => $id));
Or
$peopleRepo = $em->getRepository('API\Entity\People')->findById($id);
See Doctrine docs:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#by-simple-conditions

Passing dependency parameters to App::make() or App::makeWith() in Laravel

I have a class that uses a dependency. I need to be able to dynamically set parameters on the dependency from the controller:
$objDependency = new MyDependency();
$objDependency->setSomething($something);
$objDependency->setSomethingElse($somethingElse);
$objMyClass = new MyClass($objDependency);
How do I achieve this through the Service Container in Laravel? This is what I've tried but this seems wrong to me. In my AppServiceProvider:
$this->app->bind('MyClass', function($app,$parameters){
$objDependency = new MyDependency();
$objDependency->setSomething($parameters['something']);
$objDependency->setSomethingElse($parameters['somethingElse']);
return new MyClass($objDependency);
}
And then in the controller i'd use this like:
$objMyClass = App:make('MyClass', [
'something' => $something,
'somethingElse' => $somethingElse
]);
Is this correct? Is there a better way I can do this?
Thanks
You can see detailed documentation here: https://laravel.com/docs/5.6/container#the-make-method
It's done like this:
$api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);
Or use the app() helper
$api = app()->makeWith(HelpSpot\API::class, ['id' => 1]);
It is essential to set the array key as the argument variable name, otherwise it will be ignored. So if your code is expecting a variable called $modelData, the array key needs to be 'modelData'.
$api = app()->makeWith(HelpSpot\API::class, ['modelData' => $modelData]);
Note: if you're using it for mocking, makeWith does not return Mockery instance.
You can also do it this way:
$this->app->make(SomeClass::class, ["foo" => 'bar']);

Update only one field on Cakephp 3

In some part of my app I need to update only the field is_active of some table with a lot of fields. What is the best approach to update only this field and avoid the validations and requiriments of all other fields?
And if you want to update particular row only , use this:
$users= TableRegistry::get('Users');
$user = $users->get($id); // Return article with id = $id (primary_key of row which need to get updated)
$user->is_active = true;
// $user->email= abc#gmail.com; // other fields if necessary
if($users->save($user)){
// saved
} else {
// something went wrong
}
See here (Updating data in CakePHP3).
This will work:
$users = TableRegistry::get('Users');
$query = $users->query();
$query->update()
->set(['is_active' => true])
->where(['id' => $id])
->execute();
http://book.cakephp.org/3.0/en/orm/query-builder.html#updating-data
When you don't want callbacks to be triggered, just use updateAll()
$table->updateAll(['field' => $newValue], ['id' => $entityId]);
Using the example here: http://book.cakephp.org/3.0/en/orm/database-basics.html#running-update-statements. Run the code below to update all records in table_name_here table with a new value for is_active column.
use Cake\Datasource\ConnectionManager;
$connection = ConnectionManager::get('default');
$connection->update('table_name_here', ['is_active' => 'new_value_here']);
I faced this issue when upgrading my project from 2.10 to 3.x.
In 2.10 you could update a single field using:
$this->Menus->saveField('css', $menucss);
But since this method was deprecated, we do as below now, considering that callbacks will not be triggered:
$this->Menus->updateAll(['css' => $menucss], ['id' => $menu_id]);
The other answers don't use internationalization and other models props, callbacks, etc.
I think this is because of the query builder, it does not use the models and so their behaviors, therefore you should use:
$this->loadModel('Inputs');
$input = $this->Inputs->find()->where(['`key`' => $this->request->data['id']])->first();
$this->Inputs->patchEntity($input, ['prop' => $this->request->data['prop']]);
if ($this->Inputs->save($input)) {
die(json_encode(true));
} else {
die(json_encode(false));
}

Categories