SlideShare ist ein Scribd-Unternehmen logo
1 von 110
Downloaden Sie, um offline zu lesen
Introducing Assetic
   Asset Management for PHP 5.3




  Kris Wallsmith   February 9, 2011
@kriswallsmith

•   Symfony core team member

•   Doctrine contributor

•   Symfony Guru at

•   10+ years experience with PHP and web development

•   Open source evangelist and international speaker
OpenSky connects you with innovators,
trendsetters and tastemakers.You choose
   the ones you like and each week they
  invite you to their private online sales.
ShopOpenSky.com

•   PHP 5.3 + Symfony2

•   MongoDB + Doctrine MongoDB ODM

•   MySQL + Doctrine2 ORM

•   Less CSS

•   jQuery
Agenda

•   Strawman

•   The code

•   Twig Integration

•   Symfony2 Integration
Symfony2 is FAST
But you can still f*** that up
We build tools that
encourage best practices
Best practices like…
•   Dependency injection (DI)

•   Proper caching, edge side includes (ESI)

•   Test-driven development (TDD)

•   Don't repeat yourself (DRY)

•   Keep it simple, SVP (KISS)

•   Performance
If you haven’t optimized your
frontend, you haven’t optimized
Get your assets in line.
A poorly optimized frontend
     can destroy UX
…and SEO!


http://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html
Asset Management
Lots of awesome tools
•   CoffeeScript              •   LESS

•   Compass Framework         •   Packer

•   CSSEmbed                  •   SASS

•   Google Closure Compiler   •   Sprockets

•   JSMin                     •   YUI Compressor
The ones written in PHP…
This is a difficult problem
Assetic makes it easy
Are you ready to
kick some Assetic!?!
# /path/to/web/js/core.php

$core = new FileAsset('/path/to/jquery.js');
$core->load();

header('Content-Type: text/javascript');
echo $core->dump();
# /path/to/web/js/core.php

$core = new AssetCollection(array(
    new FileAsset('/path/to/jquery.js'),
    new GlobAsset('/path/to/js/core/*.js'),
));
$core->load(); many files into one: fewer HTTP requests
          Merge
header('Content-Type: text/javascript');
echo $core->dump();
# /path/to/web/js/core.php

$core = new AssetCollection(array(
    new FileAsset('/path/to/jquery.js'),
    new GlobAsset('/path/to/js/core/*.js'),
), array(
    new YuiCompressorJsFilter('/path/to/yui.jar'),
));
$core->load();merged asset: less data over the wire
    Compress the

header('Content-Type: text/javascript');
echo $core->dump();
<script src="js/core.php"></script>
Assetic is
Assets & Filters
Inspired by Python’s webassets


        https://github.com/miracle2k/webassets
Assets have lazy, mutable content
Filters act on asset contents during
         “load” and “dump”
Assets can be gathered in
       collections
A collection is an asset
Load
   Filter
   Filter
   Asset




            Dump
Asset Collection
Filter              Filter
Filter              Filter
Asset               Asset
Asset Collection   Filter
                                 Filter
     Asset Collection            Asset
Filter              Filter
Filter              Filter
Asset               Asset
                                 Filter
                                 Filter
                                 Asset
# /path/to/web/css/styles.php

$styles = new AssetCollection(
    array(new FileAsset('/path/to/main.sass')),
    array(new SassFilter())
);

header('Content-Type: text/css');
echo $styles->dump();
# /path/to/web/css/styles.php

$styles = new AssetCollection(array(
    new AssetCollection(
        array(new FileAsset('/path/to/main.sass')),
        array(new SassFilter())
    ),
    new FileAsset('/path/to/more.css'),
));

header('Content-Type: text/css');
echo $styles->dump();
# /path/to/web/css/styles.php

$styles = new AssetCollection(array(
    new AssetCollection(
          array(new FileAsset('/path/to/main.sass')),
          array(new SassFilter())
    ),
    new FileAsset('/path/to/more.css'),
), array(
    new YuiCompressorCss('/path/to/yui.jar'),
));
     Lazy! The filesystem isn't touched until now
