Cakephp specify fields being saved? - php

In my model, I have a field called difficulty, but no matter what value i give it, a value of 1 is saved to the database.
I did a datadump on the model before I did a save() and this is what I see:
Array
(
[title] => testtt34
[serves] => 32
[prep_time] => 32
[cooking_time] => 32
[difficulty] => 4
)
But the sql query cakephp generated is this:
INSERT INTO `recipes` (`title`, `serves`, `prep_time`, `cooking_time`, `difficulty`, `modified`, `created`) VALUES ('testtt34', 32, 32, 32, 1, '2011-03-13 19:15:16', '2011-03-13 19:15:16')
What the heck? even though difficulty is clearly 4 in my datadump, the sql generated inserted difficulty = 1.
//Do some checking to make sure the data is from proper location
$this->data = Sanitize::clean($this->data);
$this->Recipe->data = $this->data;
//error checking
$this->pa($this->Recipe->data['Recipe']);
if ($this->Recipe->save())
{
//Blah do some stuff
}

Nevermind I accidentally set difficulty's type as TINYINT(1) meant to do TINYINT(3), well that fixed it. Very dumb mistake.

Related

Array to string conversion error in Code Igniter when inserting array of data into table in database

I'm trying to insert an array of data into a table in database but an error said Array to string conversion error
This is the post function in my controller, first i post an array of data. The values of the array will be the names, and numbers, they are not id. The id is only kodejdwl. This will be pass to my model
function index_post() {
$data = array(
'kodejdwl' => $this->post('kodejdwl'),
'tahun_akad' => $this->post('kode_tahun_akad'),
'semester' => $this->post('semester'),
'mk' => $this->post('mk'),
'ruangan' => $this->post('ruangan'),
'nama_dosen' => $this->post('nama_dosen'),
'namakelas' => $this->post('nama_kelas'),
'jam_mulai' => $this->post('jam_mulai'),
'jam_selesai' => $this->post('jam_selesai'),
);
}
After the data from above code is passed to the model. I created some new variables which are the id of each the name of the value in the array data. e.g if the value of data['mk'] is Website then the id will be 1 and that id will be stored in variable $kodemk and i do it to each value in the data. Then i created new_data which stores array of the id's which i previously made. Then i insert that array into one table in my database. I thought it would be fine but it said Array to string conversion error. What should i do so i could insert that array into the table in my database?
public function insert($data){
$this->db->select('thn_akad_id');
$tahunakad_id = $this->db->get_where('tik.thn_akad',array('tahun_akad'=>$data['tahun_akad'],'semester_semester_nm'=>$data['semester']))->result();
$this->db->flush_cache();
$this->db->select('kodemk');
$kode_mk = $this->db->get_where('tik.matakuliah',array('namamk'=>$data['mk']))->result();
$this->db->flush_cache();
$ruangan = $this->db->get_where('tik.ruangan', array('namaruang' => $data['ruangan']), 1)->result();
$this->db->flush_cache();
$this->db->select('nip');
$nip_dosen = $this->db->get_where('tik.staff',array('nama'=>$data['nama_dosen']))->result();
$this->db->flush_cache();
$this->db->select('kodeklas');
$kodeklas = $this->db->get_where('tik.kelas',array('namaklas'=>$data['namakelas']))->result();
$this->db->flush_cache();
$this->db->select('kode_jam');
$kode_mk = $this->db->get_where('tik.wkt_kuliah',array('jam_mulai'=>$data['jam_mulai'],'jam_selesai'=>$data['jam_selesai']))->result();
$this->db->flush_cache();
$new_data = array(
'kodejdwl' => $data['kodejdwl'],
'thn_akad_thn_akad_id' => $tahunakad_id,
'matakuliah_kodemk' => $kode_mk,
'ruangan_namaruang' => $ruangan,
'staff_nip' => $nip_dosen,
'kelas_kodeklas' => $kodeklas,
);
$insert = $this->db->insert('tik.jadwal_kul', $new_data);
return $this->db->affected_rows();
}
You probably want to use row() instead of result() because it'll contain only one result that you want. If you want to use result() and store multiple values then you'll have to use implode to concatenate them and store it as a string.
I've written a possible solution for your problem; Some things were missing, so I've mentioned them in the comments. See if this helps you.
public function insert($data){
$this->db->select('thn_akad_id');
$tahunakad_id = $this->db->get_where('tik.thn_akad',array('tahun_akad'=>$data['tahun_akad'],'semester_semester_nm'=>$data['semester']))->row(); // use row here
$this->db->flush_cache();
$this->db->select('kodemk');
$kode_mk = $this->db->get_where('tik.matakuliah',array('namamk'=>$data['mk']))->row();
$this->db->flush_cache();
// remove your_ruangan_column with your desired column name
$this->db->select('your_ruangan_column');
$ruangan = $this->db->get_where('tik.ruangan', array('namaruang' => $data['ruangan']), 1)->row();
$this->db->flush_cache();
$this->db->select('nip');
$nip_dosen = $this->db->get_where('tik.staff',array('nama'=>$data['nama_dosen']))->row();
$this->db->flush_cache();
$this->db->select('kodeklas');
$kodeklas = $this->db->get_where('tik.kelas',array('namaklas'=>$data['namakelas']))->row();
$this->db->flush_cache();
// Not sure where this ↓↓ is being used but you can use it the same way as others
$this->db->select('kode_jam');
// duplicate variable name here ↓↓ (fix this)
$kode_mk = $this->db->get_where('tik.wkt_kuliah',array('jam_mulai'=>$data['jam_mulai'],'jam_selesai'=>$data['jam_selesai']))->row();
$this->db->flush_cache();
$new_data = array(
'kodejdwl' => $data['kodejdwl'],
'thn_akad_thn_akad_id' => $tahunakad_id->thn_akad_id, // {$tahunakad_id} consists an object with the key {thn_akad_id}-- table_column_name
'matakuliah_kodemk' => $kode_mk->kodemk, // ...
'ruangan_namaruang' => $ruangan->your_ruangan_column, // ...
'staff_nip' => $nip_dosen->nip, // ...
'kelas_kodeklas' => $kodeklas->kodeklas // ...
);
$insert = $this->db->insert('tik.jadwal_kul', $new_data);
return $this->db->affected_rows();
}
Your are making a total of 7 separate trips to the database. Best practice recommends that you always minimize your trips to the database for best performance. The truth is that your task can be performed in a single trip to the database so long as you set up the correct INSERT query with SELECT subqueries.
I don't know what your non-English words are, so I will use generalized terms in my demo (I've tested this successfully in my own CI project). I am also going to reduce the total subqueries to 3 to reduce the redundance in my snippet.
$value1 = $this->db->select('columnA')->where('cond1', $val1)->get_compiled_select('childTableA');
$value2 = $this->db->select('columnB')->where('cond2', $val2)->get_compiled_select('childTableB');
$value3 = $this->db->select('columnC')->where('cond3', $val3)->get_compiled_select('childTableC');
return (int)$this->$db->query(
"INSERT INTO parentTable
(column1, column2, column1)
VALUES (
($value1),
($value2),
($value3)
)"
);
// to mirror your affected rows return... 1 will be returned on successful insert, or 0 on failure
Granted this isn't using the ActiveRecord technique to form the complete INSERT query, but this is because CI doesn't allow subqueries in the VALUES portion (say, if you were to use the set() method). I am guessing this is because different databases use differing syntax to form these kinds of INSERTs -- I don't know.
The bottom line is, so long as you are fetching a single column value from a single row on each of these sub-SELECTs, this single query will run faster and with far less code bloat than running N number of individual queries. Because all of the variables involved are injected into the sql string using get_compiled_select() the stability/security integrity should be the same.

