从逗号分隔的列表中删除电子邮件地址的PHP脚本


PHP script to remove e-mail addresses from a comma-separated list

我经营一个小网站,我的用户要求我建立一个邮件列表。我发现了一个简单的免费脚本,可以将电子邮件地址以CSV格式添加到受保护的文本文件email.txt中:

email1@yahoo.com,email2@yahoo.com,blah,blah,blah

脚本工作完美。但是,当用户取消其列表订阅时,通过文件手动删除电子邮件地址很麻烦。我需要创建一个简单的脚本来删除电子邮件地址。

所有我想要的是一个简单的PHP脚本,显示一个文本框,让用户可以输入他们的电子邮件地址,并单击"取消时事通讯"按钮。脚本应该搜索文本文件,找到给定的电子邮件地址,并删除它和后面的逗号。

例如,假设email.txt的内容为

john@yahoo.com,peter@yahoo.com,steve@yahoo.com

如果我在脚本显示的文本框中输入"peter@yahoo.com",我希望文件看起来像这样:

john@yahoo.com,steve@yahoo.com

UPDATE: I tried this code:

<?php
        function showForm() {
            echo '
            <form method="post" action="">
            Email Address: <input type="text" name="email"> <br />
            <input type="submit" value="Cancel Newsletter" name="submit">
            </form>
            ';
        }
        $_POST['email']
        $to_delete = 'email';
        $file = array_flip(explode(",",file_get_contents("email.txt")));
        unset($file[$to_delete]);
        file_put_contents("email.txt",implode(",",array_flip($file));
        if(!$file_put_contents) {
            die('Error occured');
        } else {
            echo 'Your subscription has been cancelled. You will not receive any further emails from us.';
        }
    }
} else {
    showForm();
}
?>

这段代码甚至没有显示表单。

更新2 :

再次尝试写这个脚本:

<?php
    $email = $_POST["email"];
    $text = file_get_contents("email.txt");
    $oldWord = "$email";
    $newWord = "";
    $text = str_replace($oldWord , $newWord , $text);
    $fp = fopen('email.txt', 'w');
    fwrite($fp, $text);
    fclose($file);
?>

只要删除电子邮件地址就可以,但是没有通知(echo)。根据脚本是否成功地在列表中找到$email并删除它,我希望它说"该电子邮件未订阅"或"您已被删除"。

UPDATE 3 Dec. 31 2011:

我尝试了高级代码,只是得到一个空白页,所以我回到了我的版本。下面是我现在的代码:

<html>
    <body>
        <form method="post" action="">
            <p>Email Address: <input type="text" name="email"></p>
            <input type="submit" value="Cancel Newsletter" name="submit">
        </form>
        <?php
            $email = $_POST["email"];
            $basetext = file_get_contents("email.txt");
            $oldWord = "$email";
            $newWord = "";
            $text = str_replace($oldWord , $newWord , $basetext);
            $str1 = $basetext;
            // echo strlen($str1);
            $str2 = $text;
            // echo strlen($str2);
            $fp = fopen('email.txt', 'w');
            fwrite($fp, $text);
            if ($str1 > $str2) { // This part handles the success/fail message
                echo ("Success!");
            } else {
                echo ("Fail!");
            }
            fclose($file);
        ?>
    </body>
</html>

这工作完美。但是,它在页面加载时显示"失败"消息,而不是在按下提交按钮后触发加载时显示。

如果可能的话,我希望保留原始代码,只是重新排列,以便它只显示"成功!"或"失败!"一旦执行了代码。

我希望echo消息是在页面上执行的最后一个脚本。

你为什么不使用数据库?

CREATE TABLE `emails` (`address` VARCHAR(255) NOT NULL, PRIMARY KEY (`address`)) ENGINE=InnoDB
INSERT INTO `emails` VALUES ('user1@example.com')
SELECT * FROM `emails`
DELETE FROM `emails` WHERE `address`='user1@example.com'

这些比文本文件更简单,更有效…

但是如果你想使用文本文件…

