代码之家  ›  专栏  ›  技术社区  ›  Echo says Reinstate Monica

如何附加到字符串中的所有URL?

php
  •  4
  • Echo says Reinstate Monica  · 技术社区  · 16 年前

    我应该如何在所有URL的末尾附加一个HTML字符串,该字符串将作为电子邮件发送?我想像这样添加谷歌分析活动跟踪:
    ?utm_source=email&utm_medium=email&utm_campaign=product_notify

    99%的页面不会以“.html”结尾,某些URL可能已经有类似的内容 ?sr=1 最后。

    6 回复  |  直到 9 年前
        1
  •  5
  •   ircmaxell    16 年前

    好。。。你可以这样做:

    function AppendCampaignToString($string) {
        $regex = '#(<a href=")([^"]*)("[^>]*?>)#i';
        return preg_replace_callback($regex, '_appendCampaignToString', $string);
    }
    function _AppendCampaignToString($match) {
        $url = $match[2];
        if (strpos($url, '?') === false) {
            $url .= '?';
        }
        $url .= '&utm_source=email&utm_medium=email&utm_campaign=product_notify';
        return $match[1].$url.$match[3];
    }
    

    这会自动找到页面上的所有链接(甚至是外部链接,所以要小心)。这个?检查只是确保我们在上面附加了一个查询字符串…

    编辑:修复了regex中未按预期工作的问题。

        2
  •  6
  •   zero323 little_kid_pea    12 年前

    更新到@ircmaxell的答案,regex现在可以匹配,即使在before href&code simplification上有属性。

    /**
     * @param string $body
     * @param string $campaign
     * @param string $medium
     * @return mixed
     */
    protected function add_analytics_tracking_to_urls($body, $campaign, $medium = 'email') {
        return preg_replace_callback('#(<a.*?href=")([^"]*)("[^>]*?>)#i', function($match) use ($campaign, $medium) {
            $url = $match[2];
            if (strpos($url, '?') === false) {
                $url .= '?';
            } else {
                $url .= '&';
            }
            $url .= 'utm_source=' . $medium . '&utm_medium=' . $medium . '&utm_campaign=' . urlencode($campaign);
            return $match[1] . $url . $match[3];
        }, $body);
    }
    
        3
  •  2
  •   Wrikken    9 年前
    <?php
    $add = array(
     'utm_source'=>'email',
     'utm_medium'=>'email'
     'utm_campaign'=>'product_notify');
    $doc = new DOMDocument();
    $doc->loadHTML('your html');
    foreach($doc->getElementsByTagName('a') as $link){
        $url = parse_url($link->getAttribute('href'));
        $gets = isset($url['query']) ? array_merge(parse_str($url['query'])) : $add;
        $newstring = '';
        if(isset($url['scheme'])) $newstring .= $url['scheme'].'://';
        if(isset($url['host']))   $newstring .= $url['host'];
        if(isset($url['port']))   $newstring .= ':'.$url['port'];
        if(isset($url['path']))   $newstring .= $url['path'];
        $newstring .= '?'.http_build_query($gets);
        if(isset($url['fragment']))   $newstring .= '#'.$url['fragment'];
        $link->setAttribute('href',$newstring);
     }
     $html - $doc->saveHTML();
     ?>
    
        4
  •  1
  •   OzzyCzech    10 年前

    这里是我的解决方案,简单的问题,但非常复杂的解决方案,适用于所有URL类型

    $campaign = (object)['utm_source' => 'email', 'utm_medium' => 'email', 'utm_campaign' => 'abc'];
    $host = 'www.me.com';
    
    $html = preg_replace_callback(
            '#(<a.*?href=["\']?)(?<href>https?://[^\s"\']+)(["\']?.*?>.*?</a>)#si', function ($matches) use ($campaign, $host) {
        $url = parse_url($matches['href']);
        // if (isset($url['host']) && $url['host'] !== $host) return $matches[0];
        parse_str(isset($url['query']) ? $url['query'] : '', $query);
        $query = array_merge(
            $query, array_filter(
                      [
                          'utm_source' => $campaign->utm_source,
                          'utm_medium' => $campaign->utm_medium,
                          'utm_term' => $campaign->utm_term,
                          'utm_content' => $campaign->utm_content,
                          'utm_campaign' => $campaign->utm_campaign,
                      ]
                  )
        );
        return $matches[1] . // anchor part before url
        (isset($url['scheme']) ? $url['scheme'] . '://' : '') .
        (isset($url['user']) ? $url['user'] : '') .
        (isset($url['pass']) ? (isset($url['user']) ? ':' : '') . $url['pass'] : '') .
        (isset($url['user']) || isset($url['pass']) ? '@' : '').
        (isset($url['host']) ? $url['host'] : '') .
        (isset($url['port']) ? ':' . $url['port'] : '') .
        (isset($url['path']) ? $url['path'] : '') .
        '?' . http_build_query($query) .
        (isset($url['fragment']) ? '#' . $url['fragment'] : '') .
        $matches[3]; // anchor part after URL
    }, $html
    );
    

    最后一部分(concat url)也可以替换为 http_build_url() 但您需要启用HTTP扩展。

    在以下URL上测试了代码:

    <a href="http://www.me.com">Lorem</a>
    <a href="http://www.me.com/">ipsum</a>
    <a href="http://www.me.com/#section-2">dolor</a>
    <a href="http://www.me.com/path-to-somewhere/file.php">sit</a>
    <a href="http://www.me.com/?">amet</a>
    <a href="http://www.me.com/?foo=bar">consectetur</a>
    <a href="http://www.me.com/?foo=bar&bar=foo">consectetur</a>
    <a href="http://www.NOTME.com?utm_source=XXX&utm_medium=XXX&utm_campaign=XXX">existing utm params</a>
    <a href="http://user:password@www.me.com/?foo=bar#section-3">elit</a>
    <a href="http://user:@www.me.com/?foo=bar#section-3">elit</a>
    <a href="http://user@www.me.com?foo=bar#section-3">elit</a>
    

    结果如下:

    <a href="http://www.me.com?utm_source=email&utm_medium=email&utm_campaign=abc">Lorem</a>
    <a href="http://www.me.com/?utm_source=email&utm_medium=email&utm_campaign=abc">ipsum</a>
    <a href="http://www.me.com/?utm_source=email&utm_medium=email&utm_campaign=abc#section-2">dolor</a>
    <a href="http://www.me.com/path-to-somewhere/file.php?utm_source=email&utm_medium=email&utm_campaign=abc">sit</a>
    <a href="http://www.me.com/?utm_source=email&utm_medium=email&utm_campaign=abc">amet</a>
    <a href="http://www.me.com/?foo=bar&utm_source=email&utm_medium=email&utm_campaign=abc">consectetur</a>
    <a href="http://www.me.com/?foo=bar&bar=foo&utm_source=email&utm_medium=email&utm_campaign=abc">consectetur</a>
    <a href="http://www.NOTME.com?utm_source=email&utm_medium=email&utm_campaign=abc">existing utm params</a>
    <a href="http://user:password@www.me.com/?foo=bar&utm_source=email&utm_medium=email&utm_campaign=abc#section-3">elit</a>
    <a href="http://user:@www.me.com/?foo=bar&utm_source=email&utm_medium=email&utm_campaign=abc#section-3">elit</a>
    <a href="http://user@www.me.com?foo=bar&utm_source=email&utm_medium=email&utm_campaign=abc#section-3">elit</a>
    

    正如您可以注意到的,如果您希望在之后立即取消筛选主机名注释行,我的代码适用于HTML中的所有链接(不仅仅是me.com)。 parse_url() .

        5
  •  0
  •   softcr    16 年前

    您可以使用以下代码段,将您的Google Analytics获取参数附加到当前脚本URI的现有参数。

    function getQuery() {
    
     $url = parse_url($_SERVER['REQUEST_URI']);
    
     return $url['query'].'&utm_source=email&utm_medium=email&utm_campaign=product_notify';
    }
    
        6
  •  0
  •   qdev    12 年前

    我昨晚构建并测试的解决方案:

    我只匹配那些还没有“utm_uuu”类查询参数的链接,但是包含了作为路径一部分的“utm_u”链接:在查询参数之前,或者像“xutm_u”这样的另一个参数名称的子字符串之前。

    为此,我使用了正的和负的regex lookahead断言的组合。( http://php.net/manual/en/regexp.reference.assertions.php )

    我还允许标签在href之前和之后具有其他属性

    $pattern = '/<a[^>]*href="(?=(.(?!(\?|&)utm_))*?>)[^"]*/i';
    

    哪些链接与没有“”的所有链接匹配?在href标签中的utm_uu'或'&utm_uu'。

    然后,我使用类回调函数解决方案,以便能够传递要附加的查询参数(作为回调的额外参数)

    class link_params{
      private $parameters;    
    
      function __construct($params){
        $this->parameters = $params;
      }
    
      function callback($matches){
        return $matches[0] . (preg_match('/\\?[^"]/', $matches[0]) ? '&' : '?') . http_build_query($this->parameters);
      }
    }
    

    准备要添加到链接的查询参数:

    $params_to_add = array(
        'utm_source' => 'newsletter-sep13',
        'utm_medium' => 'email',
        'utm_campaign' => 'product-X'
    );
    
    $callback_helper = new link_params($params_to_add);
    

    最后,我应用preg_replace_回调函数,如下所示:

    $html = preg_replace_callback($pattern, array($callback_helper, 'callback'), $html);
    
    推荐文章