Welcome Guest, Not a member yet? Register   Sign In
insert without data
#1

(This post was last modified: 06-05-2022, 04:30 AM by webdeveloper.)

Hi guys,
i'm facing one "problem" with inserting new data into table.

PHP Code:
$this->model->insert([]) 

for me expecting query would be:

Code:
INSERT INTO gallery VALUES();

which is fine and works well - inserts one new row into defined table

instead of this, codeigniter returns me an error 'no data for insert'

table structure:

Code:
gallery_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT
created_at DATETIME DEFAULT CURRENT_TIMESTAMP()
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP()

I really don't need any data to insert.

Looking for solution how to override this behaviour without any hack and with query builder.

Wouldn't be great to check in query builder, if param $data of function insert($data = null, ...) isn't null but can be empty array?

vendor/codeigniter4/framework/system/Model.php

PHP Code:
/**
    * Inserts data into the database. If an object is provided,
    * it will attempt to convert it to an array.
    *
    * @param array|object|null $data
    * @param bool              $returnID Whether insert ID should be returned or not.
    *
    * @throws ReflectionException
    *
    * @return BaseResult|false|int|object|string
    */
    public function insert($data nullbool $returnID true)
    {
        if (! empty($this->tempData['data'])) {
            if (empty($data)) {
                $data $this->tempData['data'] ?? null;
            } else {
                $data $this->transformDataToArray($data'insert');
                $data array_merge($this->tempData['data'], $data);
            }
        }

        $this->escape  $this->tempData['escape'] ?? [];
        $this->tempData = [];

        return parent::insert($data$returnID);
    
Reply
#2

it's the Model itself that does this check as it's expecting to work with data. The Query Builder, on the other hand, doesn't care. So you should be able to do something like:

PHP Code:
db_connect()->table('gallery')->insert([]);

or 

db_connect()->query('INSERT INTO gallery VALUES();'); 
Reply
#3

(This post was last modified: 06-07-2022, 03:16 AM by webdeveloper.)

Yes, sure, I can. And I did, ofcourse, there was no other way. But for me, that's ugly solution now.

1. I need to defined table again (in API controller), which is already defined in connected model
2. I need to use string query (which I don't like to do anywhere in the application), instead query builder (which i prefer)

My question is, if it's possible to include this into any next update, as long as we cannot extend BaseModel. This should be, according to me, obvious behaviour

PHP Code:
// current - ugly
            $db->query('INSERT INTO `gallery` VALUES()');

            $galleryId $db->insertID();

// much more nice and safe solution, it should be done like this
            $galleryId $this->model->insert([]); 
Reply
#4

It's definitely something I can bring up with the team.

I'd be lying if I said I hadn't been bit by that "No Data" exception a time or two myself.

The thing to remember is that the Model class is basically a large set of convenience methods focused around a single table. So there will inherently be slightly different restrictions there than would be just using the query builder itself.

And there's no performance cost from using db_connect()->table() again, compared to doing it through the model.
Reply
#5

Yes i know and it really makes things easier many times, by defining $table variable and other stuff inside my Model. I like that a lot!

I would really appreciate this change. Fighted with this many times.

The exception "no data for insert" is great. Saves some time, when I forget to pass variable to insert() function. But not in case when I know what I'm doing. If I set empty array i should get query exception, directly from database like "the column XYZ has no default value set" or smthing similiar.

Imagine this scenario:

PHP Code:
$data = [];

if (
$this->request->getPost('use_reply_to')) {
    $data['reply_to_email'] = $this->request->getPost('reply_to_email');
    $data['reply_to_name'] = $this->request->getPost('reply_to_name');
}

$emailTemplate = $this->model->insert($data); 

Data array, is again empty and I want system behave according to database structure and default column values.

Currently I have to do it like this, but things could be much more easier Smile Thank you

PHP Code:
$data = [];

if (
$this->request->getPost('use_reply_to')) {
    $data['reply_to_email'] = $this->request->getPost('reply_to_email');
    $data['reply_to_name'] = $this->request->getPost('reply_to_name');
}

if (empty(
$data)) {
   db_connect()->query('INSERT INTO gallery VALUES();');

   $emailTemplateId db_connect()->insertID()
} else {
   $emailTemplateId $this->model->insert($data);

Reply
#6

This does not work, because Query Builder does not permit it.
PHP Code:
db_connect()->table('gallery')->insert([]); 

Quote:"CodeIgniter\Database\Exceptions\DataException". Message was: "You must use the "set" method to update an entry."
Reply




Theme © iAndrew 2016 - Forum software by © MyBB