A Database Error Occurred Duplicate entry '119867-en_GB' for key 'PRIMARY'

I am using codeigniter to insert data from my page to a database , and i get this error
<h1>A Database Error Occurred</h1>
<p>Error Number: 1062</p><p>Duplicate entry '119867-en_GB' for key 'PRIMARY'</p><p>INSERT INTO `ProjectTableName` (`id`, `lang`, `name`) VALUES (119867, 'en_GB', 'test data')</p><p>Filename: models/modelFileLocation.php</p><p>Line Number: 48</p> </div>
Here is my code in the model for insertion of data to the database
$this->db->insert('ProjectTableName', array('id' => $table_id,
'lang' => $lang,
'name' => $name));
How can i be able to solve this error , am using codeignter 3
you not need to send id in the insert array. remove it from the array and make it auto increment in the database. Just use the below code
$this->db->insert('ProjectTableName', array(
'lang' => $lang,
'name' => $name));
If you want to make sure that data is returned, you can also use these codes,
$data = [
'lang' => $lang,
'name' => $name,
];
$this->db->set($data)->insert('ProjectTableName');
if($this->db->affected_rows() > 0) {
return true;
} else {
return false;
}
The number of columns interacting in this way will return, and if true is greater than 0, it will return true.
I'm sure your problem is definitely caused by what I wrote below.
The 'lang' field in the table is selected as 'primary key' and the primary key fields accept only one of the data.
The right example
lang
----
a
b
c
d
If your table situation is this and wrong
lang
----
a -> 1
a -> 2
c
d
cannot contain two 'a' data in the primary key field, specify an id instead and set it as primary key. there is a repetitive entry in the primary key field as the error says.
Good work ..

