2012-08-27 39 views
1

我正在開發一個應用程序,它將查找電子郵件收件箱並將特定電子郵件保存爲其功能的一部分。發生的是一個imap連接,然後檢索所有設置爲UNSEEN的電子郵件。每個電子郵件都會根據預先定義的條件進行檢查,然後在符合時保存到數據庫中。這些條件可以由用戶設置,並且可以是下列:如何存儲/格式化這些無限數據過濾條件

主題

  • 包含字符串
  • 不包含字符串

身體

  • 包含字符串
  • 不包含字符串

  • 具體地址

條件可以 「鏈接」,例如:

FILTER WHERE 
Subject CONTAINS "Order Confirmation" 
AND 
Email FROM "[email protected]" OR "[email protected]" 

我有如何格式化和存儲這些麻煩思維條件。我需要一個GUI,用戶可以創建這些條件。

我的問題是我應該如何存儲這些條件?即某種數據庫表結構,或者可能轉換爲字符串格式並存儲在單個表中。需要爲無限數量的用戶提供無限數量的條件,並且我需要知道有哪些運營商等。

希望這是足夠的信息!

*編輯邁克爾·

因此,我可以創造條件並保存。現在我正在檢索它們並嘗試匹配電子郵件。我用一個條件創建了一個過濾器:Subject包含'TEST'。只有一封電子郵件應該與此匹配,但不知何故,所有電子郵件都將被添加到匹配的數組中。

我的控制器是獲得電子郵件/條件:

public function check_email(){ 
    $filters = $this->filters_model->get_filters($owner_id=1); 
    foreach($filters->result() as $filter){ 
     $emails = $this->gmail->get_emails($mailbox_id = $filter->mailbox_id, $limit = 10); 

     $matched = array(); 
     $conditions = unserialize($filter->conditions); 

     foreach($emails as $email){ 
      if($conditions->isMet($email) == TRUE){ 
       $matched[] = $email; 
      } 
     } 

     echo count($matched); 
     echo '<pre>'.$filter->title.'<br /.'; 
     print_r($conditions); 
     echo '</pre><br />-----'; 
     exit; 
    } 
} 

Keyvalueprerequisite.php

這似乎很好地工作作爲stripos($subject, $this->value) !== FALSE;一個的var_dump僅顯示1個電子郵件TRUE。

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 

class Keyvalueprerequisite { 

    private $key; 
    private $comparator; 
    private $value; 

    public function __construct($key, $comparator, $value){ 
     $this->key = $key; 
     $this->comparator = $comparator; 
     $this->value = $value; 
    } 


    public function isMet(&$context) 
    { 
     switch ($this->key) { 

      case "subject": 

       $subject = $context["subject"]; 
       if ($this->comparator === "in"){ 
        return stripos($subject, $this->value) !== FALSE; 
       } else if ($this->comparator === "!in") { 
        return stripos($subject, $this->value) === FALSE; 
       } 

       return FALSE; 

       break; 

      case "body": 

       $body = $context["body"]; 

       if ($this->comparator === "in") { 
        return stripos($body, $this->value) !== FALSE; 
       } else if ($this->comparator === "!in") { 
        return stripos($body, $this->value) === FALSE; 
       } 

       return FALSE; 

       break; 

      case "from_address": 

       $from = $context["from"]; 

       if ($this->comparator === "=") { 
        return $this->value === $from; 
       } else if ($this->comparator === "!=") { 
        return $this->value !== $from; 
       } else{ 
        return false; 
       } 

       break; 

      default: 
     } 

     return FALSE; 
    } 

} 

Prerequisistegroup.php

東西可能不是很寫到這裏。對於10封電子郵件中的每一封,var_dump的$result = $result && $is_met都會返回true。

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 

class Prerequisitegroup { 

    private $type; 
    private $prerequisites; 

    public function __construct($type = 'AND'){ 
     $this->type = $type; 
    } 

    public function add(){ 
     foreach(func_get_args() as $prerequisite){ 
      $this->prerequisites[] = $prerequisite; 
     } 
    } 

    public function isMet(&$context) 
    { 
     if (empty($this->prerequisites) === FALSE) { 
      $result = TRUE; 

      foreach ($this->prerequisites as $prerequisite) { 
       $is_met = $prerequisite->isMet($context); 
       if ($this->type === 'AND') { 
        $result = $result && $is_met; 
        if ($result === FALSE) { 
         return FALSE; 
        } 
       } else { 
        $result = $result || $is_met; 
        if ($result === TRUE) { 
         return TRUE; 
        } 
       } 
      } 
      return $result; 
     } 

     return TRUE; 
    } 


} 

這是我正在檢查的條件:

string(3) "AND" 
    ["prerequisites":"Prerequisitegroup":private]=> 
    array(1) { 
    [0]=> 
    object(Prerequisitegroup)#23 (2) { 
     ["type":"Prerequisitegroup":private]=> 
     string(2) "OR" 
     ["prerequisites":"Prerequisitegroup":private]=> 
     array(1) { 
     [0]=> 
     object(Keyvalueprerequisite)#24 (3) { 
      ["key":"Keyvalueprerequisite":private]=> 
      string(7) "subject" 
      ["comparator":"Keyvalueprerequisite":private]=> 
      string(2) "in" 
      ["value":"Keyvalueprerequisite":private]=> 
      string(4) "TEST" 
     } 
     } 
    } 
    } 
} 
+0

