$30 off During Our Annual Pro Sale. View Details »

Symfony CMF - A Decoupled Content Management Framework

Symfony CMF - A Decoupled Content Management Framework

Talk given at the 010PHP user group in Rotterdam

Willem-Jan Zijderveld

November 14, 2013
Tweet

More Decks by Willem-Jan Zijderveld

Other Decks in Programming

Transcript

  1. A decoupled Content Management Framework
    14 november - 010PHP

    View Slide

  2. Willem-Jan Zijderveld
    Developer at Beeldspraak
    @willemjanz
    github.com/wjzijderveld
    blog.willem-jan.net

    View Slide

  3. In this talk
    What is Symfony CMF
    Under the hood: PHPCR
    The components
    What's brewing

    View Slide

  4. What is Symfony CMF
    Toolbox
    Aimed at developers
    Set of bundles
    Scalability
    Usability
    Documentation
    Testing
    Community Driven

    View Slide

  5. Under the hood: PHPCR

    View Slide

  6. PHP Content Repository
    Proven technique
    Defines a interface
    Decouple the storage from you application
    Lots of features

    View Slide

  7. PHPCR
    Interface any PHP content management application with any
    content repository

    View Slide

  8. PHPCR
    Write applications once, switch storage backends when
    needed

    View Slide

  9. PHPCR: Quick overview
    Store content in a tree of nodes
    Each node has a name and a type
    Nodes can have children
    Nodes can have properties with values
    A value can be almost anything

    View Slide

  10. Best of both worlds
    RDBMS
    Transactions
    Query
    Structure
    Integrity
    Filesystem
    Binary
    Hierarchy
    Locking
    Access Control
    And more
    Unstructured
    Versioning
    Full-Text
    Multi-value

    View Slide

  11. Example
    <
    j
    c
    r
    :
    r
    o
    o
    t
    >
    <
    c
    m
    s
    >
    <
    p
    a
    g
    e
    s
    >
    <
    h
    o
    m
    e t
    i
    t
    l
    e
    =
    "
    H
    o
    m
    e
    p
    a
    g
    e
    "
    >
    <
    b
    l
    o
    c
    k
    t
    i
    t
    l
    e
    =
    "
    N
    e
    w
    s
    "
    c
    o
    n
    t
    e
    n
    t
    =
    "
    T
    o
    d
    a
    y
    : S
    y
    m
    f
    o
    n
    y C
    M
    F p
    r
    e
    s
    e
    n
    t
    a
    t
    i
    o
    n
    "
    /
    >
    <
    /
    h
    o
    m
    e
    >
    <
    c
    o
    n
    t
    a
    c
    t
    t
    i
    t
    l
    e
    =
    "
    C
    o
    n
    t
    a
    c
    t
    "
    c
    o
    n
    t
    e
    n
    t
    =
    "
    s
    y
    m
    f
    o
    n
    y
    -
    c
    m
    f
    -
    d
    e
    v
    s
    @
    g
    o
    o
    g
    l
    e
    g
    r
    o
    u
    p
    s
    .
    c
    o
    m
    "
    /
    >
    <
    /
    p
    a
    g
    e
    s
    >
    <
    /
    c
    m
    s
    >
    <
    /
    j
    c
    r
    :
    r
    o
    o
    t
    >
    Node home
    Path: /cms/pages/home
    Parent: /cms/pages
    Name: home

    View Slide

  12. Doctrine PHPCR ODM
    Object to Document mapper
    Persist your objects as PHPCR nodes

    View Slide

  13. I thought this talk was about
    Symfony CMF?

    View Slide

  14. The components
    CoreBundle
    Routing + RoutingBundle
    ContentBundle
    BlockBundle
    CreateBundle
    MediaBundle
    MenuBundle

    View Slide

  15. CoreBundle
    Publish Workflow
    Templating
    Multi-language support
    More...

    View Slide

  16. CoreBunde
    Publish Workflow
    Implement your publication workflow
    Uses Symfony Security Component with Access Voters

    View Slide

  17. Article.php
    MyController.php
    <
    ?
    p
    h
    p
    c
    l
    a
    s
    s A
    r
    t
    i
    c
    l
    e i
    m
    p
    l
    e
    m
    e
    n
    t
    s P
    u
    b
    l
    i
    s
    h
    a
    b
    l
    e
    I
    n
    t
    e
    r
    f
    a
    c
    e
    , P
    u
    b
    l
    i
    s
    h
    T
    i
    m
    e
    P
    e
    r
    i
    o
    d
    I
    n
    t
    e
    r
    f
    a
    c
    e
    {
    /
    *
    * @
    v
    a
    r \
    D
    a
    t
    e
    T
    i
    m
    e *
    /
    p
    r
    i
    v
    a
    t
    e $
    i
    s
    P
    u
    b
    l
    i
    s
    h
    a
    b
    l
    e
    ;
    p
    u
    b
    l
    i
    c f
    u
    n
    c
    t
    i
    o
    n i
    s
    P
    u
    b
    l
    i
    s
    h
    a
    b
    l
    e
    (
    ) {
    r
    e
    t
    u
    r
    n $
    t
    h
    i
    s
    -
    >
    i
    s
    P
    u
    b
    l
    i
    s
    h
    a
    b
    l
    e
    ;
    }
    }
    <
    ?
    p
    h
    p
    /
    / c
    h
    e
    c
    k i
    f c
    u
    r
    r
    e
    n
    t u
    s
    e
    r i
    s a
    l
    l
    o
    w
    e
    d t
    o s
    e
    e t
    h
    i
    s d
    o
    c
    u
    m
    e
    n
    t
    $
    p
    w
    c = $
    c
    o
    n
    t
    a
    i
    n
    e
    r
    -
    >
    g
    e
    t
    (
    '
    c
    m
    f
    _
    c
    o
    r
    e
    .
    p
    u
    b
    l
    i
    s
    h
    _
    w
    o
    r
    k
    f
    l
    o
    w
    .
    c
    h
    e
    c
    k
    e
    r
    '
    )
    ;
    i
    f (
    !
    $
    p
    w
    c
    -
    >
    i
    s
    G
    r
    a
    n
    t
    e
    d
    (
    P
    u
    b
    l
    i
    s
    h
    W
    o
    r
    k
    f
    l
    o
    w
    C
    h
    e
    c
    k
    e
    r
    :
    :
    V
    I
    E
    W
    _
    A
    T
    T
    R
    I
    B
    U
    T
    E
    ,
    $
    d
    o
    c
    u
    m
    e
    n
    t
    )
    ) { /
    / f
    .
    e
    . r
    e
    d
    i
    r
    e
    c
    t t
    o 4
    0
    4 }
    Most of the time, this is handled by the RequestListener

    View Slide

  18. CoreBundle
    Templating
    Provides some basic helpers
    cmf_is_published
    cmf_children
    cmf_next/cmf_prev
    ...

    View Slide

  19. CoreBundle
    Templating
    {
    % f
    o
    r n
    e
    w
    s
    I
    t
    e
    m i
    n c
    m
    f
    _
    c
    h
    i
    l
    d
    r
    e
    n
    (
    p
    a
    g
    e
    )
    |
    r
    e
    v
    e
    r
    s
    e %
    }
    <
    l
    i
    >
    <
    a h
    r
    e
    f
    =
    "
    {
    { p
    a
    t
    h
    (
    n
    e
    w
    s
    I
    t
    e
    m
    ) }
    }
    "
    >
    {
    { n
    e
    w
    s
    I
    t
    e
    m
    .
    t
    i
    t
    l
    e }
    }
    <
    /
    a
    >
    (
    {
    { n
    e
    w
    s
    I
    t
    e
    m
    .
    p
    u
    b
    l
    i
    s
    h
    S
    t
    a
    r
    t
    D
    a
    t
    e | d
    a
    t
    e
    (
    '
    Y
    -
    m
    -
    d
    '
    ) }
    }
    )
    <
    /
    l
    i
    >
    {
    % e
    n
    d
    f
    o
    r %
    }

    View Slide

  20. CoreBundle
    Multi-language support
    Configuration for all Bundles
    TranslatableInterface

    View Slide

  21. Routing + RoutingBundle
    Extends Symfony Routing Component
    Introduces ChainRouter
    Has the possibility to load routes from the database
    Bundle simply integrates the component

    View Slide

  22. ChainRouter
    Add prioritized routers
    Stops on first match
    Can use the full Request

    View Slide

  23. Dynamic Router
    Lookup routes in your database
    Generate URLs based on path or object

    View Slide

  24. Enhance your routes
    RouteContentEnhancer
    FieldMapEnchancer
    FieldByClassEnhancer
    FieldPresenceEnhancer

    View Slide

  25. RouteContentEnhancer
    When the found route is an instance of RouteObjectInterface
    <
    ?
    p
    h
    p c
    l
    a
    s
    s R
    o
    u
    t
    e i
    m
    p
    l
    e
    m
    e
    n
    t
    s R
    o
    u
    t
    e
    O
    b
    j
    e
    c
    t
    I
    n
    t
    e
    r
    f
    a
    c
    e {
    }
    Set's the contentDocument in the route
    <
    ?
    p
    h
    p $
    r
    o
    u
    t
    e
    -
    >
    g
    e
    t
    C
    o
    n
    t
    e
    n
    t
    (
    )
    ; ?
    >

    View Slide

  26. FieldMapEnhancer
    Sets a value in the route, based on a hashmap
    <
    ?
    p
    h
    p
    u
    s
    e S
    y
    m
    f
    o
    n
    y
    \
    C
    m
    f
    \
    C
    o
    m
    p
    o
    n
    e
    n
    t
    \
    R
    o
    u
    t
    i
    n
    g
    \
    E
    n
    h
    a
    n
    c
    e
    r
    \
    F
    i
    e
    l
    d
    M
    a
    p
    E
    n
    h
    a
    n
    c
    e
    r
    ;
    $
    h
    a
    s
    h
    M
    a
    p = a
    r
    r
    a
    y
    (
    '
    f
    o
    o
    ' =
    > '
    0
    1
    0
    P
    H
    P
    '
    )
    ;
    $
    e
    n
    h
    a
    n
    c
    e
    r = n
    e
    w F
    i
    e
    l
    d
    M
    a
    p
    E
    n
    h
    a
    n
    c
    e
    r
    (
    '
    b
    a
    r
    '
    , '
    t
    i
    t
    l
    e
    '
    , $
    h
    a
    s
    h
    M
    a
    p
    )
    ;
    Imagine a Route, that has a property bar with value foo
    After the enhancer is applied, the route will also have a property
    title with value 010PHP

    View Slide

  27. FieldByClassEnhancer
    Looks like FieldMap enhancer
    Checks with instanceOf instead of comparing value
    Used to set a controller based on Document

    View Slide

  28. FieldPresenceEnhancer
    Simply set's a value when a field is present
    Can also be used to set a default value
    Is used to set the default Controller

    View Slide

  29. ContentBundle
    Default Document
    Default Controller
    References routes
    References menu nodes

    View Slide

  30. BlockBundle
    Create and use blocks of content in your website.
    Makes perfect sense as childnodes in your Content Repository

    View Slide

  31. BlockBundle
    Common behaviour
    Aimed at PHPCR
    Settings
    Implements PublishableInterface
    Support Multi-language

    View Slide

  32. BlockBundle
    Available types
    StringBlock
    SimpleBlock
    ContainerBlock
    ReferenceBlock
    ActionBlock
    RssBlock
    ImagineBlock
    SlideshowBlock
    Very easy to create your own block

    View Slide

  33. BlockBundle
    Template usage
    {
    { s
    o
    n
    a
    t
    a
    _
    b
    l
    o
    c
    k
    _
    r
    e
    n
    d
    e
    r
    (
    {
    '
    n
    a
    m
    e
    '
    : '
    p
    r
    e
    s
    e
    n
    t
    a
    t
    i
    o
    n
    B
    l
    o
    c
    k
    '
    }
    ) }
    }

    View Slide

  34. CreateBundle
    Integrates CreateJS and CreatePHP into Symfony2
    Uses RDFa meta-data (like Doctrine's mapping)
    Support for CKEditor and Hallo.js
    Twig example
    {
    % c
    r
    e
    a
    t
    e
    p
    h
    p p
    a
    g
    e a
    s
    =
    "
    r
    d
    f
    " n
    o
    a
    u
    t
    o
    t
    a
    g %
    }
    <
    d
    i
    v {
    { c
    r
    e
    a
    t
    e
    p
    h
    p
    _
    a
    t
    t
    r
    i
    b
    u
    t
    e
    s
    (
    r
    d
    f
    ) }
    }
    >
    <
    h
    1 c
    l
    a
    s
    s
    =
    "
    m
    y
    -
    t
    i
    t
    l
    e
    " {
    { c
    r
    e
    a
    t
    e
    p
    h
    p
    _
    a
    t
    t
    r
    i
    b
    u
    t
    e
    s
    ( r
    d
    f
    .
    t
    i
    t
    l
    e ) }
    }
    >
    {
    { c
    r
    e
    a
    t
    e
    p
    h
    p
    _
    c
    o
    n
    t
    e
    n
    t
    ( r
    d
    f
    .
    t
    i
    t
    l
    e ) }
    }
    <
    /
    h
    1
    >
    <
    d
    i
    v {
    { c
    r
    e
    a
    t
    e
    p
    h
    p
    _
    a
    t
    t
    r
    i
    b
    u
    t
    e
    s
    ( r
    d
    f
    .
    b
    o
    d
    y ) }
    }
    >
    {
    { c
    r
    e
    a
    t
    e
    p
    h
    p
    _
    c
    o
    n
    t
    e
    n
    t
    ( r
    d
    f
    .
    b
    o
    d
    y ) }
    }
    <
    /
    d
    i
    v
    >
    <
    /
    d
    i
    v
    >
    {
    % e
    n
    d
    c
    r
    e
    a
    t
    e
    p
    h
    p %
    }

    View Slide

  35. MediaBundle
    Basic documents
    Controllers for showing and downloading
    Helper for uploading
    Adapters for 3rd-party integration
    LiipImagine
    elFinder
    Gaufrette

    View Slide

  36. MenuBundle
    Integrates KnpMenu into Symfony CMF
    Can point to content or a route

    View Slide

  37. MenuBundle
    {
    { k
    n
    p
    _
    m
    e
    n
    u
    _
    r
    e
    n
    d
    e
    r
    (
    '
    m
    a
    i
    n
    -
    m
    e
    n
    u
    '
    ) }
    }
    Simple isn't it?

    View Slide

  38. Even more Bundles
    CmfTreeBrowserBundle
    CmfBlogBundle
    CmfSearchBundle
    CmfSimpleCms
    LuneticsLocaleBundle
    SonataDoctrinePhpcrAdminBundle
    ...

    View Slide

  39. What's brewing?

    View Slide

  40. 1.0 has been released!
    1.1 scheduled a month after Symfony 2.4
    So somewhere in December

    View Slide

  41. Release cycle

    View Slide

  42. Who is using it?

    View Slide

  43. Contribute!

    View Slide

  44. 7 / 44
    Questions?
    Freenode: #symfony-cmf
    http://cmf.symfony.com
    [email protected]

    View Slide