0

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?

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

2 Answers 2

2

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

1

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');
        }
    }
}
3
  • This results in INSERT IGNOREINTO for me (using MariaDB 10.1). Also, INSERT IGNORE is not supported on PostgreSQL, I think.
    – Sharky
    Dec 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
  • 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, 2018 at 13:52

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