Entries are the fundamental building blocks of your Flextype powered project. Entries are local flat files or external resources that can be represented as a PHP array inside the controllers, templates, etc...

Entries formats

Flextype support several flat files entries formats.

Frontmatter (.md)

[icon name="file-text" set="bootstrap"] project/entries/movies/sg-1/season-5/episode-21/entry.md
---
title: Meridian
description: As Jackson suffers from a fatal dose of radiation, he struggles with the value of his life while his friends deal with the emotional and diplomatic repercussions.
director: William Waring
writers: Brad Wright, Jonathan Glassner
stars: Richard Dean Anderson, Michael Shanks, Amanda Tapping
---
SG-1 returns from an off-world mission to P9Y-3C3 with Daniel Jackson suffering from what is likely a fatal dose of radiation. On the planet, they dealt with the country of Kelowna and their representative Jonas Quinn. That country was at the same stage of development as the United States in the 1940s and well on their way to creating an atomic weapon using Goa'uld technology found in an ancient temple. Daniel argued against the Kelownans developing such a weapon and is accused of attempting to sabotage the project. As members of the team sit by his deathbed, Daniel receives an unexpected offer from someone they once met off-world.

For Frontmatter header you may define custom frontmatter header serializer as yaml, json, json5 or neon by adding serializer name after first ---.

Example:

---json
{
  "title": "Meridian",
  "description": "As Jackson suffers from a fatal dose of radiation, he struggles with the value of his life while his friends deal with the emotional and diplomatic repercussions.",
  "director": "William Waring",
  "writers": "Brad Wright, Jonathan Glassner",
  "stars": "Richard Dean Anderson, Michael Shanks, Amanda Tapping"
}
---
SG-1 returns from an off-world mission to P9Y-3C3 with Daniel Jackson suffering from what is likely a fatal dose of radiation. On the planet, they dealt with the country of Kelowna and their representative Jonas Quinn. That country was at the same stage of development as the United States in the 1940s and well on their way to creating an atomic weapon using Goa'uld technology found in an ancient temple. Daniel argued against the Kelownans developing such a weapon and is accused of attempting to sabotage the project. As members of the team sit by his deathbed, Daniel receives an unexpected offer from someone they once met off-world.

YAML (.yaml)

project/entries/movies/sg-1/season-5/episode-21/entry.yaml
title: Meridian
description: As Jackson suffers from a fatal dose of radiation, he struggles with the value of his life while his friends deal with the emotional and diplomatic repercussions.
director: William Waring
writers: Brad Wright, Jonathan Glassner
stars: Richard Dean Anderson, Michael Shanks, Amanda Tapping
content: |
    SG-1 returns from an off-world mission to P9Y-3C3 with Daniel Jackson suffering from what is likely a fatal dose of radiation. On the planet, they dealt with the country of Kelowna and their representative Jonas Quinn. That country was at the same stage of development as the United States in the 1940s and well on their way to creating an atomic weapon using Goa'uld technology found in an ancient temple. Daniel argued against the Kelownans developing such a weapon and is accused of attempting to sabotage the project. As members of the team sit by his deathbed, Daniel receives an unexpected offer from someone they once met off-world.

NEON (.neon)

project/entries/movies/sg-1/season-5/episode-21/entry.neon
title: "Meridian"
description: "As Jackson suffers from a fatal dose of radiation, he struggles with the value of his life while his friends deal with the emotional and diplomatic repercussions."
director: William Waring
writers: "Brad Wright, Jonathan Glassner"
stars: "Richard Dean Anderson, Michael Shanks, Amanda Tapping"
content: '''
    SG-1 returns from an off-world mission to P9Y-3C3 with Daniel Jackson suffering from what is likely a fatal dose of radiation. On the planet, they dealt with the country of Kelowna and their representative Jonas Quinn. That country was at the same stage of development as the United States in the 1940s and well on their way to creating an atomic weapon using Goa'uld technology found in an ancient temple. Daniel argued against the Kelownans developing such a weapon and is accused of attempting to sabotage the project. As members of the team sit by his deathbed, Daniel receives an unexpected offer from someone they once met off-world.
'''