header('Content-Type: text/css');
echo $styles->dump();
Basic Asset Classes

•   AssetCollection

•   AssetReference

•   FileAsset

•   GlobAsset

•   StringAsset
Core Filter Classes
•   CallablesFilter                   •   SassSassFilter

•   CoffeeScriptFilter                •   SassScssFilter

•   CssRewriteFilter                  •   SprocketsFilter

•   GoogleClosureCompilerApiFilter   •   YuiCssCompressorFilter

•   GoogleClosureCompilerJarFilter   •   YuiJsCompressorFilter

•   LessFilter                        •   More to come…
Asset Manager
$am = new AssetManager();
$am->set('jquery',
    new FileAsset('/path/to/jquery.js'));
$plugin = new AssetCollection(array(
    new AssetReference($am, 'jquery'),
    new FileAsset('/path/to/jquery.plugin.js'),
));
jQuery will only be included once
       $core = new AssetCollection(array(
           $jquery,
           $plugin1,
           $plugin2,
       ));

       header('text/javascript');
       echo $core->dump();
Filter Manager
$yui = new YuiCompressorJs();
$yui->setNomunge(true);

$fm = new FilterManager();
$fm->set('yui_js', $yui);
jQuery will only be compressed once

   $jquery = new FileAsset('/path/to/core.js');
   $jquery->ensureFilter($fm->get('yui_js'));

   $core = new AssetCollection(array(
       $jquery,
       new GlobAsset('/path/to/js/core/*.js'),
   ));
   $core->ensureFilter($fm->get('yui_js'));
Asset Factory
# /path/to/asset_factory.php

$fm = new FilterManager();
$fm->set('coffee', new CoffeeScriptFilter());
$fm->set('closure', new GoogleClosureCompilerApi());

$factory = new AssetFactory('/path/to/web');
$factory->setAssetManager($am);
$factory->setFilterManager($fm);
include '/path/to/asset_factory.php';

$asset = $factory->createAsset(
    array('js/src/*.coffee'),
    array('coffee', 'closure')
);

header('Content-Type: text/javascript');
echo $asset->dump();
Debug Mode
Debugging compressed
   Javascript sucks
Mark filters for omission
    in debug mode
// new AssetFactory('/path/to/web', true);

include '/path/to/asset_factory.php';

$asset = $factory->createAsset(
    array('js/src/*.coffee'),
    array('coffee', 'closure')
);

header('Content-Type: text/javascript');
echo $asset->dump();
// new AssetFactory('/path/to/web', true);

include '/path/to/asset_factory.php';

$asset = $factory->createAsset(
    array('js/src/*.coffee'),
    array('coffee', '?closure')
);

header('Content-Type: text/javascript');
echo $asset->dump();
// new AssetFactory('/path/to/web', false);

include '/path/to/asset_factory.php';

$asset = $factory->createAsset(
    array('js/src/*.coffee'),
    array('coffee', '?closure'),
    array('debug' => true)
);

header('Content-Type: text/javascript');
echo $asset->dump();
Factory Workers
Everything passes through the
       workers’ hands
$worker = new EnsureFilterWorker(
    '/.css$/',          // the output pattern
    $fm->get('yui_css'), // the filter
    false                // the debug mode
);

$factory = new AssetFactory('/path/to/web');
$factory->addWorker($worker);

// compressed
$factory->createAsset('css/sass/*', 'sass', array(
    'output' => 'css',
));
$worker = new EnsureFilterWorker(
    '/.css$/',          // the output pattern
    $fm->get('yui_css'), // the filter
    false                // the debug mode
);

$factory = new AssetFactory('/path/to/web');
$factory->addWorker($worker);

// uncompressed
$factory->createAsset('css/sass/*', 'sass', array(
    'output' => 'css',
    'debug' => true,
));
Not Lazy Enough?
Asset Formulae and the
 Lazy Asset Manager
$asset = $factory->createAsset(
    array('js/src/*.coffee'),
    array('coffee', '?closure'),
    array('output' => 'js')
);
$formula = array(
    array('js/src/*.coffee'),
    array('coffee', '?closure'),
    array('output' => 'js')
);
$am = new LazyAssetManager($factory);
$am->setFormula('core_js', $formula);