Mass assignment issue

I have a form with a lot of fields and each of them has to be added in a table as a different row.
My table looks like this:
| Category | Device | Value |
|----------|:-------|-------------|
| 2 | 1 | some value |
| 3 | 1 | other value |
| 7 | 3 | etc |
The Category and Device are actually foreign keys from the Categories and Devices tables. Also they should be unique, meaning that there can't be Category: 2 and Device: 1 twice. If they exists already, the value should be updated.
The categories and value are retrieved from the form and it looks like this:
{"2":"some value","3":"other value","5":"etc","6":"something","8":"can be empty"}
The device also comes from the form but it will be the same.
Now I need to enter everything in my database and I'm looking for a simple solution.
But it will do about 100 queries (one for each input) and I'm sure there must be a better solution.
If one of the values that comes from the form is empty, it should be ignored.
Here's my currently working code, maybe you can understand better:
public function postSpecs(Request $request)
{
$specs = $request->except(['_token', 'deviceid']);
foreach($specs as $key=>$val)
{
if($val == '') continue;
if(Spec::where('category', $key)->where('device', $request->deviceid)->exists())
{
$spec = Spec::where('category', $key)->where('device', $request->deviceid)->first();
$spec->value = $val;
$spec->save();
}
else
{
$spec = new Spec;
$spec->category = $key;
$spec->device = $request->deviceid;
$spec->value = $val;
$spec->save();
}
}
}
use the insert method like:
$model->insert([
['email' => 'taylor#example.com', 'votes' => 0],
['email' => 'dayle#example.com', 'votes' => 0]
]);
See also: http://laravel.com/docs/5.1/queries#inserts
EDIT:
Updated to your code:
public function postSpecs(Request $request)
{
$specs = $request->except(['_token', 'deviceid']);
$data = array();
foreach($specs as $key=>$val)
{
if($val == '') continue;
if(Spec::where('category', $key)->where('device', $request->deviceid)->exists())
{
$spec = Spec::where('category', $key)->where('device', $request->deviceid)->first();
$spec->value = $val;
$spec->save();
}
else
{
$data[]['category'] = $key;
$data[]['device'] = $request->deviceid;
$data[]['value'] = $val;
}
}
Spec::insert($data);
}
While this is not perfect, it will save you a lot queries. Else you have to use raw query something like (untested!):
INSERT INTO spec (id,category,device,value) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE id=LAST_INSERTED_ID(id)
A little more information on the on duplicate key update method because I think it deserves to be a possible solution if this is something that's going to happen a lot...
First, you would need to create the unique key. This will force those columns to be unique. I'd highly suggest adding the unique key no matter how you handle the inserts. It may help preserve your sanity in the future.
In a migration, you would do...
$table->unique(['Category', 'Device']);
Or in plain sql...
alter table category_device add unique index unique_category_device (Category, Device);
Now to insert into the table, you would simply use the query...
insert into category_device (Category, Device, Value) values ($category_id, $device_id, $value)
on duplicate key udpate Value = VALUES(Value)
If it's not a duplicate entry, mysql will simply insert the new record. If it is a duplicate, mysql will update the value column with whatever you tried to insert as the new value. This is very performance friendly as you will not be required to check for the existence of duplicates before trying to do the insert as it will simpy act like an update statement in the event there is a duplicate. The drawback here is laravel does not support on duplicate key update so you would need to actually write the SQL. I would suggest you still use data bindings though which can make it somewhat easier.
$sql = "insert into category_device (`Category`, `Device`, `Value`) values (:category_id, :device_id, :value)
on duplicate key udpate Value = VALUES(Value)";
$success = \DB::insert($sql, [
'category_id' => $category_id,
'device_id' => $device_id,
'value' => $value
]);
Also please note, if you have over 100 entries, you could loop through them and keep adding to the query and it should work just the same...
insert into category_device (`Category`, `Device`, `Value`)
values
(1, 1, 'some value'), (1, 2, 'some other value'), (1, 3, 'third value')...
on duplicate key udpate Value = VALUES(Value)";
If you are using this method, I would probably not worry about the data binding and just insert the values right into the query. Just make sure they are properly escaped beforehand.
If you had a hundred items to insert, which would be 200 queries (one for checking the existence of the record, and another for inserting/updating), this would turn that 200 queries into 1 query which obviously would be a huge performance gain.

