【问题标题】:Preprocessing PHP to remove functionality from built files预处理 PHP 以从构建的文件中删除功能
【发布时间】:2011-09-03 10:46:49
【问题描述】:

我一直在阅读有关 Phing 和 Ant 的文章,但我不确定这些工具中的哪一个(如果有的话)对这种情况最有用。

它可能很容易是调试语句等,但我会给你我们的文字扫描。

我们有一个可下载的 PHP 应用程序的免费和高级版本,而不是仅仅包含一个隐藏在某处的变量然后执行:

if($premium == true) {
   echo 'some additional functionality';
} else {
    echo 'basic functionality';
}

显然有人可以获取源代码并更改该变量,然后砰的一声——他们窃取了我们的代码。根据我的经验,像 Ioncube 之类的东西完全不实用,而且对托管公司的支持还不够好。

我更喜欢一些东西..也许类似于这个:

## if premium ##
echo 'some additional functionality';
## else ##
echo 'basic functionality';
## endif ##

然后我会运行两个构建,一个将溢价设置为 true,一个设置为 false,这将生成两个文件:

echo 'some additional functionality';

echo 'basic functionality';

根据传递给构建应用程序的相同条件,仅包含整个文件也是非常有帮助的。

我找不到这样做的方法,但如果可能的话,我愿意接受任何替代想法。

帮助很大,

更新

使用 C 预处理器很棒,看起来它可以满足我的所有需求。但是,我找不到如何做以下 3 件事。

#1 我需要将生成的 cmets 移除到输出文件中。以下是其中的一个示例。

# 1 "./index.php"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "./index.php"

我没有在您链接到的手册页中找到如何执行此操作的示例。

#2 我需要让它递归地遍历每个发现的文件。当我运行当前代码时出现错误:../target/./folder/test.php: No such file or directory

所以基本上我有我所在的“源”文件夹,其中包含一个名为“文件夹”的子文件夹,它不会重新创建它,也不会重新创建其中的文件 (test.php)

#3 我确信这很简单——我怎样才能让它处理 .js 文件,可能还有 .html 以确保安全?一通电话,我的意思是。我认为在 .jpg 等文件上运行它是个坏主意..

再次感谢!

【问题讨论】:

  • 你如何部署你的包?如果使用 PEAR 进行打包,只需创建两个不同的packages.xml(当然不能同时命名为package.xml)。
  • 我们实际上不使用 PEAR 进行包装。部署只是压缩文件并将其上传到我们的服务器。它在这个领域非常基础,简单是关键——只有一个来源,因此不需要版本控制等。但我无法手动跟踪不相关区域中的错误并将该修复合并到天知道有多少定制我们会结束的。

标签: php ant build phing


【解决方案1】:

很抱歉挖掘了这个话题,但我也有同样的需求,而且 CPP 方法对我的使用有太多副作用。

所以我为 phing 开发了一个基本的预处理器过滤器来解决问题:

#ifdef premium
  echo 'some additional functionality';
#else
  echo 'basic functionality';
#endif

过滤器在 github 上可用:https://github.com/tmuguet/PreProcessorFilter