你能像'email'一樣擁有多個'contains'嗎?你能對'包含'有否定嗎? – Michael

回答

1

對於CMS我解決了類似的問題,通過抽象的條件(先決條件)分爲兩類:前提和PrerequisiteGroup(一前者的子類,然後將它們序列化,或者更準確地說對象,因爲在MySQL中只有一個變成BLOB。

a這樣做的好處是我可以簡單地反序列化對象並調用一個函數而不會打擾附加函數的深度或複雜性。當然,缺點是我無法對這些對象進行數據庫查詢。但是,在這種特殊情況下,這不是問題,根據您自己的建議,我認爲這也不屬於您的問題。

Prerequisite類(或接口)實現了一個方法isMet($context),告訴你你的條件是否爲真。您的案例中的上下文將是要審查的$電子郵件。例如。如果來自電子郵件匹配「[email protected]」。

PrerequisiteGroup代表ANDOR,以簡化的方式。的缺省方法基團的條件是由

下面是創建和存儲的條件的一個例子:

$c1 = new KeyValuePrerequisite("EmailFrom", "=", "[email protected]"); 
$c2 = new KeyValuePrerequisite("EmailFrom", "=", "[email protected]"); 
$c3 = new KeyValuePrerequisite("Subject", "in", "Order Confirmation"); 

$from_condition = new PrerequisiteGroup('or'); 
$from_condition->add($c1, $c2); 

$final_condition = new PrerequisiteGroup($c3, $from_condition); // defaults to and 

$db->query("INSERT INTO conditions SET user_id = %i, conditions = %l", $user_id, serialize($final_condition)); 

下面是一個例子用法:

// Fetch conditions 

$email_conditions = $user->getEmailConditions() 

// Connect to your inbox and fetch relevant emails 

$matching_emails = array(); 
foreach ($emails as $email) { 
    if ($email_conditions->isMet($email) { 
     $matching_emails[] = $email; 
    } 
} 

前提接口:

interface Prerequisite 
{ 
    /** 
    * Must return TRUE or FALSE. 
    */ 
    public function isMet(&$context); 
} 

KeyValue先決條件實現(在我的實現中,這實際上是一個abstra CT類,但你的目的,你可以在這裏實現的一切,你可以把它叫做EmailPrerequisite或EmailCondition):

class KeyValuePrerequisite extends PrerequisiteGroup 
{ 
    protected $key; 
    protected $comparator; 
    protected $value; 

    public function __construct($key, $comparator, $value = NULL) 
    { 
     $this->key  = $key; 
     $this->comparator = $comparator; 
     $this->value  = $value; 
    } 

    public function isMet(&$context) 
    { 
     switch ($this->key) { 

      case "Subject": 

       $subject = $context["subject"]; 

       if ($this->comparator === "in") } 
        return stripos($subject, $this->value) !== FALSE; 
       } else if ($this->comparator === "not int") { 
        return stripos($subject, $this->value) === FALSE; 
       } 

       return FALSE; 

       break; 

      case "EmailFrom": 

       $from = $context["from"]; 

       return $this->value === $from; 

       break; 

      default: 
     } 

     return FALSE; 
    } 
} 

PrerequisiteGroup實現:

class PrerequisiteGroup implements Prerequisite 
{ 
    private $type; 
    private $prerequisites; 

    public function __construct($type = 'AND') 
    { 
     $this->type = $type; 
    } 

    public function add(Prerequisite $prerequisite) 
    { 
     if ($prerequisite instanceof Prerequisite) { 
      $this->prerequisites[] = $prerequisite; 
     } else { 
      throw new Exception('Unknown Prerequisite type ' . get_class($prerequisite)); 
     } 
    } 

    public function isMet(&$context) 
    { 
     if (empty($this->prerequisites) === FALSE) { 
      $result = $this->type === 'AND'; 
      foreach ($this->prerequisites as $prerequisite) { 
       $is_met = $prerequisite->isMet($context); 
       if ($this->type === 'AND') { 
        $result = $result && $is_met; 
        if ($result === FALSE) { 
         return FALSE; 
        } 
       } else { 
        $result = $result || $is_met; 
        if ($result === TRUE) { 
         return TRUE; 
        } 
       } 
      } 
      return $result; 
     } 

     return TRUE; 
    } 
} 

GUI

當涉及到GUI有幾種方法/模式。最常見的,我認爲,對於電子郵件相關的應用是有一個數字,都與運算表達式的行和[+]來添加更多的條件:

Row 1: [select: subject] [select:contains] [input:"Order Confirmation"] 

當談到我們需要表達from要麼。這僅僅是行很難做到的。這是先決條件或條件組的概念變得方便的地方。您只需添加一個新的行,這是一個組,並讓用戶選擇使用AND或OR。

組是AND組。

因此,GUI元素相當容易轉換爲代碼,反之亦然 - 尤其是使用KeyValuePrerequisite impl。先決條件。

希望這有助於或至少引發一些想法來解決您的問題。

+0

請注意,我有這個概念的幾個源和用例。就像顯示內容的條件一樣,給予折扣的先決條件或活動激活並顯示(在電子商務解決方案中)。既然你只需要用電子郵件進行操作,那可能簡單得多。 – Michael

+0

哇謝謝,這無疑給了我一些想法。你在編寫代碼,解決問題比我的水平高一點,但我會嘗試使用你提供的解決方案。可能會先回答一兩個問題! – iamjonesy

+0

當然,要求離開。 – Michael