How do I insert my imploded array into my database?

I'm trying to update permissions of userroles in my application.
Everything works the way I want untill I want to insert the changes into my database.
$permission = $_POST['permission'];
$permissiondb = implode(",", $permission);
print_r($permission)
print_r($permissiondb);
The permission print shows this:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 6 [4] => 5 [5] => 4 )
The permissiondb print shows this:
1,2,3,6,5,4
my db query is:
INSERT INTO give_permissions (userrole, permission_id) VALUES ($userrole, $permissions);
When I send the values to my database it inserts a ' 0 ' at the wanted userrole, but instead
I want the system to put in all permissions for the userrole.
I hope I gave enough code for you to help me... can someone help me with this?
You have a list of ids which are being stored in permission_id which suggests that its setup to take a single integer? Thus a list of ids will not work.
a) Change your data type to varchar and wrap $permissions with '$permissions'.
By using this method you would stick with implode(",", $permissions) but there is a better way.
// Your example with modifications
$permission = $_POST['permission'];
$permissiondb = implode(",", $permission);
// INSERT INTO give_permissions (userrole, permission_id)
// VALUES ($userrole, '$permissiondb');
b) Change your data type to varchar and use 'json_encode($permissions)' - This would be the preferable option by many as a shortcut.
When you use json_encode() you store it in a more manageable way. When you encode it you will receive a string in the format of [{1},{2},...] which you can drop into your table quite nicely.
So what about later on when you want to retrieve that permissions list? You use json_decode($permissions) which will then give you a JSON array. For your purposes its easier to cast that json array to a standard array (array)json_decode($permissions) which will take that [{}] string and give you a perfectly standard array(1,2,3,...).
// Your example with modifications
$permission = $_POST['permission'];
$permissiondb = json_encode($permission);
// INSERT INTO give_permissions (userrole, permission_id)
// VALUES ($userrole, '$permissiondb');
c) Setup a corresponding table to take each id and link them. - This would be the perfect ideal.
Change permission data type int to varchar and try this
INSERT INTO give_permissions (userrole, permission_id) VALUES ($userrole, $permissions);

PHP ldap_mod_replace fails with «Type or value exists» error

I have created a light Model Manager for LDAP over PHP's API to ease object managements from Active Directory.
Everything runs fine but I have a problem when updating multi valued attributes even if I change all the values, the transaction fails with «Type or value exists» error and the attribute is not changed in the database.
The test case I am using is to change de multi valued "description" field for a user. If I add new values or change the whole array of values, the transaction always fail.
The part of the code is the following:
if (count($mod_attr) > 0)
{
$ret = #ldap_mod_replace($this->getHandler(), $dn, $mod_attr);
if ($ret === false)
{ $this->log(sprintf("LDAP ERROR '%s' -- Modifying {%s}.", ldap_error($this->getHandler()), print_r($mod_attr, true)), \SlapOM\LoggerInterface::LOGLEVEL_CRITICAL);
throw new LdapException(sprintf("Error while MODIFYING values <pre>%s</pre> in dn='%s'.", print_r($mod_attr, true), $dn), $this->getHandler(), $this->error);
}
$this->log(sprintf("Changing attribute {%s}.", join(', ', array_keys($mod_attr))));
}
The complete code can be found [here on github](https://github.com/chanmix51/SlapOM/blob/master/lib/SlapOM/Connection.php#L115 [github]).
The logs show the following lines:
2013-06-04 10:39:54 | => MODIFY dn='CN=HUBERT Gregoire,OU=...
2013-06-04 10:39:54 | => LDAP ERROR 'Type or value exists' -- Modifying {Array
(
[description] => Array
(
[0] => Description 2
[1] => Description 3
)
)}
Even if the preceding values were ["description" => ['Description 1']]. Is there something I am not getting or doing wrong ?
The answer is short: «Description is not a multi valued field». As usual, the error message was so confusing, it lead me to spend hours on the wrong problem.
In short: the LDAP error 20 «Type or value exists» can be either you are trying to insert twice the same values in a multi valued field or you are trying to insert several values in a single valued field.

Categories