【讨论】:

    【解决方案2】:

    我想到了一个想法,在此之前的答案已被接受,但我还是想分享它。所以这是交易:

    将所有付费功能存储在单独的文件中。使用钩子类,您可以检查并添加所需的功能。不要在免费版本的构建中包含付费功能。您将有 2 个 zip 文件,但只有一个来源。

    这是一个非常简单的 Hook 类,可能会对您有所帮助:

    Class Hook {
        var $features_enabled;
        public function __construct() {
            // Construction codes goes here.
            // You can check features files. If there is, require them once
            // if there isnt any, define a variable:
            if (file_exists("./features/feature1.php")) {
                require_once './features/feature1.php';
    
                // set this true. so we can check the features and run it
                $this->features_enabled = TRUE;
            }
            else {
                // there is no feature avaliable. So there is no need to check functions.
                $this->features_enabled = FALSE;
            }
        }
    
        /**
         * Check the Feature.
         *
         * @param string The feature name
         * @param array|string|... The arguments that you want to pass.
         */
        public function check($feature_name, $args = NULL) {
            // if features cannot be included on constructor, do not need to check.
            if ($this->features_enabled == FALSE)
                return;
    
            // if feature is a function: check it then run it
            if (function_exists($feature_name))
                $feature_name($args);
    
            // if feature is a Class: create it then return it.
            if (class_exists($feature_name))
                return new $feature_name($args);
        }
    }
    

    然后您可以将它们签入代码中的任何位置。示例:

    $hook = new Hook();
    
    //.... Codes goes here.
    
    // This will check for a function of class. If there is, execute it
    $hook->check('feature_badges');
    

    我知道它非常简单,需要以许多其他方式进行开发。但如果你能做到:

    • 您将分离特征。这样,您可以创建不同的包。
    • 您将使用类检查功能。即使用户看到功能名称,也没关系。因为他看不到功能的代码。

    【讨论】:

    • 这绝对是个好主意。然而,应用程序已经存在,并且由于规模的原因,以这种方式重构它(即提供功能的类)会很困难。
    【解决方案3】:

    它的技术含量很低,但当然有 C 预处理器可以完全满足您的需求;只需敲入几个 makefile 并使用 findgrep -R 调用它,您就会得到一个简单易懂的解决方案,其语法您可能知道。

    更多细节

    您可能已经在任何 *nix 主机上安装了 gcc。否则,它将是一个标准包。一些发行版将它单独提供给gcc(如 Debian 的 cpp 包)。

    程序有一些简单的指令; wiki page 是一个好的开始,manual 的细节比您需要的要多。基本上,使用-E 选项在每个文件上调用它只是为了进行宏处理,然后将输出复制到某个构建目录。

    您可以使用 find 编写一个单行脚本来执行此操作,沿着 find &lt;proj dir&gt; -type f -name '*.php' -exec cpp -E -D &lt;FULL or RESTRICTED&gt; {} -o &lt;build dir&gt;/{} \; 的行并在您的 PHP 中引用宏 FULL 和 RESTRICTED,例如

    #ifdef FULL
        <lines for paying customers>
    #endif
    

    更新为了使路径正常工作,试试这个:

    #!/bin/bash
    cd /.../phing/source/
    find . -type f -name '*.php' -exec cpp -E -D FULL {} -o ../target/{} \;
    

    那么../target/{}应该扩展为../target/./index.php

    更新

    添加了-P 以删除线标记 (#1)。添加了一行来复制目录结构(#2)。更改文件名匹配以在 js on html (#3) 上运行。

    #!/bin/bash
    cd /.../phing/source/
    find . -type d -exec mkdir -p ../target/{} \;
    find . -type f -regex '.*\.(php|html|js)' -exec cpp -E -P -D FULL {} -o ../target/{} \;
    

    【讨论】:

    • 这听起来可能很完美,但您认为您可以给我更多信息,了解我需要安装什么以及我的简单示例将如何发生吗?
    • 怎么样?更详细一点。我建议你也研究一下 git 的版本控制。它非常轻量级,学习时间不会太长,并且是跟踪更改和通过查找导致它们的原因来回滚回归的好方法。我也用它来管理不同机器之间的内容,所以我只能上传改变的东西(见nicholaswilson.me.uk/view-source/system/scripts/site-bundle的例子)。
    • 版本控制对我来说并不是一个巨大的需求(尽管我过去使用过 SVN)。细节非常出色,但是,打开输出文件时出现错误。 find /home/marc/Server/phing/source/ -type f -name '*.php' -exec cpp -E -D FULL {} -o /home/marc/Server/phing/target/{} \; 这给了我cc1: fatal error: opening output file /home/marc/Server/phing/target//home/marc/Server/phing/source/index.php: No such file or directory 到目前为止,您的帮助非常出色-我刚刚弄乱了我的目录吗?
    • 你可以使用sed 来调整路径,或者保持它非常简单,只需cd 进入你的源目录。如果你知道SVN,你可能会惊喜git,但是这需要一些时间来学习,所以很公平。
    • 到目前为止,这绝对是绝妙的——如果可以的话,我还有两个最后的问题。我可以在一个构建调用中包含组合吗? (为了满足多个 ifdef 调用?例如,FULL 和 DEBUG)而且,如果我只有一个 ifdef 并且我不想定义它(所以我需要构建一个没有定义 FULL - 什么都没有),我将如何这样做?
    【解决方案4】:

    嗯,Phing 是 PHP 的 Ant。我从未使用过 Phing,但我认为它已针对此类内容进行了调整。

    使用 Phing 创建两个单独的包:一个是高级应用程序,一个是免费应用程序。

    您也可以使用 Ant,但 Ant 是为 Java 调整的,而 Phing 是为 PHP 调整的。您可能希望在 Phing 上使用 Ant 的唯一原因是 Ant 可用的资源比 Phing 多得多。但是,如果您是一家 PHP 商店,那么学习使用 Phing 只是为了在简历上看起来不错。 (“是的,我是一名资深的 PHP 开发人员。我什至知道 Phing”)。

    【讨论】:

    • 当然,但非常具体地,这将如何在我的源文件中工作?我正在探索上面的 CPP 想法,但在 Phing 中更强大的解决方案可能对未来更好。我还没有找到一个合适的例子,只有直接的标记替换(没有帮助)或正则表达式匹配,这对我来说感觉很笨拙。
    • 也许使用 Phing 的最佳解决方案是创建两个构建目标,并通过直接调用脚本或 cpp 来使用它来管理您的预处理。
    • 使用 Phing(与 Ant 一样),您可以使用过滤器在处理源时更改源。我会在 cpp 之前使用它,它实际上是 C 而不是 PHP 的一部分。没有理由为什么 cpp 不起作用,但它不是 PHP 的一部分。因此,在雇用新开发人员时,您将遇到一些支持/教育问题。看看 。这可能是一个更好的选择。
    • 不幸的是,Phing 的内置过滤器不能很好地处理条件;这就是重点。 CPP 与 C 或 C++ 没有任何关系。它只是一种用于预处理的通用宏语言,它与 C 捆绑在一起,因为打包系统是原始的,他们需要一种包含头文件的方法。 CPP 简单而透明,所以也许从 Phing 调用它确实是最简单的解决方案。
    【解决方案5】:

    您可以自己构建这样的预处理器 - PHP 已内置支持解析 PHP 文件:http://www.php.net/manual/en/function.token-get-all.php

    我已经用它构建了一个混淆器,并且必须说它非常易于使用。只需打印您想要的令牌并删除“## if premium ##”块内的令牌。

    更新:我猜 C 预处理器的想法更好。不过为了完整起见,请留下这个答案。 :)

    【讨论】:

    • 很酷的想法,但只是“你可以构建自己的预处理器”这句话感觉就像是假经济!我想我更喜欢在 PHP 中做这件事的想法,但是,嘿。 C 的想法运行良好,除了我上面的 3 个问题,我相信我很快就会得到帮助!
    【解决方案6】:

    免责声明:我完全确定这不是最有效的方法!

    --

    我分四部分来做:

    • 克隆source目录结构target
    • 将PHP和JS文件从source解析成target
    • source复制所有jpg、gif、css等文件到target
    • target中的所有PHP和JS文件中删除cpp调用添加的cmets

    --

    find ./ -type d -exec mkdir ../target/{} \;
    find ./ -regextype posix-awk -regex "(.*.php|.*.js)" -exec cpp -E -D COMMERCIAL {} -o ../target/{} \;
    find ./ -type f -regextype posix-extended -regex "(.*.jpg|.*.gif|.*.png|.*.css|.*.html|.*.txt|.*.xml|.*.ttf)" -exec cp -p --parents "{}" ../target \;
    cd ../target
    find ./ -regextype posix-awk -regex "(.*.php|.*.js)" -exec sed -i ./{} -e 's/#.*//;/^\s*$/d' \;

    --

    正如我所说,我确信这并不是非常低效,但我执行并敲击了一个 .sh 文件 - 我有我的构建!

    【讨论】:

    • 显然我是从源目录的范围内执行的。我希望这对处于类似情况的人有所帮助。
    • 第 3 行,复制其他文件:您可以使用 -not -regex '.*\.(php|js)' 复制除这些文件之外的所有内容。另请参阅上面关于-P 的评论。如果某些文件很大,那么自然的方法是使用rsync。我很高兴你让它为你工作。
    猜你喜欢
    • 2022-12-29
    • 2013-06-29
    • 2023-02-22
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-21
    相关资源
    最近更新 更多