header('Content-Type: text/javascript');
echo $am->get('core_js')->dump();
Good: Basic Caching
# /path/to/web/css/styles.php

$styles = new AssetCollection(
    array(new FileAsset('/path/to/main.sass')),
    array(new SassFilter())
);

echo $styles->dump();
# /path/to/web/css/styles.php

$styles = new AssetCache(new AssetCollection(
    array(new FileAsset('/path/to/main.sass')),
    array(new SassFilter())
), new FilesystemCache('/path/to/cache'));
          Run the filters once and cache the content

echo $styles->dump();
Better: HTTP Caching
# /path/to/web/js/core.php

$mtime = gmdate($core->getLastModified());

if ($mtime == $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
    header('HTTP/1.0 304 Not Modified');
    exit();
}

header('Content-Type: text/javascript');
header('Last-Modified: '.$mtime);
echo $core->dump();
Best: Static Assets
# /path/to/scripts/dump_assets.php

$am = new AssetManager();
$am->set('foo', $foo);
// etc...

$writer = new AssetWriter('/path/to/web');
$writer->writeManagerAssets($am);
# /path/to/scripts/dump_assets.php

$am = new AssetManager();
$am->set('foo', $foo);
// etc...

$writer = new AssetWriter('/path/to/web');
foreach (array_slice($argv, 1) as $name) {
    $writer->writeAsset($am->get($name));
}
Best-est:
Content Distribution Network
new AssetWriter('s3://my-bucket')

                 A CloudFront S3 bucket
Twig Integration
$twig->addExtension(new AsseticExtension($factory));
{% assetic 'js/*.coffee', filter='coffee' %}
<script src="{{ asset_url }}"></script>
{% endassetic %}
<script src="assets/92429d8"></script>
{% assetic 'js/*.coffee', filter='coffee' %}
<script src="{{ asset_url }}"></script>
{% endassetic %}
{% assetic 'js/*.coffee', filter='coffee',
   output='js' %}
<script src="{{ asset_url }}"></script>
{% endassetic %}
<script src="js/92429d8.js"></script>
{% assetic 'js/*.coffee', filter='coffee',
   output='js' %}
<script src="{{ asset_url }}"></script>
{% endassetic %}
{% assetic 'js/*.coffee', filter='coffee,?closure',
   output='js', name='core_js' %}
<script src="{{ asset_url }}"></script>
{% endassetic %}
Formula Loader
Uses the Twig parser to extract asset formulae from templates
$loader = new FormulaLoader($twig);

// loop through your templates
$formulae = array();
foreach ($templates as $template) {
    $formulae += $loader->load($template);
}

$am = new LazyAssetManager($factory);
$am->addFormulae($formulae);
if (!file_exists($cache = '/path/to/formulae.php')) {
    $loader = new FormulaLoader($twig);

    // loop through your templates
    $formulae = array();
    foreach ($templates as $template) {
        $formulae += $loader->load($template);
    }

    file_put_contents($cache,
        '<?php return '.var_export($formulae, true));
}

$am = new LazyAssetManager($factory);
$am->addFormulae(require $cache);
AsseticBundle
{% assetic filter='scss,?yui_css', output='css/all.css',
   '@MainBundle/Resources/sass/main.scss',
   '@AnotherBundle/Resources/sass/more.scss' %}
<link href="{{ asset_url }}" rel="stylesheet" />
{% endassetic %}
<link href="css/all.css" rel="stylesheet" />
{% assetic filter='scss,?yui_css', output='css/all.css',
   '@MainBundle/Resources/sass/main.scss',
   '@AnotherBundle/Resources/sass/more.scss' %}
<link href="{{ asset_url }}" rel="stylesheet" />
{% endassetic %}
{% assetic filter='scss,?yui_css', output='css/all.css',
   '@MainBundle/Resources/sass/main.scss', debug=true,
   '@AnotherBundle/Resources/sass/more.scss' %}
