0

作成したメール テンプレートがあり、[NAME]、[EMAIL]、[PHONE] などを使用して、送信時にそれらを置き換えられるようにしたいと考えています。これらは簡単ですが、[PRODUCT:12] や [ARTICLE:23] などの他のより複雑なタグもあり、最初の部分を「タイプ」として読み取り、2 番目の部分を値として処理します。

ある種の preg_match と preg_replace が必要になると思いますが、私はこれらの機能が苦手なので、ここで本当に途方に暮れています。

助言がありますか?

- -編集 - -

ただ明確にします。問題は、括弧で囲まれた var:value の 2 つの部分にあります。リンクを作成できるように、それが製品であることを確認し、製品を返す id=12 を検索できるようにする必要があります。

---編集2---

public function parse_message_tags($matches){

    $keys = explode(':', $matches[1]);
    $key = $keys[0];
    $id = (array_key_exists(1, $keys)) ? $keys[1] : -1;
    switch ($key) {
       case 'NAME':
          return $this->session->member->name();
       break;
       case 'FIRST_NAME':
          return $this->session->member->first_name;
       break;
       case 'EMAIL':
          return $this->session->member->email;
       break;
       case 'PRODUCT':
          $product = Product::find_by_id($id);
          return '<a href="/products/'.$product->seo_name.'">'.$product->name.'</a>';
       break;
       case 'ARTICLE':
          $product = Article::find_by_id($id);
          return '<a href="/blog/'.$article->seo_title.'">'.$article->name.'</a>';
       break;
    }

}

public function parse_message($input)
{
    $pattern = '/\[(NAME|FIRST_NAME|EMAIL|PHONE|PRODUCT:\d+|ARTICLE:\d+)\]/';
    return preg_replace_callback($pattern, create_function('$matches', 'return self::parse_message_tags;'), $input);

}

結果:

致命的なエラー: アクティブなクラス スコープがない場合、self:: にアクセスできません

また

致命的なエラー: オブジェクト コンテキストでない場合に $this を使用する

私は create_function() がスコープ/コンテキストからあなたを連れ出すと推測しています。ここでは明らかにクラス メソッドを使用しているため、単純に「parse_message_tags」を呼び出すことはできません。

4

4 に答える 4

2

この状況で使用する関数はpreg_replace_callback()です。これは、2番目のタイプのタグのインデックスで配列ルックアップを実行する必要があるためです。ここでは、コードをクラスでラップすると便利です。どういうわけか、コールバック関数にデータを渡す必要があります。グローバル変数の使用は醜いでしょう。

class EmailTemplate {

    protected $text;
    protected $data;

    public function __construct($text, $data) {
        $this->text = $text;
        $this->data = $data;
    }

    public function callback($matches) {
        $replacement = null;
        $name = $matches[1];
        $index = (int) $matches[2];
        if(isset($this->data[$name])) {
            $value = $this->data[$name];
            if(is_scalar($value)) {
                $replacement = $value;
            } else {
                if(isset($value[$index])) {
                    $replacement = $value[$index];
                }
            }
        }
        return $replacement;
    }

    public function __toString() {
        return preg_replace_callback('/\[(\w+)(?:\:(\d+))?\]/', array($this, 'callback'), $this->text);
    }
}

$data = array(
    "NAME" => "Bob",
    "PRODUCT" => array("dog", "cat", "eggplant")
);
$email = new EmailTemplate("Dear [NAME], please buy my [PRODUCT:2]", $data);

echo $email;

パターンはやや当惑するように見えるかもしれません。ここで重要なのは(?:)?部。2番目の疑問符は、\:(\ d +)内のパターンがオプションであることを示します。最初の疑問符とコロンは、文字をキャプチャせずにグループ化します。配列ルックアップの番号だけが必要なので、ここで使用します。

于 2012-08-10T06:43:57.283 に答える
1

この正規表現は Id の両方に一致し、テキスト内の ID を提供する必要があります。\[([A-Z]*):(\d*)\] 新しい正規表現\[([A-Z]*:?\d*)\]は両方に一致します。

于 2012-08-10T06:02:14.787 に答える
0

これは、以下を使用して比較的クリーンに実行できますpreg_replace_callback()

$pattern = '/\[(NAME|EMAIL|PHONE|PRODUCT:\d+|ARTICLE:\d+)\]/';

function callbackHandler($matches) {
    $keys = explode(':', $matches[1]);
    $key = $keys[0];
    $id = (array_key_exists(1, $keys)) ? $keys[1] : -1;
    switch ($key) {
        case 'NAME':
            return '##name##';
        break;
        case 'EMAIL':
            return '##email##';
        break;
        case 'PHONE':
            return '##phone##';
        break;
        case 'PRODUCT':
            return '##product id:'.$id.'##';
        break;
        case 'ARTICLE':
            return '##article id:'.$id.'##';
        break;
    }
}

$string = "Hello [NAME], have you checked out our latest product [PRODUCT:32]. We're sure you'll like it! If you don't we'll call you on [PHONE] and link you to [ARTICLE:12], which will put your email ([EMAIL]) on our hourly email newsletter";

echo preg_replace_callback($pattern, 'callbackHandler', $string);

戻り値:

こんにちは##name##、最新の製品## product id:32##をチェックしましたか。きっと気に入るはずです!そうでない場合は、## phone ##で電話をかけ、## article id:12 ##にリンクします。これにより、1時間ごとのメールニュースレターにメール(## email ##)が掲載されます。

コードパッドで見る

于 2012-08-10T07:22:48.680 に答える
0

次のような関数を使用できます。

function parse_tag($tag) {
  preg_match('#\[(.*?)\]#', $tag, $matches);
  return explode(':', $matches[1]);
}

これを使用するには、次のようにします。

$tests = array(
  '[NAME]' => array('NAME'),
  '[PRODUCT:SHIRT]' => array('PRODUCT', 'SHIRT'), 
  '[ARTICLE:23]' => array('ARTICLE', 23)
);

foreach($tests as $search => $expected) {
  $result = parse_tag($search);
  assert($expected == $result);
}

ここで実際の例を参照してください

于 2012-08-10T06:02:30.930 に答える