Assetic to include all files within sub directories

时间:2015-11-18 21:03:50

标签: symfony assetic

Just started using assectic in my Symfony2 project and have it working quite well but can't see a nice easy way to include all the javascript files within a bundle.

The structure for my AppBundle is

AppBundle
  - Controller
  - Resources
    - views
    - public
      - js
        - Model
          - User.js
        - View
          - Dashboard.js
        - Bundle.js
        - Router.js

My current code to compile this is

{% javascripts '@AppBundle/Resources/public/js/*' %}
    <script src="{{ asset_url }}"></script>
{% endjavascripts %}

Which dumps out

<script src="/js/d356fea_part_1_Bundle_1.js"></script>
<script src="/js/d356fea_part_1_Router_2.js"></script>

So how can I get it to include all the javascript files in the sub folders?

Also is it possible to change the name of part_1? Would love that to say AppBundle during development.

1 个答案:

答案 0 :(得分:0)

经过大量的研究和演奏,这对于Assetic来说是不可能的。出于这个原因,我不得不从项目中删除Assetic,而且更新文件的速度太慢,这对前端开发人员造成了问题。

这不是一个正确的答案,但因为这是我能在短时间内找到的唯一解决方案,我最终总结了一个解决方案。

我们现在有一个像这样的JSON配置文件:

{
  "lib": {
    "cwd": {
      "vendor": "app/Resources/vendor"
    },
    "files": [
      "%vendor%/jquery/dist/jquery.min.js",
      "%vendor%/underscore/underscore-min.js",
      "%vendor%/backbone/backbone-min.js"    
    ]
  },
  "app": {
    "cwd": {
      "app": "app/Resources/public/js",
      "AppBundle": "src/AppBundle/Resources/public/js"
    },
    "files": [
      "%app%/*.js",
      "%AppBundle%/*.js"
    ]
  }
}

然后使用grunt-contrib-symlink将这些目录符号链接到web目录。

    symlink: {
        expanded: {
            files: function () {
                var symlinks = [];

                Object.keys(js).forEach(function (key) {
                    var file = js[key];

                    Object.keys(file.cwd).forEach(function (name) {
                        symlinks.push({
                            src: [file.cwd[name]],
                            dest: 'web/js/' + name
                        });
                    });
                });

                return symlinks;
            }()
        }
    },

然后我们有一个简单的twig函数,它将把它拆开并找到所有文件名,将它们分别包含在开发环境中。

class AssetService
{
    protected $rootDir;

    public function __construct($rootDir)
    {
        $this->rootDir = $rootDir;;
    }

    public function getJavascriptFiles($ref)
    {
        $output = [];
        $data = json_decode(file_get_contents(realpath($this->rootDir . '/Resources/config/include.json')), true);
        $paths = [];

        foreach ($data[$ref]['cwd'] as $key => $path) {
            $paths['%' . $key . '%'] = $this->rootDir . '/../' . $path;
        }

        foreach ($data[$ref]['files'] as $file) {
            $output = array_merge($output, str_replace(
                $paths,
                array_keys($data[$ref]['cwd']),
                $this->globRecursive(str_replace(array_keys($paths), $paths, $file), GLOB_NOCHECK)
            ));
        }

        return $output;
    }

    protected function globRecursive($pattern, $flags = 0)
    {
        $files = glob($pattern, $flags);
        foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
            $files = array_merge($files, $this->globRecursive($dir . '/' . basename($pattern)));
        }
        return $files;
    }
}

然后在开发中我们的输出看起来像这样:

<script src="/js/vendor/jquery/dist/jquery.min.js"></script>
<script src="/js/vendor/underscore/underscore-min.js"></script>
<script src="/js/vendor/backbone/backbone-min.js"></script>
<script src="/js/AppBundle/Bundle.js"></script>
<script src="/js/AppBundle/Router.js"></script>
<script src="/js/AppBundle/Collection/Products.js"></script>
<script src="/js/ProjectsBundle/Model/Project.js"></script>
<script src="/js/AppBundle/View/Product/Index.js"></script>

在使用相同的逻辑将文件与Grunt联系起来之后,在生产中我们有:

<script src="/js/lib.js"></script>
<script src="/js/app.js"></script>

有点hacky,但它是即时更新,并使PHP生产环境完全不知道前端资产。