JSON (.json)

project/entries/movies/sg-1/season-5/episode-21/entry.json
{
  "title": "Meridian",
  "description": "As Jackson suffers from a fatal dose of radiation, he struggles with the value of his life while his friends deal with the emotional and diplomatic repercussions.",
  "director": "William Waring",
  "writers": "Brad Wright, Jonathan Glassner",
  "stars": "Richard Dean Anderson, Michael Shanks, Amanda Tapping",
  "content": "SG-1 returns from an off-world mission to P9Y-3C3 with Daniel Jackson suffering from what is likely a fatal dose of radiation. On the planet, they dealt with the country of Kelowna and their representative Jonas Quinn. That country was at the same stage of development as the United States in the 1940s and well on their way to creating an atomic weapon using Goa'uld technology found in an ancient temple. Daniel argued against the Kelownans developing such a weapon and is accused of attempting to sabotage the project. As members of the team sit by his deathbed, Daniel receives an unexpected offer from someone they once met off-world."
}

JSON5 (.json5)

project/entries/movies/sg-1/season-5/episode-21/entry.json5
{
  title: "Meridian",
  description: "As Jackson suffers from a fatal dose of radiation, he struggles with the value of his life while his friends deal with the emotional and diplomatic repercussions.",
  director: "William Waring",
  writers: "Brad Wright, Jonathan Glassner",
  stars: "Richard Dean Anderson, Michael Shanks, Amanda Tapping",
  content: "SG-1 returns from an off-world mission to P9Y-3C3 with Daniel Jackson suffering from what is likely a fatal dose of radiation. On the planet, they dealt with the country of Kelowna and their representative Jonas Quinn. That country was at the same stage of development as the United States in the 1940s and well on their way to creating an atomic weapon using Goa'uld technology found in an ancient temple. Daniel argued against the Kelownans developing such a weapon and is accused of attempting to sabotage the project. As members of the team sit by his deathbed, Daniel receives an unexpected offer from someone they once met off-world."
}

Entries and Urls structure

All project entries are located in the project/entries folder.

Each entry file should be placed in its idividual folder.

Folder names should also be valid slugs. Slugs are entirely lowercase, with accented characters replaced by letters from the Latin alphabet and whitespace characters replaced by a dash or an underscore to avoid being encoded.

Examples
# Physical Location
project/entries/movies/sg-1/entry.md

# ID
movies/sg-1

# Slug
sg-1
# Physical Location
project/entries/movies/sg-1/season-5/entry.md

# ID
movies/sg-1/season-5

# Slug
season-5
# Physical Location
project/entries/movies/sg-1/season-5/episode-21/entry.md

# ID
movies/sg-1/season-5/episode-21

# Slug
episode-21

Fields

visibility

Entries visibility is about controlling who can see your entries. Flextype allows you to control the visibility of your entries on an individual basis. By default, all entries are visible.

Name Default Available values for option
visibility visible visible, draft or hidden

Example

---
title: My Entry Title
visibility: draft
---
My entry content here.

routable

By default, all entries are routable. This means that they can be reached by pointing your browser to the URL of the entry. However, you may need to create a specific entry to hold specific data, but it is meant to be called directly by a plugin, another entry.

Name Default Available values for option
routable true true or false

Example

---
title: Commment42
routable: false
---
Content for Commment42

published_at

Allows you to specifically set a published_at date associated with this entry.

Name Default Available values for option
published_at Date & Time

Examples

---
title: My Entry Title
published_at: '15-05-2020 06:57'
---
My entry content here.

published_by

Allows you to specifically set a published_by User UUID associated with this entry.

Name Default Available values for option
published_by User UUID

Examples

---
title: My Entry Title
published_by: ea7432a3-b2d5-4b04-b31d-1c5acc7a55e2
---
My entry content here.

created_at

Allows you to specifically set a created_at date associated with this entry.

Name Default Available values for option
created_at Date & Time

modified_at

Allows you to specifically set a modified_at date associated with this entry.