$to_delete = 'user1@example.com';
$file = array_flip(explode(",",file_get_contents("email.txt")));
unset($file[$to_delete]);
file_put_contents("email.txt",implode(",",array_flip($file));

基本上它所做的是,它通过逗号爆炸,然后翻转数组,使电子邮件是键(它们的数字位置是值,但这并不重要),然后它删除你想要删除的电子邮件,最后重新组装文件。这样做的好处是,它还将删除您可能拥有的任何重复项。

您可以使用类似的方法来添加电子邮件地址,只需将unset行更改为$file['user1@example.com'] = -1;(以确保数字不与任何内容冲突,因为这会干扰数组翻转)。

此答案最初由op附加到问题正文中。

首先,我将表单移动到/cancel.html,并使用<form action="/cancel_submit.html">

(这里我写了.html,这只是为了演示,因为我的服务器配置为不使用页面扩展,也使PHP在.html页面上解析。)

然后我将PHP代码放入/cancel_submit.html页面并移动
if ($str1 > $str2) {
    echo ("You Have Successfully Unsubscribed From Our Newsletter....<br>You Will Not Receive Any More Emails From Us.");
} else {
    echo ("The Email Address You Specified Is Not In Our Mailing List.");
}

转换为另一组PHP括号。

这意味着通过POST将电子邮件地址发送到另一个页面,然后该页面执行从列表中实际删除电子邮件地址的操作,然后检查是否删除了一个地址以提供确认消息。

我还向$oldword = "$email";添加了两个逗号,使其成为$oldword = ",$email,";,以便它只查找输入到电子邮件框中的文本,如果它的两边都有逗号。这解决了某人提交一半电子邮件地址的情况。

我还将$newWord = "";更改为$newWord = ",";,以便如果脚本删除了两侧带有逗号的电子邮件地址,则相邻的两个电子邮件地址将不会被逗号分隔。

下面是两个页面的代码:

  1. cancel.html

    <p>To cancel our Newsletter please enter your email address below....</p>
    <p>
    <form method="post" action="/cancel_submit.html">
    <p>Email Address: <input type="text" name="email"></p>
    <input type="submit" value="Cancel Newsletter" name="submit">
    </form>
    
  2. cancel_submit.html

    <?php
        $email = $_POST["email"];
        $basetext = file_get_contents("email.txt");
        $oldWord = ",$email,";
        $newWord = ",";
        $text = str_replace($oldWord , $newWord , $basetext);
        $str1 = $basetext;
        // echo strlen($str1);
        $str2 = $text;
        // echo strlen($str2);
        $fp = fopen('email.txt', 'w');
        fwrite($fp, $text);
        fclose($file);
    ?>
    <?php
        if ($str1 > $str2) {
            echo ("You Have Successfully Unsubscribed From Our Newsletter....<br>You Will Not Receive Any More Emails From Us.");
        } else {
            echo ("The Email Address You Specified Is Not In Our Mailing List.");
        }
    ?>
    <p>
        <p>Please wait to be re-directed or <a href="http://the-flying-shuttle.com/"><u>CLICK HERE.</u></a>
        </p>
    

编辑:

我做了一些改进。我加了:

$email = strtolower($email);

添加到电子邮件添加脚本和电子邮件删除脚本。这将把输入任意一种形式的所有字符转换为小写;以前,它不会删除与大列表不同类型的电子邮件。

这会使确认消息命令混乱,所以我将其更改为

if (str_replace($oldWord , $newWord , $basetext)) {
    echo ("You Have Successfully Unsubscribed From Our Newsletter....<br>You Will Not Receive Any More Emails From Us.");
} else {
    echo ("The Email Address You Specified Is Not In Our Mailing List.");
}

建议研究:

http://us.php.net/manual/en/function.explode.php
http://us3.php.net/manual/en/function.file-put-contents.php
编辑补充:http://us3.php.net/manual/en/function.file-get-contents.php

如果你最终使用第三方服务,不要付钱给Aweber。选择MailChimp。如果你的邮件列表不是那么大,他们有免费的计划。

在您的示例中,您引用了一个变量$_POST['email'],而没有赋值或测试该值。此外,您可能希望对该变量进行消毒。

我看到的另一个问题是$to_delete = 'email';,你只寻找'email'的条目。

您的$file_put_contents没有被分配。

} else { showForm(); }没有与if语句配对。

