【问题标题】:Store client/server string filtering directives for realtime use存储客户端/服务器字符串过滤指令以供实时使用
【发布时间】:2014-04-29 13:48:15
【问题描述】:

我有一个应用程序从外部 API 中获取行,并将它们发送到浏览器而不存储在数据库中。数据库只保存 API 请求的 URL。

从 API 接收的行需要按行过滤,无论是服务器端 (PHP) 还是客户端,并且过滤器需要存储在数据库中。例如,行的过滤器可以是子字符串或替换。

我假设您永远不想在数据库中包含 javascript/PHP 代码,但是这还能怎么做呢?有没有合适的javascript解决方案?

我想要在我的数据库表中是这样的:

------------------ API URL ------------ -------- 过滤器

第 1 行 --------------- api.com/get_data-----------这里是字符串过滤器

第 2 行 --------------- api.com/get_more_data---这里是字符串过滤器

“过滤器”包含有关如何过滤 API 结果中的字符串的说明。

【问题讨论】:

    标签: javascript php string


    【解决方案1】:

    取决于您要使用的过滤器类型,可能需要将代码存储在数据库中,我认为没有办法解决它,因为您对过滤器没有任何限制。但是,您可以尝试以下方法:

    1/ 函数名称:如果过滤器的数量很少,可以为它们编写函数并将过滤器名称存储在数据库中。

    2/ 正则表达式:RegExp 足以进行基本的子字符串替换和过滤。对于复杂的过滤器,您甚至可以为每个 URL 设置多个 RegExp。

    【讨论】:

    • 过滤列也可以是URI,它们不必是真实的URL,你可以发明私有的URN方案,例如:urn:x-regex:search:replace或urn:x-子字符串:开始:长度(或结束),任何东西。使用 URN 只是更容易在同一列中指定函数 参数。您的服务器端代码仍然负责解析过滤器并将它们委托给预定义函数,但这比将任意代码存储在数据库中要好,因为您可以验证参数等。
    • 你说得对,但我想这只是表示函数和正则表达式的一种方式。您几乎可以对任何序列化格式执行相同的操作,例如 JSON 或 XML。
    • 是的,最简单的。
    • 谢谢,@LeeKowalkowski。我想我正在寻找类似 URN 的方法。也许您可以将其放在答案中并进行更多解释。例如,如何在一列中添加多个过滤器?我将如何解析它?
    【解决方案2】:

    如何存储过滤器的类名,实例化一个实例,然后以这种方式通过过滤器运行数据?

    所以你可以设置如下过滤器:

    abstract class FilterAbs {
        abstract public function filter($to_filter);
    }
    
    class TrimFilter extends FilterAbs {
        public function filter($to_filter) {
            return trim($to_filter);
        }
    }
    

    然后您的过滤器列将包含过滤器列表(例如“TrimFilter、EmailFilter”)。您可以像这样创建实例和过滤器:

    $to_filter = "blah";
    
    $filter_col = "TrimFilter, EmailFilter";
    
    $filters = explode(",", $filter_col);
    
    foreach($filters as $filter_name) {
        $filter_name = trim($filter_name);
        $filter_obj = new $filter_name();
        if( !is_a($filter_obj, "FilterAbs") ) continue;
        $to_filter = $filter_obj->filter($to_filter);
    }
    

    如果您需要参数,可以将它们存储为 json 编码数组,并使用 ReflectionClass 使用参数创建实例(c.f. instantiate a class from a variable in PHP?)。

    【讨论】:

      【解决方案3】:

      您存储的 API 已经以结构化格式返回数据。这里最常见的数据格式是 JSON 或 XML。

      使用正则表达式作为过滤器会起作用,但是,如果数据已经以某种方式结构化,那么可能有特定的处理方式(为该特定格式构建的查询语言)。

      例如,如果 API 返回 XML,您可以使用 XPathXQuery 作为过滤器。可以使用 matches() 函数,以及 replace() 函数(一些示例可以是 found here) . 关于XPathare theseMDN articles 的其他一些很好的信息来源。此外,PHP 通过内置的 DOMXPath classSimpleXMLElement::xpath 提供 XPath 支持。

      如果你的 API 返回 JSON,有一些过滤方式:

      旁注:RFC 6902 将操作 add/remove/replace/move/copy/test 添加到上述 RFC 6901。

      当被视为描述过滤器(您希望将其存储在数据库中)的语言时,这些可能是可行的选项。

      【讨论】:

      • 我从这个答案中学到了很多。虽然,现在我正在寻找一些模式来过滤字符串,而不是 XML/JSON。
      【解决方案4】:

      我建议使用工厂模式并在数据库中存储一个 json 对象,其中包含构造过滤器的指令。 json 对象将从数据库中检索并传递给工厂,工厂将创建正确类型的过滤器对象。

      假设您有两个过滤器,一个使用正则表达式,另一个过滤值范围。然后,您可以按如下方式创建每个过滤器:

      class Filter{
          public function filter($results){
              $filteredResults = array();
              foreach($results as $item){
                  if($this->isMatch($item)){
                      $filteredResults[]=$item;
                  }
              }
              return $filteredResults
          }
          public function isMatch($row){
              return true;
          }
      }
      class RegexFilter extends Filter{
          public function __construct($regexString){
              $this->regex = $regexString;
          }
          public function isMatch($item){
              return preg_match($this->regex,$item) ==1;
          }
      }
      class RangeFilter extends Filter{
          public function __construct($min,$max){
              $this->max = $max;
              $this->min = $min;
          }
          public function isMatch($item){
              return $this->min < $item && $item <$this->max;
          }
      }
      class FilterFactory{
          public function createFilter($json){
              $filterData = json_decode($json);
              if($filterData->filterType == 'regex'){
                  return new RegexFilter($filterData->regexStr);
              }
              elseif($filterData->filterType == 'range'){
                  return new RangeFilter($filterData->min,$filterData->max);
              }
          }
      }
      // Example use
      // match only results that start with http
      $regexJsonStr = '{
              "filterType":"regex",
              "regexStr":"/^http/"
      }';
      $filter = FilterFactory::createFilter($regexJson);
      $filteredResults = $filter->filter($results);
      
      // Match results that values between 0 and 100 exclusive
      $regexJsonStr = '{
              "filterType":"range",
              "min":0,
              "max":100
      }';
      $filter = FilterFactory::createFilter($rangeJson);
      $filteredResults = $filter->filter($results);
      

      这种方法允许您使用最佳实践来维护您的代码库,同时仍将过滤指令存储在您的数据库中。

      子类使用 Filter 的 filter 方法,但它们自己的 isMatch 方法,使得添加新过滤器更容易。您只需 A) 从 Filter 类继承并实现一个新的 isMatch 方法; B)向FilterFactory-&gt;createFilter添加一个新子句以正确创建过滤器,C)将描述过滤器的Json添加到数据库中。

      您可以在其他任何地方使用完全相同的逻辑来过滤结果:

      $filter=FilterFactory::createFilter($jsonFromDatabase);
      $filteredResults = $filter->filter($resultsFromApi);
      

      【讨论】:

        【解决方案5】:

        // 首先,您必须清楚您必须指示代码根据需要过滤数据。 由于您使用了许多 API 并且它们的格式并不常见(正如我在之前的 cmets 和问题中看到的那样),您可以创建一个具有过滤功能的类(Filter)。

        // First create a formatted container of your API data from database in below format
        $filterContainer[0]['URL'] = 'http://www.api.com/get_data';
        $filterContainer[0]['Filter'] = 'ALPHA_NUMERIC_ONLY';
        
        $filterContainer[1]['URL'] = 'http://www.api.com/get_more_data';
        $filterContainer[1]['Filter'] = 'STRING';
        

        行 ------------------ API URL ------------------- 过滤器

        第 1 行 --------------- api.com/get_data-------------ALPHA_NUMERIC_ONLY

        第 2 行 --------------- api.com/get_more_data--------STRING

        /**
         * You will need to use these constant values to store in database in filters.
         *
         * Class APIFilter
         */
        class APIFilter
        {
            const ALPHA_NUMERIC = 'ALPHA_Numeric';
            const STRING        = 'STRING';
        
            /**
             * @param string $filterType Filter Constant value
             * @param string $data       Raw data
             *
             * @return string|bool
             */
            static public function GetFilteredData($filterType, $data)
            {
                if (empty($filterType) || empty($data)) {
                    return false;
                }
        
                switch ($filterType) {
                    case self::ALPHA_NUMERIC:
                        // Call Alpha numeric Filter functions and return filtered data
                        break;
        
                    case self::STRING:
                        // Call string filter functions and return filtered data
                        break;
        
                    default:
                        break;
                }
        
                return false;
            }
            /**
             ******** Write related filter functions here ********
             *
             */
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-06-08
          • 1970-01-01
          • 2011-08-07
          • 1970-01-01
          • 1970-01-01
          • 2021-03-03
          • 1970-01-01
          相关资源
          最近更新 更多