Name Default Available values for option
modified_at Date & Time

Examples

---
title: My Entry Title
modified_at: '15-05-2020 06:57'
---
My entry content here.

cache

By default, all entries are stored in the cache if flextype cache setting is true. But this can be changed by setting individual cache for each entry.

Name Default Available values for option
cache true or false

slug

The field should be in lowercase, with accented characters replaced by letters from the Latin alphabet and whitespace characters replaced by a dash or an underscore, to avoid being encoded.

Name Default Available values for option
slug Entry Slug

id
Name Default Available values for option
id Entry ID

You can define custom fields.

project/entries/home/entry.md
---
title: My Entry Title
description: My entry description
author:
  twitter: "@_flextype"
---
My entry content here, author twitter: ] author.twitter ]

Examples

Get field author.twitter and field content in PHP.

//=> @_flextype
echo entries()->fetch('home')['author.twitter']; 

//=> My entry content here, author twitter: @_flextype
echo entries()->fetch('home')['content'];

Directives

Directive Description
shortcodes Parse shortcodes text inside current field.
markdown Parse markdown text inside current field.
textile Parse textile text inside current field.
php Execute php code inside current field.
type Set current field type.
$[] Evaluate expression.

Directives Details

shortcodes

Parse shortcodes text inside current field.

Examples

---
discount: "@shortcodes (strings random)" 
---
markdown

Parse markdown text inside current field.

Examples

---
text: "@markdown **bold text here**" 
---
textile

Parse textile text inside current field.

Examples

---
text: "@textile **bold text here**" 
---
php

Execute php code inside current field.

Examples

---
text: "@php echo 'Hello World';" 
---
type

Set current field type.

Available types: int, integer, float, bool, boolean, array, json, collection, null and string.

Examples

−−−
_vars: 
    title: "GT Fury"
    currency: "USD"
    vat: '@type[int]  (strings random: "2,1234567890)"'
title: "$[ _vars.title ]"
price: "(calc:'100+$[ _vars.vat ]' )"
price_with_currency: "$[ price ] $[ _vars.currency ]"
−−−
GT Fury content here...
$[ ] @[ ] #[ ]

Evaluate expression.

price: "$[ 100 + var('vat') ]"
message: "$[ field('price') > 100 ? 'Price is greater than 100' : 'Price is less than 100' ]"
content: |
  #[ This is comment ]
  @[ entries().create('movies/sg-1/season-5/episode-23', {}) ]

Macros

entries

Examples

macros:
  entries:
    fetch:
      posts:
        id: blog
        options:
          collection: true
          find: []
          filter: []
      post:
        id: blog/post-1
        options:
          filter: []
      testimonials:
        id: testimonials
registry

Examples

macros:
  registry:
    get:
      flextype:
        id: flextype.manifest.name
      author.name:
        id: flextype.manifest.author.name
      license:
        id: flextype.manifest.license
php

Examples

title: Blog
macros:
  php: |
    $entry = entries()->registry()->get('methods.fetch');
    $entry['result']['posts'] = entries()->fetch('blog', ['collection' => true, 'filter' => ['sort_by' => ['key' => 'date', 'direction' => 'ASC']]])->toArray();
    entries()->registry()->set('methods.fetch', $entry); 

Expressions

Flextype uses Symfony Expression Language Component, which provides an engine that can compile and evaluate expressions.

The purpose of using this component is to allow developers to use expressions inside entries, configurations, etc.. more complex logic than just flat data.

The idea is to let the developers of Flextype powered projects do some business logic inside entries fields without using PHP or introducing security problems.

Expressions can be seen as a very restricted PHP sandbox and are immune to external injections as you must explicitly declare which variables are available in an expression.

Examples

---
vars: 
    title: "GT Fury"
    currency: "USD"
    vat: "@type[int] $[ strings().random(2, 1234567890) ]"
title: "$[ var('title') ]"
price: "$[ 100 + var('vat') ]"
message: "$[ field('price') > 100 ? 'Price is greater than 100' : 'Price is less than 100' ]"
random: "$[ strings().random() ]"
---
### Price
$[ field('price') ]

