Codeigniter: Active Records Insert Unique values - php

I am importing GMail contacts from Google API and just want to persist unique email ids into database.
Is it possible to insert unique records using codeigniter's Active Record?
Does CodeIgniter provide it out of the box?
If I make the column unique the query throws exception. After digging into documentation I understood that CodeIgniter doesn't provide try catch blocks.

your email field have to be unique in your table indexes.
$query_string = $this->db->insert_string('table', $data);
$query_string = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $query_string);
$req = $this->db->query($query_string);
if($req->affected_rows() == 1) {
//data inserted
} else {
//email exists already
}
If you use the IGNORE keyword, errors that occur while executing the
INSERT statement are treated as warnings instead. For example, without
IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY
value in the table causes a duplicate-key error and the statement is
aborted. With IGNORE, the row still is not inserted, but no error is
issued. Data conversions that would trigger errors abort the statement
if IGNORE is not specified. With IGNORE, invalid values are adjusted
to the closest values and inserted; warnings are produced but the
statement does not abort.
MySQL INSERT syntax
CI Database Helper

You can create a base model (application/core/MY_Model.php) and implement a save function to insert if new and update if exists. Extend your model from it.
This is an extract from http://thephpcode.com/blog/codeigniter/a-smart-codeigniter-model
public function save($data,$tablename="")
{
if($tablename=="")
{
$tablename = $this->table;
}
$op = 'update';
$keyExists = FALSE;
$fields = $this->db->field_data($tablename);
foreach ($fields as $field)
{
if($field->primary_key==1)
{
$keyExists = TRUE;
if(isset($data[$field->name]))
{
$this->db->where($field->name, $data[$field->name]);
}
else
{
$op = 'insert';
}
}
}
if($keyExists && $op=='update')
{
$this->db->set($data);
$this->db->update($tablename);
if($this->db->affected_rows()==1)
{
return $this->db->affected_rows();
}
}
$this->db->insert($tablename,$data);
return $this->db->affected_rows();
}

If your data comes from a from, CI provides a form_validation class that can validate your form on the server side.By form_validation has a rule called is_unique its checks if the given value is already exist on the database or not. you can see a complete and clear explanation here
Or, you can check it manually before inserting your email in that unqiue column.
$this->db->select('email');
$this->db->where(array('email'=>$email));
$query = $this->db->get('yourtable');
if($query->num_rows() > 0){
// the query returned data, so the email already exist.
}else{
// the email not exists, so you can insert it.
}

Related

If else in sql insert