<?php
function showForm() {
    echo '<form method="post" action="">' . PHP_EOL
       . 'Email Address: <input type="text" name="email"> <br />' . PHP_EOL
       . '<input type="submit" value="Cancel Newsletter" name="submit">' . PHP_EOL
       . '</form>';
}
if($_POST['email']) {
    $to_delete = $_POST['email'];
    $file = array_flip(explode(",",file_get_contents("email.txt")));
    unset($file[$to_delete]);
    $file_put_contents = file_put_contents("email.txt",implode(",",array_flip($file));
    if(!$file_put_contents) {
        die('Error occured');
    } else {
        echo 'Your subscription has been cancelled. You will not receive any further emails from us.';
    }
} else {
    showForm();
}

如果我正确理解你的问题,这就是你想要实现的。

  • 检查用户是否已经从表单发帖。
    • 获取电子邮件。(你应该确保在这一步中它是一个相同的值)
    • 检索成员数据
    • 检查用户是否在列表中。
      • 删除用户并保存数据(如果适用)
    • 输出函数的结果
  • 显示一条消息,其中包含要提交给self的表单。

我知道这可以作为一个非常简单的任务来完成,但我不相信这种方法。此外,我认为任何与数据永久存储交互的东西都应该有一些温和到适度的抽象形式。

我会这样做。

class MailingList {
    const EMAIL_OK = 1;
    const ERR_EMAIL_EXISTS = -1;
    const ERR_EMAIL_INVALID = -2;
    const ERR_EMAIL_NOTFOUND = -3;
    protected $_db_src;
    protected $_db_opt;
    protected $members = array(); // An array intended to hold members.
    public function email_exists($email) {
        return array_key_exists($this->members, $email);
    }
    public function remove_email($email) {
        $this->_sanitize_email($email);
        if ($email) {
            if (array_key_exists($this->members, $email)) {
                unset($this->members[$email]);
                $this->_update_members();
                return self::EMAIL_OK;
            } else {
                return self::ERR_EMAIL_NOTFOUND;
            }
        } else {
            return self::ERR_EMAIL_INVALID;
        }
    }
    public function add_email($email) {
        $this->_sanitize_email($email);
        if ($email) {
            if (array_key_exists($this->members) {
                return self::ERR_EMAIL_EXISTS;
            } else {
                $this->members[$email] = -1;
                $this->_save_members();
                $this->_load_members();
                return self::EMAIL_OK;
            }
        } else {
            return self::ERR_EMAIL_INVALID;
        }
    }
    // We expect a data source and options for the
    //     data source upon instantiation.
    // This is to prepare this class for abstraction and allow it to be
    //     extended to databases.
    public function __construct($data_source = "flatfile", $data_options = "email.txt") {
        $this->_db_src = $data_source;
        $this->_db_opt = $data_options;
        $this->_load_members();
    }
    protected function _load_members() {
        // Create the function name to ensure it exists.
        $data_function = "handle_" . $this->_db_src;
        if (!method_exists(&$this, $this->_db_src)) {
            throw new Exception('Invalid data source');
        }
        // Build our array of parameters to be sent to our handler function.
        $parameters = array_merge(array('load'), (array) $this->_db_opt);
        // This calls our data function with a load action parameter.
        // This is written to expect the data function to populate $this->members.
        return call_user_func_array(array(&$this, $data_function), $parameters);
    }
    // Most of this is similar to the constructor as far as data handling goes.
    protected function _save_members() {
        // Create the function name to ensure it exists.
        $data_function = "handle_" . $this->_db_src;
        if (!method_exists(&$this, $this->_db_src)) {
            throw new Exception('Invalid data source');
        }
        // Set up our data options with a save action.
        $parameters = array_merge(array('save'), (array) $this->_db_opt);
        return call_user_func_array(array(&$this, $data_function), $parameters);
    }
    // The heart of the storage engine, designed for CSV data.
    protected function handle_flatfile($action, $filename) {
        switch ($action) {
            case "load":
                // Make sure we can load members.
                if (!is_readable($filename)) {
                    throw new Exception("File: $filename, is not readable");
                }
                // Open our data file and load the information.
                // Populate $this->members as an array just the way we expect it.
                $this->members = array_flip(explode(',', file_get_contents($filename)));
                break;
            case "save":
                // Make sure we can write to the file before we move forward.
                if (!is_writeable($filename)) {
                    throw new Exception("File $filename, is now writable");
                }
                // Convert our array back to a CSV string and write it to the file.
                $status = file_put_contents($filename, implode(',', array_flip($this->members)));
                // If we failed to write to the file make sure something is done before we continue.
                if (!$status) {
                    throw new Exception("Writing to file failed!");
                }
                break;
            default:
                throw new Exception("Unknown action called on data handler.");
        }
    }
    // converts email addresses to lowercase to avoid duplication.
    // should add a regex filter here to ensure that we have a valid address
    protected function _sanitize_email(&$email) {
        $email = strtolower($email);
    }
}
function show_form() {
    echo '<form method="post" action="">' . PHP_EOL
       . 'Email Address: <input type="text" name="email"> <br />' . PHP_EOL
       . '<input type="submit" value="Cancel Newsletter" name="submit">' . PHP_EOL
       . '</form>';
}
if (isset($_POST) && isset($_POST['email'])) {
    $list = new MailingList();
    $status = $list->remove_email($_POST['email']);
    switch ($status) {
        case MalingList::EMAIL_OK:
            echo "<p class='success'>Your email was successfully removed.<p>";
            break;
        case MailingList::ERR_EMAIL_INVALID:
            echo "<p class='error'>The email address provided was invalid.</p>";
        case MailingList::ERR_EMAIL_NOTFOUND:
            echo "<p class='error'>The email address provided was not registered.</p>";
        default:
            show_form();
    }
} else {
    show_form();
}