### Message
$[ field('message') ]

### Random
$[ field('random') ]

Learn more about Symfony Expression Language Component

Functions

Function Description
actions Get actions service.
entries Get entries service.
collection Create a new arrayable collection object from the given elements.
collectionFromJson Create a new arrayable collection object from the given JSON string.
collectionFromString Create a new arrayable collection object from the given string.
collectionWithRange Create a new arrayable object with a range of elements.
collectionFromQueryString Create a new arrayable object from the given query string.
filterCollection Filter collection.
const Get php constant.
var Get entry var.
field Get entry field.
csrf Get csrf hidden input.
filesystem Get filesystem instance.
tr Returns translation of a string. If no translation exists, the original string will be returned. No parameters are replaced.
__ Returns translation of a string. If no translation exists, the original string will be returned. No parameters are replaced.
parsers Get parsers service.
serializers Get serializers service.
slugify Get slugify service.
strings Get strings instance.
registry Get registry service.
urlFor Get the url for a named route.
fullUrlFor Get the full url for a named route.
isCurrentUrl To determine is current url equal to route name.
getCurrentUrl To get current path on given Uri.
getBasePath To get the base path.
getBaseUrl To get the base url.
getAbsoluteUrl To get the absolute url.
getProjectUrl To get the project url.
getUriString To get the uri string.
redirect To create redirect.

Methods

Method Description
fetch Fetch entry or entries collection.
create Create entry
update Update entry
move Move entry
copy Copy entry
delete Delete entry
has Check whether entry exists
getFileLocation Get entry file location
getDirectoryLocation Get entry directory location

Methods Details

fetch

Fetch entry or entries collection.

/**
 * Fetch.
 *
 * @param string $id      Unique identifier of the entry.
 * @param array  $options Options array.
 *
 * @return mixed Returns mixed results from APIs or default is an instance of The Collection class with founded items.
 *
 * @access public
 */
public function fetch(string $id, array $options = [])
Fetch single entry

Examples

Fetch single entry movies/sg-1/season-5/episode-21

$data = entries()->fetch('movies/sg-1/season-5/episode-21');

Fetch singe entry in movies/sg-1/season-5/episode-21 and send $options.

$data = entries()->fetch('movies/sg-1/season-5', $options);

$options is an array of valid values for filter helper.

$options = [
    'filter' => [
        // Return items.
        // Valid values: all, first, last, next, random, shuffle
        'return' => 'all',

        // Filters the array items by a given condition.
        // key - of the array or object to used for comparison.
        // operator - used for comparison.
        //    operators: in, nin, lt, <, lte,
        //         >, gt, gte, >=, contains, ncontains
        //         >=, <=, like, nlike, regexp, nregexp,
        //         eq, =, neq, !=, starts_with,
        //         ends_with, between, nbetween, older, newer
        // value - Value used for comparison.
        'where' => [
            [
                'key' => '',
                'operator' => '',
                'value' => '',
            ],
            [...],
            [...],
        ],

        // Group by key
        'group_by' => '',

        // Sort by key and direction.
        // Order direction: DESC (descending) or ASC (ascending)
        'sort_by' => [
            'key' => '',
            'direction' => 'ASC'
        ],

        // Extract only items.
        'only' => [],

        // Extract except
        'except' => [],

        // Extract a slice of the current array with specific offset.
        'offset' => 0,

        // Extract a slice of the current array with offset 0 and specific length.
        'limit' => 10,
    ],
];
Fetch entries collection

Examples

Fetch collections of entries episodes in movies/sg-1/season-5

$data = entries()->fetch('movies/sg-1/season-5', $options);

Fetch collections of entries in movies/sg-1 and send $options.

$data = entries()->fetch('movies/sg-1/season-5', $options);

$options is an array of valid values for find and filter helpers.