<link href="{{ asset_url }}" rel="stylesheet" />
{% endassetic %}
Each "leaf" asset is referenced individually

<link href="css/all_part1.css" rel="stylesheet" />
<link href="css/all_part2.css" rel="stylesheet" />
Configuration
assetic.config:
    debug:          %kernel.debug%
    use_controller: %kernel.debug%
    document_root: %kernel.root_dir%/../web
{# when use_controller=true #}

<script src="{{ path('route', { 'name': 'core_js' }) }}"...
# routing_dev.yml
_assetic:
    resource: .
    type:     assetic
{# when use_controller=false #}

<script src="{{ asset('js/core.js') }}"></script>

                 Lots for free
The Symfony2 Assets Helper


•   Multiple asset domains

•   Cache buster
app.config:
    templating:
        assets_version: 1.2.3
        assets_base_urls:
            - http://assets1.domain.com
            - http://assets2.domain.com
            - http://assets3.domain.com
            - http://assets4.domain.com
{% assetic filter='scss,?yui_css', output='css/all.css',
   '@MainBundle/Resources/sass/main.scss',
   '@AnotherBundle/Resources/sass/more.scss' %}
<link href="{{ asset_url }}" rel="stylesheet" />
{% endassetic %}
<link href="http://assets3.domain.com/css/all.css?1.2.3" ...
assetic:dump
$ php app/console assetic:dump web/
$ php app/console assetic:dump s3://my-bucket

                 Register a stream wrapper in boot()
PHP templates
   Coming soon…
<?php foreach ($view['assetic']->urls(
    array('@MainBundle/Resources/sass/main.scss',
          '@AnotherBundle/Resources/sass/more.scss'),
    array('scss', '?yui_css'),
    array('output' => 'css/all.css')
) as $url): ?>
    <link href="<?php echo $url ?>" rel="stylesheet" />
<?php endforeach; ?>
Fork me!
http://github.com/kriswallsmith/symfony-sandbox
What’s Next?
•   Finish Symfony2 helpers for PHP templates

•   Filter configuration

•   Image sprites, embedded image data

•   --watch commands

•   Client-aware optimizations?

•   Better CDN integration
Assetic is a killer feature of
        Symfony2…
…but is only one month old,
        so be nice :)
Questions?
Assetic
http://github.com/kriswallsmith/assetic

Weitere ähnliche Inhalte

Was ist angesagt?

Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Arc & Codementor
 
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017Ryan Weaver
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
深入淺出 MVC
深入淺出 MVC深入淺出 MVC
深入淺出 MVCJace Ju
 
HTML5 JavaScript APIs
HTML5 JavaScript APIsHTML5 JavaScript APIs
HTML5 JavaScript APIsRemy Sharp
 
(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014
(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014
(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014Amazon Web Services
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress DevelopmentAdam Tomat
 
Childthemes ottawa-word camp-1919
Childthemes ottawa-word camp-1919Childthemes ottawa-word camp-1919
Childthemes ottawa-word camp-1919Paul Bearne
 
Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)Jacob Kaplan-Moss
 
Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3makoto tsuyuki
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
 

Was ist angesagt? (20)

Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
 
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
The Coolest Symfony Components you’ve never heard of - DrupalCon 2017
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
WebGUI Developers Workshop
WebGUI Developers WorkshopWebGUI Developers Workshop
WebGUI Developers Workshop
 
深入淺出 MVC
深入淺出 MVC深入淺出 MVC
深入淺出 MVC
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
HTML5 JavaScript APIs
HTML5 JavaScript APIsHTML5 JavaScript APIs
HTML5 JavaScript APIs
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014
(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014
(DEV305) Building Apps with the AWS SDK for PHP | AWS re:Invent 2014
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Symfony 2
Symfony 2Symfony 2
Symfony 2
 
CodeIgniter 3.0
CodeIgniter 3.0CodeIgniter 3.0
CodeIgniter 3.0
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
 
Childthemes ottawa-word camp-1919
Childthemes ottawa-word camp-1919Childthemes ottawa-word camp-1919
Childthemes ottawa-word camp-1919
 
Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)
 
Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3
 
WCLV13 JavaScript
WCLV13 JavaScriptWCLV13 JavaScript
WCLV13 JavaScript
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
 

Ähnlich wie Introducing Assetic: Asset Management for PHP 5.3

Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Kris Wallsmith
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVCAlive Kuo
 
Build Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBuild Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBob Paulin
 
eZ Publish Cluster Unleashed
eZ Publish Cluster UnleashedeZ Publish Cluster Unleashed
eZ Publish Cluster UnleashedBertrand Dunogier
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejsNick Lee
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)Doris Chen
 
Styling components with JavaScript
Styling components with JavaScriptStyling components with JavaScript
Styling components with JavaScriptbensmithett
 
以Vue開發電子商務網站
架構與眉角
以Vue開發電子商務網站
架構與眉角以Vue開發電子商務網站
架構與眉角
以Vue開發電子商務網站
架構與眉角Mei-yu Chen
 
Laying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme developmentLaying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme developmentTammy Hart
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolGordon Forsythe
 
Express Presentation
Express PresentationExpress Presentation
Express Presentationaaronheckmann
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Intro to php
Intro to phpIntro to php
Intro to phpSp Singh
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareAlona Mekhovova
 
Workshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastWorkshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastMichelangelo van Dam
 

Ähnlich wie Introducing Assetic: Asset Management for PHP 5.3 (20)

Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
Build Your Own CMS with Apache Sling
Build Your Own CMS with Apache SlingBuild Your Own CMS with Apache Sling
Build Your Own CMS with Apache Sling
 
eZ Publish Cluster Unleashed
eZ Publish Cluster UnleashedeZ Publish Cluster Unleashed
eZ Publish Cluster Unleashed
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
jQuery Makes Writing JavaScript Fun Again (for HTML5 User Group)
 
Styling components with JavaScript
Styling components with JavaScriptStyling components with JavaScript
Styling components with JavaScript
 
以Vue開發電子商務網站
架構與眉角
以Vue開發電子商務網站
架構與眉角以Vue開發電子商務網站
架構與眉角
以Vue開發電子商務網站
架構與眉角
 
Laying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme developmentLaying the proper foundation for plugin and theme development
Laying the proper foundation for plugin and theme development
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
Express Presentation
Express PresentationExpress Presentation
Express Presentation
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Intro to php
Intro to phpIntro to php
Intro to php
 
Fatc
FatcFatc
Fatc
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
Php frameworks
Php frameworksPhp frameworks
Php frameworks
 
Workshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastWorkshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfast
 

Mehr von Kris Wallsmith

How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonKris Wallsmith
 
Love and Loss: A Symfony Security Play
Love and Loss: A Symfony Security PlayLove and Loss: A Symfony Security Play
Love and Loss: A Symfony Security PlayKris Wallsmith
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Kris Wallsmith
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony TechniquesKris Wallsmith
 
A Practical Introduction to Symfony2
A Practical Introduction to Symfony2A Practical Introduction to Symfony2
A Practical Introduction to Symfony2Kris Wallsmith
 

Mehr von Kris Wallsmith (10)

Matters of State
Matters of StateMatters of State
Matters of State
 
The View From Inside
The View From InsideThe View From Inside
The View From Inside
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
 
Drupal, meet Assetic
Drupal, meet AsseticDrupal, meet Assetic
Drupal, meet Assetic
 
Love and Loss: A Symfony Security Play
Love and Loss: A Symfony Security PlayLove and Loss: A Symfony Security Play
Love and Loss: A Symfony Security Play
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
A Practical Introduction to Symfony2
A Practical Introduction to Symfony2A Practical Introduction to Symfony2
A Practical Introduction to Symfony2
 
Symfony in the Cloud
Symfony in the CloudSymfony in the Cloud
Symfony in the Cloud
 

Kürzlich hochgeladen

Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentMahmoud Rabie
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialJoão Esperancinha
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Nikki Chapple
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...Karmanjay Verma
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...itnewsafrica
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 

Kürzlich hochgeladen (20)

Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career Development
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorial
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 

Introducing Assetic: Asset Management for PHP 5.3