Option #1 - the clean way (my recommended approach)
Call this query from phpMyAdmin to permanently establish the two columns as UNIQUE KEYS
. (You will need to replace the #_
prefix with your private prefix string.)
ALTER TABLE `#__parts_analogues` ADD UNIQUE KEY(original_id, analogue_id)
Then whenever you wish to throw new rows into the table, you can use a INSERT IGNORE INTO
query to avoid receiving those syntax errors. This adjustment is applied inside the setQuery()
call.
Here is how I would write the OO code:
$db = JFactory::getDBO();
try {
$insert_query = $db->getQuery(true)
->insert("#__parts_analogues")
->columns("original_id, analogue_id")
->values($value); // I'm not sure if you are delivering a string, 1-dim array, or multi-dim array
$db->setQuery(preg_replace('~INSERT \K~', 'IGNORE ', $insert_query, 1)); // add IGNORE after first occurring `INSERT ` in query
$db->execute();
echo $db->getAffectedRows() , " row(s) inserted into parts_analogues table";
} catch (Exception $e) {
echo "Syntax Error"; // . " & Error: " . $e->getMessage();
}
I'm not sure if $value
is a comma-separated string, a one-dimensional array containing two elements, or a multi-dimensional array containing sets of 2-element subarrays. If these id
values are integers and coming from an external source, you should cast each id
as (int)
before feeding to the query for security reasons. Here's some relevant literature:
I should also point out that there is technically a possibility of making unintended multiple replacements within the query while using str_replace()
. For this reason, I am using preg_replace()
with a replacement limit of 1 for peace of mind.
Another note: Joomla puts \r\n
(or just \n
depending on your operating system) at the start of the query; var_dump($db)
after setQuery()
to see. For this reason, my pattern does not use ~^INSERT ~
, but I could just as easily use ~^\sINSERT~
or ~^\RINSERT ~
to anchor the pattern to the start of the string.
Option #2 - which IMO is the less elegant way because it requires two round trips to the database.
Basically, you would run a SELECT COUNT(*) query with a WHERE
clause that searches for matches using your $values
data to determine if the pair of values exists in the table, then you call an INSERT
query when it is unique. *note, you can use two where()
method calls, but I don't prefer that style because it is too much of a departure from raw sql syntax. You could also hardcode the AND
and write a single string, but I was trying to get the whole code block to fit the available width on this page.
$db = JFactory::getDBO();
try {
$select_query = $db->getQuery(true)
->select("COUNT(*)")
->from("#__parts_analogues")
->where(
array(
"original_id = " . (int)$original_id),
"analogue_id = " . (int)$analogue_id)
)
)
->setLimit(1);
$db->setQuery($select_query);
if (!$db->loadResult()) {
// if count is 0 (false-y) that means the values are unique
$insert_query = $db->getQuery(true)
->insert("#__parts_analogues")
->columns("original_id, analogue_id")
->values((int)$original_id . "," . (int)$analogue_id);
$db->setQuery($insert_query);
$db->execute();
echo "Row Added";
} else {
echo "Non-unique Values";
}
} catch (Exception $e) {
echo "Syntax Error"; // . " & Error: " . $e->getMessage();
}