$options = [
    'collection' => true,

    'find' => [
        // Restrict the depth of traversing
        // https://symfony.com/doc/current/components/finder.html#directory-depth
        'depth' => ['> 1', '< 5'],

        // Restrict by a date range
        // https://symfony.com/doc/current/components/finder.html#file-date
        'date' => ['>= 2018-01-01', '<= 2018-12-31'],

        // Restrict by a size range
        // https://symfony.com/doc/current/components/finder.html#file-size
        'size' => ['>= 1K', '<= 2K'],

        // Exclude directories from matching
        // https://symfony.com/doc/current/components/finder.html#location
        'exclude' => 'directory',

        // Find files by content
        // https://symfony.com/doc/current/components/finder.html#file-contents
        'contains' => '',

        // Find files by content excludes files containing given pattern
        // https://symfony.com/doc/current/components/finder.html#file-contents
        'not_contains' => '',

        // Filter results with your own strategy
        // https://symfony.com/doc/current/components/finder.html#custom-filtering
        'filter' => 'CALLBACK_FUNCTION',

        // Sort results by your own sorting algorithm
        // https://symfony.com/doc/current/components/finder.html#sorting-results
        'sort' => 'CALLBACK_FUNCTION',

        // Find files and directories by path
        // https://symfony.com/doc/current/components/finder.html#path
        'path' => 'data',

        // Sort the files and directories by the last accessed, changed or modified time
        // Values: atime, mtime, ctime
        // https://symfony.com/doc/current/components/finder.html#sorting-results
        'sort_by' => 'atime',
    ],

    'filter' => [
        // Return items.
        // Valid values: all, first, last, next, random, shuffle
        'return' => 'all',

        // Filters the array items by a given condition.
        // key - of the array or object to used for comparison.
        // operator - used for comparison.
        //    operators: in, nin, lt, <, lte,
        //         >, gt, gte, >=, contains, ncontains
        //         >=, <=, like, nlike, regexp, nregexp,
        //         eq, =, neq, !=, starts_with,
        //         ends_with, between, nbetween, older, newer
        // value - Value used for comparison.
        'where' => [
            [
                'key' => '',
                'operator' => '',
                'value' => '',
            ],
            [...],
            [...],
        ],

        // Group by key
        'group_by' => '',

        // Sort by key and direction.
        // Order direction: DESC (descending) or ASC (ascending)
        'sort_by' => [
            'key' => '',
            'direction' => 'ASC'
        ],

        // Extract a slice of the current array with specific offset.
        'offset' => 0,

        // Extract a slice of the current array with offset 0 and specific length.
        'limit' => 10,
    ],
];
create

Create entry.

/**
 * Create entry.
 *
 * @param string $id   Unique identifier of the entry.
 * @param array  $data Data to create for the entry.
 *
 * @return bool True on success, false on failure.
 *
 * @access public
 */
public function create(string $id, array $data = []): bool

Examples

Create new entry episode-22 in movies/sg-1/season-5

$data = [
                'title' => 'Revelations',
                'description' => 'While still dealing with the loss of Daniel Jackson the SGC is contacted by the Asgard who require assistance dealing with Anubis, who seems to have new shield technology that can repel Asgard weapons.',
                'director' => 'Martin Wood',
                'writers' => 'Brad Wright, Jonathan Glassner',
                'stars' => 'Richard Dean Anderson, Michael Shanks, Amanda Tapping',
                'content' => 'Osiris engages in space combat with Thor over a violation of the protected planets treaty. Freyr arrives at the SGC bringing news of Thor\'s death and asking SG-1 to mount a rescue mission to retrieve an Asgard scientist from the planet in question. Upon their arrival Heimdall informs them that Thor still lives and has been taken captive by the Goa\'uld. O\'Neill and Teal\'c transport over to the mothership to rescue him from the clutches of Anubis.'
        ];


entries()->create('movies/sg-1/season-5/episode-22', $data);
update

Update entry.

/**
 * Update entry
 *
 * @param string $id   Unique identifier of the entry.
 * @param array  $data Data to update for the entry.
 *
 * @return bool True on success, false on failure.
 *
 * @access public
 */
public function update(string $id, array $data): bool

Examples

Update entry episode-22 in movies/sg-1/season-5

