I'm trying to save email addresses to database when a customer send an email via contact form. I put the insert query into the _sendEmail
function, but when I send an email, it didn't insert the address. How can I solve this?
-
1Can you please share the code for your full query so we can look through it?– LodderDec 3, 2018 at 10:56
-
Also, please clarify how exactly it is not working. Is there an error generated? If so, we'd like to know the error message.– mickmackusaDec 3, 2018 at 11:11
2 Answers
You shouldn't modify core files. Create a contact plugin with onSubmitContact
event. Basic example to catch unique emails:
defined('_JEXEC') or die;
use Joomla\CMS\Plugin\CMSPlugin;
class PlgContactEmails extends CMSPlugin
{
public function onSubmitContact(&$contact, &$data)
{
if (empty($data['contact_email']))
{
return;
}
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName('#__plg_contact_emails'))
->where($db->quoteName('email') . ' = ' . $db->quote($data['contact_email']));
if ($db->setQuery($query)->loadResult())
{
return;
}
$query = $db->getQuery(true)
->insert($db->quoteName('#__plg_contact_emails'))
->columns($db->quoteName('email'))
->values($db->quote($data['contact_email']));
$db->setQuery($query)->execute();
}
}
Note, you have to create a SQL installation script for creating custom database table and add it to plugin's manifest file.
https://docs.joomla.org/J3.x:Creating_a_simple_module/Using_the_Database
To expand/refine Sharky's answer, you can set up your new/basic database table with this structure:
CREATE TABLE IF NOT EXISTS `#__plg_contact_emails` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
By setting email
as a UNIQUE key, you can streamline the plugin's querying process and ensure that your table only contains unique email addresses.
<?php
defined('_JEXEC') or die;
use Joomla\CMS\Plugin\CMSPlugin;
class PlgContactEmails extends CMSPlugin
{
public function onSubmitContact(&$contact, &$data)
{
if (!empty($data['contact_email']) && filter_var($data['contact_email'], FILTER_VALIDATE_EMAIL)) // in case validation is necessary
{
$db = JFactory::getDBO();
$query = $db->getQuery(true)
->insert("#__plg_contact_emails")
->columns("email")
->values($db->q($data['contact_email']));
$db->setQuery(preg_replace('~INSERT \K~', 'IGNORE ', $query, 1)); // add IGNORE to avoid duplicate entry error
$db->execute();
}
}
}
Here is a related post where I explain the effect and benefits of my single query snippet: https://joomla.stackexchange.com/a/22966/12352
If you can't or don't want to hack at the built query with IGNORE
, you can convert mysql errors to exceptions and either ignore them or handle them specifically:
if (!empty($data['contact_email']) && filter_var($data['contact_email'], FILTER_VALIDATE_EMAIL)) // in case validation is necessary
{
$db = JFactory::getDBO();
$query = $db->getQuery(true)
->insert("#__plg_contact_emails")
->values("null, " . $db->q($data['contact_email'])); // without columns() call
$db->setQuery($query);
try
{
$db->execute();
}
catch (Exception $e)
{
// do nothing or whatever you like
if ($e->getCode() == 1062)
{
// JFactory::getApplication()->enqueueMessage("Duplicate Entry", 'notice');
}
else
{
// JFactory::getApplication()->enqueueMessage("Syntax Error", 'error');
}
}
}
-
This results in
INSERT IGNOREINTO
for me (using MariaDB 10.1). Also,INSERT IGNORE
is not supported on PostgreSQL, I think.– SharkyDec 5, 2018 at 13:11 -
Must not be
\r\n
at the front of the query. Probably only\n
. I've never used PostgreSQL or MariaDB.preg_replace('~INSERT \K~', 'IGNORE ', $query, 1)
should work everywhere. Dec 5, 2018 at 13:16 -
1Doesn't work yet. The inconsistency is between different operating systems. Original code works on Windows but not on Linux. So line endings could indeed be the issue. Could use
strpos()
in this case:substr_replace($query, ' IGNORE', strpos($query, 'INSERT') + 6, 0)
.– SharkyDec 5, 2018 at 13:52