I want to make a code where if the data already exists in the database and the user insert the same input again and send to the database, the sql command will detect it and will not allow the duplicate data enter the database. Addtional information, I don`t have primary key for my table. Here is my code.
$sql="INSERT IGNORE INTO tempahan(Nama,Aktiviti,No_HP,Unit,Tempat,Tarikh_Penggunaan,Masa_Mula,Masa_Akhir,Email) VALUES('$_POST[name]','$_POST[Aktiviti]','$_POST[number]','$_POST[unit]','$_POST[tempat]','$_POST[tarikh]','$_POST[masa1]','$_POST[masa2]','$_POST[email]')";
$_POST['tempat'] = $data['Tempat'] ;
$_POST['masa1'] = $data['Masa_Mula'];
$_POST['masa2'] = $data['Masa_Akhir']; if($_POST['tempat'] != $data['Tempat'] && $_POST['masa1'] != $data['Masa_Mula'] && $_POST['masa2'] != $data['Masa_Akhir']) {
echo 'the booking was successful.';
}
else
{ echo 'the place already occupied.';}
I'm new to sql and also php. Therefore, I really need help from all of you guys. I already see the other same question. But, every solution provided I've failed.
The correct way to do this is to enforce a unique constraint on your table, across the fields that you consider to be unique. You can do that as such.
alter table tempahan
add unique (Tempat, Masa_Mula, Masa_Akhir)
Your database will then reject out of hand any attempts to insert duplicate data. No need to do a prior check before inserting.
Here is a very basic demo of what happens when you set your table up with this unique constraint, and then try and insert duplicate data. In short: it errors.
$query = $db->query( // query your table );
$array = array('name'=>$_POST['name'],
'address'=>$_POST['address']);
while ($row = mysqli_fetch_all($query)) {
$diff = in_array($array, $row);
{
if(empty($diff))
{
// insert data into table
}
else{
//data already exist
}
}
}
// first check existing recors on the database
$select = "SELECT `Tempat`, `Masa_Mula`, `Masa_Akhir`
FROM `tempahan`
WHERE `Tempat` = {$_POST['tempat']}
AND `Masa_Mula` = {$_POST['masa1']}
AND `Masa_Akhir` = {$_POST['masa2']}";
$result = mysql_query($select, $dbconnection);
// check if the have existing records
// the query fetching depends on your work
// but this is a simple way only
// but have more examples on the internet
// to make query more better and ellegant
if (mysql_num_rows($select) > 0) {
echo 'the place already occupied.';
} else {
// insert new record
$sql="INSERT IGNORE INTO tempahan(Nama,Aktiviti,No_HP,Unit,Tempat,Tarikh_Penggunaan,Masa_Mula,Masa_Akhir,Email)
VALUES(
'$_POST[name]',
'$_POST[Aktiviti]',
'$_POST[number]',
'$_POST[unit]',
'$_POST[tempat]',
'$_POST[tarikh]',
'$_POST[masa1]',
'$_POST[masa2]',
'$_POST[email]')";
echo 'the booking was successful.';
}

MySQL query sent successfully, yet database field stays empty

The following 2 queries are the result of an echo in php:
UPDATE glymping_userdata
SET current_location_gps = '51.9171115;4.484812'
WHERE id = 1
and
UPDATE glymping_user_has_appointments
SET status = 'enroute',
start_location_gps = '51.9171115;4.484812'
WHERE userId = 1
AND appointmentId = 47
Both queries work when entered manually in the database and all fields are filled correctly. When I let the php file run the queries, the queries are like shown above, but the "start_location_gps" and the "current_location_gps" are empty.
The values in the queries are strings and the database fields are a varchar(30). Yet the fields in the database are empty.
The location value is received from a post method.
Does anyone knows what I am forgetting or doing wrong?
EDIT:
php example
public function SendQuery($query)
{
$results = $this->mysqli->query($query);
return $results;
}
public function UpdateUserLocation($currentLocationGps)
{
$query = "UPDATE ".DB_PREFIX."userdata
SET current_location_gps = '{$currentLocationGps}'
WHERE id = ".$this->userId;
//echo $query;
$this->db->SendQuery($query);
}
Your current code doesn't check the return value of mysqli_query; the query might fail "silently". It could also be that the query does not affect any records in the database becaue of wrong values in the WHERE clause.
Try it with
if ( !$this->db->SendQuery($query) ) {
// query failed: syntax error, connection lost, access denied,duplicate entries, ...
trigger_error($this->mysqli->error);
}
else {
if ( 0 < $this->mysqli->affected_rows ) {
// WHERE clause doesn't match any record, no values changed, ...
trigger_error('no rows affected');
}
}
Your query might also be prone to sql injections, please check http://php.net/manual/en/security.database.sql-injection.php

How do I take a php variable that has an sql query inside it and add it to an existing sql query using $db->updatePhoneNumbers()?

I am trying to make a database of Users. One user can have an indefinite number of phone numbers. So in the form I’ve created a js function that will give me new input fields and they put the information into a nestled array.
I am doing a double foreach loop to go through my array, and add SQL queries to it based on if the id already exists and just needs to be updated or if it's entirely new and needs to be inserted. I add these SQL queries to a variable $phoneSql . When I echo that variable, it does contain a valid SQL query which works if I try it directly in phpMyAdmin.
This is the foreach loop code:
$phoneSql = 'SELECT id FROM user WHERE id = '.$id.' INTO #id;';
foreach($_POST['phone'] as $key => $value) {
foreach($_POST['user'][$key] as $id => $number) {
if($id == 0 && !$number == ''){
$phoneSql .= 'INSERT INTO phone_number (id, user_id, number) VALUES (NULL, #id, "'.$number.'");';
} else if (!$number == '') {
$phoneSql .= 'UPDATE phone_numbers SET user_id = #id, number = "'.$number.'" WHERE id = '.$id.';';
}
}
}
I have one edit.php page with the form, which posts to update.php where I have the foreach loop from above and following code:
$db->updatePhoneNumber($phoneSql);
It also gets the $id from the user I’m editing at the moment. Then it gets sent to db.php and into this function:
public function updatePhoneNumbers($phoneSql) {
$ phoneSql = $ phoneSql;
$sth = $this->dbh->prepare($phoneSql);
$sth->execute();
if ($sth->execute()) {
return true;
} else {
return false;
}
}
But this is not working. Can I add a variable with sql queries into a function like that or do I have to do it some other way? I’m quite new to this so I’m not sure how to proceed. I’ve tried searching for a solution but haven’t found any. I’m thankful for any advice.
What you should be doing is using an INSERT ... ON DUPLICATE KEY UPDATE ... construct, saving you a lot of that logic.
e.g.
INSERT INTO phone_number (id, user_id, number) VALUES (...)
ON DUPLICATE KEY UPDATE user_id=VALUES(user_id), number=VALUES(number)
With this, no need to select, test, then insert/update. You just insert, and MySQL will transparently convert it into an update if a duplicate key error occurs.

Codeigniter handle database error without num_rows()

I'm having trouble finding a simple method for handling database errors in CI. For instance, I can't insert duplicate entries in my database table. If I try to, I get a 1062 database error.
The most common solution suggested is to check if the entry already exists and use
$query->num_rows() > 0
in a if-statement to prevent an error. That method seems redundant to me because I'm performing an extra query. Ideally I want to check if an error occurs in my main query or if a row is affected.
I found the following functions that may help
$this->db->affected_rows()
$this->db->_error_message()
however I'm not sure how to use them.
I tried in my Model:
$this->db->insert('subscription', $data);
return $this->db->affected_rows();
To my understanding that should return the number of effected rows. Then in my controller I added:
$affected = $this->Subscribe_model->subscribe($data);
if ($affected < 1)
{
//display error message in view
}
else
{
$this->Subscribe_model->subscribe($data); //perform query
}
Unfortunately the script stops in the model at $this->db->insert('subscription', $data); if an error occurs and displays the entire database error.
I do not know if this works for $this->db->insert();, but $this->db->query(); will return false if it errors so you could do something like this:
$sql = $this->db->insert_string('subscription', $data);
$sql = $this->db->query($sql)
if(!$sql){
//Do your error handling here
} else {
//query ran successfully
}
Try using #$this->db->insert('subscription', $data);, #, in PHP means "suppress warning".
As an alternate -- if you know that data is safe, or you're willing to use $this->db->insert_string, you could add, on duplicate key to the end of the query.
This should work (untested):
$this->db->simple_query( $this->db->insert_string( 'subscription', $data ) .
' ON DUPLICATE KEY ' .
$this->db->update_string(
'subscription',
$data,
/* your where clause here */ );

Simple PHP SQLite question

I am trying to implement a function that will insert a new entry in a database if a field with same name (as the one given) doesn't already exist. In particular I want to restrict duplicate usernames in a table.
The only way I could think was to run a select query and then if that doesn't return anything run the insert query. For some reason though I cant get it to work...
My db select Function
function getAllUsers($user)
{
$stmt = $this->db->stmt_init();
$stmt->prepare('SELECT username from users where username=? ');
$stmt->bind_param("s", $user);
$stmt->bind_result($username);
$stmt->execute();
$results = array();
while($stmt->fetch())
{
$results[] = array('username' => $username);
}
$stmt->close();
return $results;
}
My php code (this is in a different page)
foreach ($GLOBALS['db']->getAllUsers($_POST['username']) as $i)
{
$results = "".$i['username']."";
break;
}
if(strcmp($results, "")==0)
{
if($GLOBALS['db']->addUser($_POST['username'],$_POST['password']))
{
session_destroy();
echo "registerSucces";
}
else
{
session_destroy();
echo "registerError";
}
}
else
{
echo "userNameExists";
}
Can you see whats wrong with this???
Thanks
Mike
Still cant find how to make the above code work but just in case someone needs this: A temporary simple solution is not to compare strings at all and instead have a counter in the foreach loop and then check that upon a desired number(0 in my case)...
SQLite supports the UNIQUE constraint. Simply declare a UNIQUE index on the column and check whether an INSERT fails.
If you're using the username as the primary key in your tables, you can use the INSERT OR IGNORE command instead of checking to see if the username already exists.
If SQLite finds that an INSERT OR IGNORE command will conflict with an existing row in your table, it will simply ignore the command.
You can find out more stuff in the SQLite documentation for the INSERT command

Categories