$data = ['soundtracks' => 'Joel Goldsmith'];


entries()->update('movies/sg-1/season-5/episode-22', $data);
move

Move entry.

/**
 * Move entry
 *
 * @param string $id    Unique identifier of the entry.
 * @param string $newID New Unique identifier of the entry.
 *
 * @return bool True on success, false on failure.
 *
 * @access public
 */
public function move(string $id, string $newID): bool

Examples

Move entry episode-22 to episode-23 in movies/sg-1/season-5

entries()->move('movies/sg-1/season-5/episode-22',
                          'movies/sg-1/season-5/episode-23');
copy

Copy entry.

/**
 * Copy entry.
 *
 * @param string $id    Unique identifier of the entry.
 * @param string $newID New Unique identifier of the entry.
 *
 * @return bool|null True on success, false on failure.
 *
 * @access public
 */
public function copy(string $id, string $newID): ?bool

Examples

Copy entry episode-23 to episode-22 in movies/sg-1/season-5

entries()->rename('movies/sg-1/season-5/episode-23',
                                       'movies/sg-1/season-5/episode-22');
delete

Delete entry.

/**
 * Delete entry.
 *
 * @param string $id Unique identifier of the entry.
 *
 * @return bool True on success, false on failure.
 *
 * @access public
 */
public function delete(string $id): bool

Examples

Delete entry episode-23 in movies/sg-1/season-5

entries()->delete('movies/sg-1/season-5/episode-23');
has

Check whether entry exists.

/**
 * Check whether entry exists
 *
 * @param string $id Unique identifier of the entry.
 *
 * @return bool True on success, false on failure.
 *
 * @access public
 */
public function has(string $id): bool

Examples

Check whether entry episode-23 exists in movies/sg-1/season-5

if (entries()->has('movies/sg-1/season-5/episode-23')) {
    // do something...
}
getFileLocation

Get entry file location

/**
 * Get entry file location
 *
 * @param string $id Unique identifier of the entry.
 *
 * @return string entry file location
 *
 * @access public
 */
public function getFileLocation(string $id): string

Examples

Check whether entry episode-23 exists in movies/sg-1/season-5

$data = entries()->getFileLocation('movies/sg-1/season-5/episode-23');
getDirectoryLocation

Get entry directory location

/**
 * Get entry directory location
 *
 * @param string $id Unique identifier of the entry.
 *
 * @return string entry directory location
 *
 * @access public
 */
public function getDirectoryLocation(string $id): string

Examples

Get entry episode-23 exists in movies/sg-1/season-5

$data = entries()->getDirectoryLocation('movies/sg-1/season-5/episode-23');

Extending

Entries are "macroable", which allows you to add additional methods to the Entries API at run time.

For example, the following code adds a fetchRecentPosts() method to the Entries API.

Examples

// Create new macros for fetch recent posts.
entries()::macro('fetchRecentPosts', function($limit = 10) {
    return entries()
                ->fetchCollection('blog')
                ->sortBy('publised_at')
                ->limit($limit);
});

// Display recent posts.
foreach (entries()->fetchRecentPosts(5) as $post) {
    echo $post['title'] . "\n";
}

As you can see, the macro method takes as arguments a name and an anonymous function to call (optionally, you able to add additional arguments, if you need that).

When you call a macro, your code in function would be called from the context of that class (in the example it is Entries API class context), allowing you to execute your code along with Flextype built-in features.

Using mixins

Macros awesome, and you may want to use a lot of them. You may group them with help of mixins. For this approach, you should use a mixin static method on the macroable Entries API class, and pass your mixin class as an argument.

Examples

// Blog Mixin Class.
class BlogMixin {
    public function fetchRecentPosts() {
        return function($limit = 10) {
            return entries()
                        ->fetchCollection('blog')
                        ->sortBy('publised_at')
                        ->limit($limit);
        }
    }
}

// Create new mixin BlogMixin with it is macros.
entries()::mixin(new BlogMixin());

// Display recent posts.
foreach (entries()->fetchRecentPosts(5) as $post) {
    echo $post['title'] . "\n";
}