Question

I have a class that uses Assetic to generate some css files to disk. I'll jump right into the code.

In my layout header, I'm doing something like this:

$assetify = new Assetify();  
$assetify->setDebug(true);
$assetify->setAssetDirectory(BASE_DIR . '/public/assets');
$assetify->setOutputDirectory(BASE_DIR . '/public/assets/generated');
$assetify
    ->addStylesheet('/assets/css/bootstrap-2.3.2.css')
    ->addStylesheet('/assets/css/select2-3.4.3.css')
    ->addStylesheet('/assets/css/main.css');

echo $assetify->dump();

My "Assetify" class runs this through Assetic. I'll paste what I hope are only the relevant portions from the dump() function:

// The Asset Factory allows us to not have to do all the hard work ourselves.
$factory = new AssetFactory($this->assetDirectory, $this->debug);
$factory->setDefaultOutput('/generated/*.css');

// The Filter Manager allows us to organize filters for the asset handling.
// For other filters, see: https://github.com/kriswallsmith/assetic
$fm = new FilterManager();
$fm->set('yui_css', new Yui\CssCompressorFilter('/usr/local/bin/yuicompressor-2.4.7.jar'));
$fm->set('yui_js', new Yui\JsCompressorFilter('/usr/local/bin/yuicompressor-2.4.7.jar'));
$factory->setFilterManager($fm);

// The Asset Manager allows us to keep our assets organized.
$am = new AssetManager();
$factory->setAssetManager($am);

// The cache-busting worker prefixes every css with what amounts to a version number.
$factory->addWorker(new CacheBustingWorker());

$assetCollection = array();
foreach ($assetGroups as $assetGroup) {
    foreach ($assetGroup as $media => $items) {
        $fileCollection = array();
        foreach ($items as $item) {
            // Add this asset to the asset collection.
            $fileCollection[] = new FileAsset($item);
        }
        $assetCollection[] = new AssetCollection($fileCollection);
    }
}

$assetCollection = new AssetCollection($assetCollection);
$am->set('base_css', $assetCollection);

// Generate the required assets. Prefixing a filter name with a question mark
// will cause that filter to be omitted in debug mode.
$asset = $factory->createAsset(
    array('@base_css'),
    array('?yui_css')
);

// Configure an internal file system cache so we don't regenerate this file on every load.
$cache = new AssetCache(
    $asset,
    new FilesystemCache($this->outputDirectory)
);

// And generate static versions of the files on disk.
$writer = new AssetWriter($this->assetDirectory);
$writer->writeAsset($cache);

This generates two different files, 87229eb-f47a352.css and a37c1589762f39aee5bd24e9405dbdf9. The contents of the files are exactly the same. The 87229eb-f47a352.css file seems to get generated every single time, and the other file is not regenerated unless the contents of the files change (this is what I would like). If I comment out the $writer->writeAsset($cache), no files are written to disk.

What obvious configuration am I missing? I appreciate the help, thank you.

Was it helpful?

Solution

I was able to roughly replicate your code and got the same results.

I was trying to get the same results as what I think you require but ended up writing my own code to cache and serve static files.

It's not complete by any means but it is working. It has the following features:

  • You can choose to cache files for different pages if you specify $filename
  • You can choose to create versions of your released files or delete previous versions
  • A cached file will be generated to your target folder only if changes have made to a source file
  • You just need to put the code in to a class or function and return the url to serve.

Hope it helps :)

 <?php
    use Assetic\Factory\AssetFactory;
    use Assetic\AssetManager;
    use Assetic\FilterManager;
    use Assetic\Asset\AssetCollection;
    use Assetic\Asset\FileAsset;
    use Assetic\Filter\JSMinFilter;

    // JavaScript Collection
    $js_collection[] = new FileAsset(SCRIPT_PATH . 'jquery.js');
    $js_collection[] = new FileAsset(SCRIPT_PATH . 'production.js');
    if (file_exists(SCRIPT_PATH . $page_info['name'] . '.js')) {
        $js_collection[] = new FileAsset(SCRIPT_PATH . $page_info['name'] . '.js');
    }

    // CSS Collection
    $css_collection[] = new FileAsset(STYLE_PATH . 'theme.css');
    if (file_exists(STYLE_PATH . $page_info['name'] . '.css')) {
        $css_collection[] = new FileAsset(STYLE_PATH . $page_info['name'] . '.css');
    }

    // The Filter Manager allows us to organize filters for the asset handling.
    $fm = new FilterManager();
    $fm->set('js', new JSMinFilter());

    $js = new AssetCollection (
        $js_collection
    );
    $js->setTargetPath(SCRIPT_PATH . 'static');

    $css = new AssetCollection (
        $css_collection
    );
    $css->setTargetPath(STYLE_PATH . 'static');

    $am = new AssetManager();
    $am->set('js', $js);
    $am->set('css', $css);



    //** TO DO: put the below in a class and return the static file names **//

    // options
    $seperator = '-';
    $filename = $page_info['name'];
    $versions = false;

    // get a list of all collection names
    $collections = $am->getNames();

    // get each collection
    foreach ($collections as $collection_name) {

        // get the collection object
        $collection = $am->get($collection_name);

        // ensure file types are identical
        $last_ext = false;
        foreach ($collection as $leaf) {
            $ext = strtolower(pathinfo($leaf->getSourcePath(), PATHINFO_EXTENSION));
            if (!$last_ext || $ext == $last_ext) {
                $last_ext = $ext;
            } else {
                throw new \RuntimeException('File type mismatch.');
            }
        }

        // get the highest last-modified value of all assets in the current collection
        $modified_time = $collection->getLastModified();

        // get the target path
        $path = $collection->getTargetPath();

        // the target path must be set
        if (!$path) {
            throw new \RuntimeException('Target path not specified.');
        }

        // build the filename to check
        $file = ($filename) ? $filename . $seperator . $modified_time . '.' . $ext : $modified_time . '.' . $ext;
        $cached_file  = $path . '/' . $file;

        // the file doesn't exist so we need to minify, dump and save as new cached file
        if (!file_exists($cached_file)) {

            // create the output dir if it doesnt exist
            if (!is_dir($path) && false === @mkdir($path, 0777, true)) {
                throw new \RuntimeException('Unable to create directory ' . $path);
            }

            // apply the filters
            if ($fm->has($collection_name)) {
                $collection->ensureFilter($fm->get($collection_name));
            }

            // If not versioned, delete previous version of this file
            if (!$versions) {
                if ($filename) {
                    foreach (glob($path . '/' . $filename . $seperator . '*.' . $ext) as $searchfile) {
                        @unlink($searchfile);
                    }
                } else {
                    foreach (glob($path . '/*.' . $ext) as $searchfile) {
                        @unlink($searchfile);
                    }
                }
            }

            // put the contents in the file
            if (false === @file_put_contents($cached_file, $collection->dump())) {
                throw new \RuntimeException('Unable to write file ' . $cached_file);
            }
        }

        // return the cached file
        echo 'output: ' . $cached_file . '<br>';
    }
    exit;
    ?>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top