• 技术文章 >后端开发 >php教程

    php实现压缩合并js的方法

    墨辰丷墨辰丷2018-06-01 11:02:33原创889
    这篇文章主要介绍了php实现压缩合并js的方法,涉及php压缩文件类JSMin的相关调用与使用技巧,并附带了完整的demo源码供读者下载参考,需要的朋友可以参考下

    test.php文件如下:

    require_once('jsmin.php');
    $files = glob("js/*.js");
    $js = "";
    foreach($files as $file) {
      $js .= JSMin::minify(file_get_contents($file));
    }
    file_put_contents("combined.js", $js);
    echo "success";

    jsmin.php文件如下:

    <?php
    /**
     * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
     *
     * This is pretty much a direct port of jsmin.c to PHP with just a few
     * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
     * outputs to stdout, this library accepts a string as input and returns another
     * string as output.
     *
     * PHP 5 or higher is required.
     *
     * Permission is hereby granted to use this version of the library under the
     * same terms as jsmin.c, which has the following license:
     *
     * --
     * Copyright (c) 2002 Douglas Crockford (www.crockford.com)
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy of
     * this software and associated documentation files (the "Software"), to deal in
     * the Software without restriction, including without limitation the rights to
     * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     * of the Software, and to permit persons to whom the Software is furnished to do
     * so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in all
     * copies or substantial portions of the Software.
     *
     * The Software shall be used for Good, not Evil.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     * SOFTWARE.
     * --
     *
     * @package JSMin
     * @author Ryan Grove <ryan@wonko.com>
     * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
     * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
     * @copyright 2012 Adam Goforth <aag@adamgoforth.com> (Updates)
     * @license http://opensource.org/licenses/mit-license.php MIT License
     * @version 1.1.2 (2012-05-01)
     * @link https://github.com/rgrove/jsmin-php
     */
    class JSMin {
     const ORD_LF      = 10;
     const ORD_SPACE     = 32;
     const ACTION_KEEP_A   = 1;
     const ACTION_DELETE_A  = 2;
     const ACTION_DELETE_A_B = 3;
     protected $a      = '';
     protected $b      = '';
     protected $input    = '';
     protected $inputIndex = 0;
     protected $inputLength = 0;
     protected $lookAhead  = null;
     protected $output   = '';
     // -- Public Static Methods --------------------------------------------------
     /**
      * Minify Javascript
      *
      * @uses __construct()
      * @uses min()
      * @param string $js Javascript to be minified
      * @return string
      */
     public static function minify($js) {
      $jsmin = new JSMin($js);
      return $jsmin->min();
     }
     // -- Public Instance Methods ------------------------------------------------
     /**
      * Constructor
      *
      * @param string $input Javascript to be minified
      */
     public function __construct($input) {
      $this->input    = str_replace("\r\n", "\n", $input);
      $this->inputLength = strlen($this->input);
     }
     // -- Protected Instance Methods ---------------------------------------------
     /**
      * Action -- do something! What to do is determined by the $command argument.
      *
      * action treats a string as a single character. Wow!
      * action recognizes a regular expression if it is preceded by ( or , or =.
      *
      * @uses next()
      * @uses get()
      * @throws JSMinException If parser errors are found:
      *     - Unterminated string literal
      *     - Unterminated regular expression set in regex literal
      *     - Unterminated regular expression literal
      * @param int $command One of class constants:
      *   ACTION_KEEP_A   Output A. Copy B to A. Get the next B.
      *   ACTION_DELETE_A  Copy B to A. Get the next B. (Delete A).
      *   ACTION_DELETE_A_B Get the next B. (Delete B).
     */
     protected function action($command) {
      switch($command) {
       case self::ACTION_KEEP_A:
        $this->output .= $this->a;
       case self::ACTION_DELETE_A:
        $this->a = $this->b;
        if ($this->a === "'" || $this->a === '"') {
         for (;;) {
          $this->output .= $this->a;
          $this->a    = $this->get();
          if ($this->a === $this->b) {
           break;
          }
          if (ord($this->a) <= self::ORD_LF) {
           throw new JSMinException('Unterminated string literal.');
          }
          if ($this->a === '\\') {
           $this->output .= $this->a;
           $this->a    = $this->get();
          }
         }
        }
       case self::ACTION_DELETE_A_B:
        $this->b = $this->next();
        if ($this->b === '/' && (
          $this->a === '(' || $this->a === ',' || $this->a === '=' ||
          $this->a === ':' || $this->a === '[' || $this->a === '!' ||
          $this->a === '&' || $this->a === '|' || $this->a === '?' ||
          $this->a === '{' || $this->a === '}' || $this->a === ';' ||
          $this->a === "\n" )) {
         $this->output .= $this->a . $this->b;
         for (;;) {
          $this->a = $this->get();
          if ($this->a === '[') {
           /*
            inside a regex [...] set, which MAY contain a '/' itself. Example: mootools Form.Validator near line 460:
             return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value'));
           */
           for (;;) {
            $this->output .= $this->a;
            $this->a = $this->get();
            if ($this->a === ']') {
              break;
            } elseif ($this->a === '\\') {
             $this->output .= $this->a;
             $this->a    = $this->get();
            } elseif (ord($this->a) <= self::ORD_LF) {
             throw new JSMinException('Unterminated regular expression set in regex literal.');
            }
           }
          } elseif ($this->a === '/') {
           break;
          } elseif ($this->a === '\\') {
           $this->output .= $this->a;
           $this->a    = $this->get();
          } elseif (ord($this->a) <= self::ORD_LF) {
           throw new JSMinException('Unterminated regular expression literal.');
          }
          $this->output .= $this->a;
         }
         $this->b = $this->next();
        }
      }
     }
     /**
      * Get next char. Convert ctrl char to space.
      *
      * @return string|null
      */
     protected function get() {
      $c = $this->lookAhead;
      $this->lookAhead = null;
      if ($c === null) {
       if ($this->inputIndex < $this->inputLength) {
        $c = substr($this->input, $this->inputIndex, 1);
        $this->inputIndex += 1;
       } else {
        $c = null;
       }
      }
      if ($c === "\r") {
       return "\n";
      }
      if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
       return $c;
      }
      return ' ';
     }
     /**
      * Is $c a letter, digit, underscore, dollar sign, or non-ASCII character.
      *
      * @return bool
      */
     protected function isAlphaNum($c) {
      return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
     }
     /**
      * Perform minification, return result
      *
      * @uses action()
      * @uses isAlphaNum()
      * @uses get()
      * @uses peek()
      * @return string
      */
     protected function min() {
      if (0 == strncmp($this->peek(), "\xef", 1)) {
        $this->get();
        $this->get();
        $this->get();
      } 
      $this->a = "\n";
      $this->action(self::ACTION_DELETE_A_B);
      while ($this->a !== null) {
       switch ($this->a) {
        case ' ':
         if ($this->isAlphaNum($this->b)) {
          $this->action(self::ACTION_KEEP_A);
         } else {
          $this->action(self::ACTION_DELETE_A);
         }
         break;
        case "\n":
         switch ($this->b) {
          case '{':
          case '[':
          case '(':
          case '+':
          case '-':
          case '!':
          case '~':
           $this->action(self::ACTION_KEEP_A);
           break;
          case ' ':
           $this->action(self::ACTION_DELETE_A_B);
           break;
          default:
           if ($this->isAlphaNum($this->b)) {
            $this->action(self::ACTION_KEEP_A);
           }
           else {
            $this->action(self::ACTION_DELETE_A);
           }
         }
         break;
        default:
         switch ($this->b) {
          case ' ':
           if ($this->isAlphaNum($this->a)) {
            $this->action(self::ACTION_KEEP_A);
            break;
           }
           $this->action(self::ACTION_DELETE_A_B);
           break;
          case "\n":
           switch ($this->a) {
            case '}':
            case ']':
            case ')':
            case '+':
            case '-':
            case '"':
            case "'":
             $this->action(self::ACTION_KEEP_A);
             break;
            default:
             if ($this->isAlphaNum($this->a)) {
              $this->action(self::ACTION_KEEP_A);
             }
             else {
              $this->action(self::ACTION_DELETE_A_B);
             }
           }
           break;
          default:
           $this->action(self::ACTION_KEEP_A);
           break;
         }
       }
      }
      return $this->output;
     }
     /**
      * Get the next character, skipping over comments. peek() is used to see
      * if a '/' is followed by a '/' or '*'.
      *
      * @uses get()
      * @uses peek()
      * @throws JSMinException On unterminated comment.
      * @return string
      */
     protected function next() {
      $c = $this->get();
      if ($c === '/') {
       switch($this->peek()) {
        case '/':
         for (;;) {
          $c = $this->get();
          if (ord($c) <= self::ORD_LF) {
           return $c;
          }
         }
        case '*':
         $this->get();
         for (;;) {
          switch($this->get()) {
           case '*':
            if ($this->peek() === '/') {
             $this->get();
             return ' ';
            }
            break;
           case null:
            throw new JSMinException('Unterminated comment.');
          }
         }
        default:
         return $c;
       }
      }
      return $c;
     }
     /**
      * Get next char. If is ctrl character, translate to a space or newline.
      *
      * @uses get()
      * @return string|null
      */
     protected function peek() {
      $this->lookAhead = $this->get();
      return $this->lookAhead;
     }
    }
    // -- Exceptions ---------------------------------------------------------------
    class JSMinException extends Exception {}
    ?>

    总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。

    相关推荐:

    php实现URL加密解密

    PHP版单点登陆实现方案

    php实现背景图上添加圆形logo图标

    以上就是php实现压缩合并js的方法的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:javascript php 方法
    上一篇:PHP实现的mysql读写分离操作 下一篇:PHP基于pdo的数据库操作类【可支持mysql、sqlserver及oracle】
    20期PHP线上班

    相关文章推荐

    精选22门好课,价值3725元,开通VIP免费学习!• php7.2怎么连接oracle数据库?OCI8扩展的安装• PHP 获得文件夹大小 计算文件_PHP教程• PHP服务器变量设置的方法介绍_PHP教程• 关于PHP数组转字符串详细介绍_PHP教程• 深入剖析PHP变量的具体使用方法_PHP教程
    1/1

    PHP中文网