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?

closed as unclear what you're asking by mickmackusa, Neil Robertson, Lodder Dec 10 at 9:39

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    Can you please share the code for your full query so we can look through it? – Lodder Dec 3 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. – mickmackusa Dec 3 at 11:11

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. – Sharky Dec 5 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. – mickmackusa Dec 5 at 13:16
  • 1
    Doesn'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). – Sharky Dec 5 at 13:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.