diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 2f20b5b4..067d5e8f 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -8,8 +8,7 @@ jobs: matrix: # operating-systems: ubuntu-latest, windows-latest, macos-latest operating-system: [ubuntu-latest] - # php-versions: 8.0, 8.1, 8.2 - php-versions: ['8.0', '8.1', '8.2'] + php-versions: ['8.0', '8.1', '8.2', '8.3'] runs-on: ${{ matrix.operating-system }} steps: - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index c68c6185..7548f7c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [2.1.0] - 2025-04-13 + +### Added +- Support for PHP 8.3 +- Support for Docker and Docker Compose + +### Fixed +- Failed WebsiteCest + +## [2.0.0] - 2023-01-02 + +See https://github.com/getherbie/herbie/issues/82. + ## [1.1.0] - 2018-10-27 - Remove Composer minimum-stability - Bump php version requirement to 5.6 @@ -31,6 +44,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -[Unreleased]: https://github.com/getherbie/herbie/compare/v1.0.1...HEAD +[Unreleased]: https://github.com/getherbie/herbie/compare/v2.1.0...HEAD +[2.1.0]: https://github.com/getherbie/herbie/compare/v2.0.0...v2.1.0 +[2.0.0]: https://github.com/getherbie/herbie/compare/v1.1.0...v2.0.0 +[1.1.0]: https://github.com/getherbie/herbie/compare/v1.0.1...v1.1.0 [1.0.1]: https://github.com/getherbie/herbie/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/getherbie/herbie/compare/v0.5.0...v1.0.0 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..30229641 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +ARG PHP_VERSION=8.3 + +FROM composer:lts AS composer + +FROM php:$PHP_VERSION-cli + +WORKDIR /app +VOLUME /app + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + git \ + libicu-dev \ + libfreetype-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +RUN docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j$(nproc) gd intl + +RUN pecl channel-update pecl.php.net \ + && pecl install xdebug \ + && docker-php-ext-enable xdebug + +RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" + +COPY --from=composer /usr/bin/composer /usr/bin/composer + +EXPOSE 80 diff --git a/README.md b/README.md index 8e6e320b..ad5ba85c 100644 --- a/README.md +++ b/README.md @@ -42,36 +42,51 @@ Herbie is well tested: - Unit, Integration and Acceptance Tests with [Codeception](https://codeception.com) - Static Code Analysis with [PHPStan](https://phpstan.org) -- Code Fixing with [PHP Coding Standards Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) +- Code Fixing with [PHP Coding Standards Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) -## Use Cases +## Supported PHP Versions -TBD +8.0 / 8.1 / 8.2 / 8.3 ## Installation -### Composer +### With PHP and Composer on your machine The easiest way to install Herbie is through Composer. Run the following commands in your terminal to create a new project and install all dependent libraries. composer create-project getherbie/start-website mywebsite -Change to the `mywebsite/web` directory: +Change to the `mywebsite/web` directory. cd mywebsite/web -Start the internal webserver: +Start the built-in webserver. php -S localhost:8888 index.php -Now open with your browser. +Open with your browser. You should see your first Herbie website. +### With Docker and Docker Compose on your machine + +Create website and install dependencies. + + docker run --rm -v $PWD:/app composer create-project --ignore-platform-reqs getherbie/start-website mywebsite + +Change to the `mywebsite` directory and start website. + + cd mywebsite + docker compose up website + +Open with your browser. + ## Development Environment If you need a development environment, you can follow these steps. +### With PHP and Composer on your machine + Clone the GitHub repository. git clone https://github.com/getherbie/herbie.git @@ -90,40 +105,97 @@ Change to the `website/web` directory. Start PHP's internal web server. - php -S localhost:9999 index.php + php -S localhost:8888 index.php -Now, open `localhost:9999` with your favorite web browser. +Open `localhost:8888` with your favorite web browser. If you want to have additional console output or logging information, set the debug environment variable. - HERBIE_DEBUG=1 php -S localhost:9999 index.php + HERBIE_DEBUG=1 php -S localhost:8888 index.php If you want to use Xdebug (3.x), start the internal web server as follows. Hint: For this to work, Xdebug must of course be installed. - XDEBUG_MODE=debug php -S localhost:9999 index.php + XDEBUG_MODE=debug php -S localhost:8888 index.php + +### With Docker and Docker Compose on your machine + +Clone the GitHub repository. + + git clone https://github.com/getherbie/herbie.git + +Change to the `herbie` directory. + + cd herbie + +Start PHP's built-in web server and launch website. + + docker compose up website + +Open `localhost:8888` with your favorite web browser. + +Other Docker Compose commands are + + # install Composer dependencies + docker compose run install + + # run test suite + docker compose run test + + # start test suite website + docker compose up test-website + + # run bash terminal + docker compose run bash + +You can use different PHP versions. + + PHP_VERSION=8.0 docker compose up website + PHP_VERSION=8.1 docker compose up website + PHP_VERSION=8.2 docker compose up website + PHP_VERSION=8.3 docker compose up website ## Tests -Run unit tests +### With PHP on your machine - php vendor/bin/codecept run unit + # run tests + php vendor/bin/codecept run -Run integration tests + # run unit tests + php vendor/bin/codecept run unit + # run integration tests php vendor/bin/codecept run integration -Run acceptance tests - + # run acceptance tests php vendor/bin/codecept run acceptance -Run all tests + # run tests with Code Coverage + XDEBUG_MODE=coverage php vendor/bin/codecept run --coverage --coverage-xml --coverage-html + +### With Docker Compose on your machine + +Open the container shell + + docker compose run bash + +Run tests within the container + # run tests php vendor/bin/codecept run -Run tests with Code Coverage + # run unit tests + php vendor/bin/codecept run unit + + # run integration tests + php vendor/bin/codecept run integration + + # run acceptance tests + php vendor/bin/codecept run acceptance - XDEBUG_MODE=coverage vendor/bin/codecept run --coverage --coverage-xml --coverage-html + # run tests with Code Coverage + XDEBUG_MODE=coverage php vendor/bin/codecept run --coverage --coverage-xml --coverage-html ## More Information diff --git a/compose.yml b/compose.yml new file mode 100644 index 00000000..1078ea2f --- /dev/null +++ b/compose.yml @@ -0,0 +1,60 @@ +services: + website: + build: + context: . + args: + - PHP_VERSION=${PHP_VERSION:-8.3} + profiles: [website] + environment: + - XDEBUG_MODE=debug + - XDEBUG_CONFIG="client_host=host.docker.internal" + working_dir: "/app/website" + command: ["php", "-S", "0.0.0.0:80", "-t", "/app/website/web"] + volumes: + - .:/app + ports: + - "8888:80" + depends_on: + - install + install: + build: + context: . + args: + - PHP_VERSION=${PHP_VERSION:-8.3} + profiles: [website] + working_dir: "/app" + command: ["composer", "install"] + volumes: + - .:/app + test: + build: + context: . + args: + - PHP_VERSION=${PHP_VERSION:-8.3} + profiles: [website] + working_dir: "/app" + command: ["php", "vendor/bin/codecept", "run"] + volumes: + - .:/app + test-website: + build: + context: . + args: + - PHP_VERSION=${PHP_VERSION:-8.3} + profiles: [website] + working_dir: "/app/tests/_data" + command: ["php", "-S", "0.0.0.0:80", "-t", "/app/tests/_data/web"] + volumes: + - .:/app + ports: + - "8888:80" + bash: + build: + context: . + args: + - PHP_VERSION=${PHP_VERSION:-8.3} + profiles: [website] + working_dir: "/app" + command: ["bash"] + volumes: + - .:/app diff --git a/composer.json b/composer.json index 05720178..f7f8f55a 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "getherbie/plugin-simplecontact": "dev-master", "getherbie/plugin-simplesearch": "dev-master", "guzzlehttp/psr7": "^2.4", - "laminas/laminas-diactoros": "^2.24", + "laminas/laminas-diactoros": "^2.26 || ^3.5", "netcarver/textile": "^4.0", "nyholm/psr7": "^1.5", "nyholm/psr7-server": "^1.0", diff --git a/composer.lock b/composer.lock index 57afc905..f1045fd1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "189b44a72c363849f1b2946ff37c35bb", + "content-hash": "e8f2615113d0d6ce418ba847254015b1", "packages": [ { "name": "ausi/slug-generator", @@ -3383,20 +3383,20 @@ }, { "name": "laminas/laminas-diactoros", - "version": "2.25.2", + "version": "2.26.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "9f3f4bf5b99c9538b6f1dbcc20f6fec357914f9e" + "reference": "6584d44eb8e477e89d453313b858daac6183cddc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/9f3f4bf5b99c9538b6f1dbcc20f6fec357914f9e", - "reference": "9f3f4bf5b99c9538b6f1dbcc20f6fec357914f9e", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/6584d44eb8e477e89d453313b858daac6183cddc", + "reference": "6584d44eb8e477e89d453313b858daac6183cddc", "shasum": "" }, "require": { - "php": "~8.0.0 || ~8.1.0 || ~8.2.0", + "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.1" }, @@ -3422,8 +3422,8 @@ "type": "library", "extra": { "laminas": { - "config-provider": "Laminas\\Diactoros\\ConfigProvider", - "module": "Laminas\\Diactoros" + "module": "Laminas\\Diactoros", + "config-provider": "Laminas\\Diactoros\\ConfigProvider" } }, "autoload": { @@ -3476,7 +3476,7 @@ "type": "community_bridge" } ], - "time": "2023-04-17T15:44:17+00:00" + "time": "2023-10-29T16:17:44+00:00" }, { "name": "myclabs/deep-copy", @@ -4493,20 +4493,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -4530,7 +4530,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -4542,9 +4542,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "ralouphie/getallheaders", @@ -6546,5 +6546,5 @@ "composer-runtime-api": "^2.0" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/tests/website/WebsiteCest.php b/tests/website/WebsiteCest.php index c0873137..554c8a87 100644 --- a/tests/website/WebsiteCest.php +++ b/tests/website/WebsiteCest.php @@ -41,8 +41,8 @@ public function testDocFirstSteps(AcceptanceTester $I) // if we see this, redirect was successful $I->see('Quickstart', 'h1'); $I->dontSee('On this page', '.toc-title'); - $I->seeNumberOfElements('.content>p', 6); - $I->seeNumberOfElements('.content>pre', 1); + $I->seeNumberOfElements('.content>p', 8); + $I->seeNumberOfElements('.content>pre', 2); } public function testDocFirstStepsInstallation(AcceptanceTester $I) @@ -52,9 +52,9 @@ public function testDocFirstStepsInstallation(AcceptanceTester $I) $I->seeResponseCodeIs(HttpCode::OK); $I->see('Installation', 'h1'); $I->see('On this page', '.toc-title'); - $I->seeNumberOfElements('.content>h2', 2); - $I->seeNumberOfElements('.content>p', 6); - $I->seeNumberOfElements('.content>pre', 3); + $I->seeNumberOfElements('.content>h2', 3); + $I->seeNumberOfElements('.content>p', 9); + $I->seeNumberOfElements('.content>pre', 5); } public function testDocFirstStepsConfiguration(AcceptanceTester $I) @@ -202,7 +202,7 @@ public function testDocIndepthQueryBuilder(AcceptanceTester $I) $I->see('Query Builder', 'h1'); $I->see('On this page', '.toc-title'); $I->seeNumberOfElements('.content>h2', 7); - $I->seeNumberOfElements('.content>p', 30); + $I->seeNumberOfElements('.content>p', 31); $I->seeNumberOfElements('.content>pre', 20); $I->seeNumberOfElements('.content>table', 1); } diff --git a/website/site/pages/1-index.md b/website/site/pages/1-index.md index f4b1248a..2e06a6d4 100644 --- a/website/site/pages/1-index.md +++ b/website/site/pages/1-index.md @@ -13,6 +13,10 @@ title: Homepage Herbie is a simple, modern, fast and highly customizable flat-file Content Management System (CMS) powered by PHP, Twig, Markdown, Textile, reStructuredText and other human-readable text files. +## Supported PHP Versions + +8.0 / 8.1 / 8.2 /8.3 + ## Featuring Herbie is powered by proven libraries: diff --git a/website/site/pages/2-doc/2-first-steps/2-quickstart.md b/website/site/pages/2-doc/2-first-steps/2-quickstart.md index 0ed3a79d..a33d51f7 100644 --- a/website/site/pages/2-doc/2-first-steps/2-quickstart.md +++ b/website/site/pages/2-doc/2-first-steps/2-quickstart.md @@ -7,10 +7,18 @@ layout: doc Here is the short version of how to install a simple Herbie website using a website template. +With PHP and Composer: + composer create-project getherbie/start-website mywebsite cd mywebsite/web php -S localhost:8888 index.php +With Docker and Docker Compose: + + docker run --rm -v $PWD:/app composer create-project --ignore-platform-reqs getherbie/start-website mywebsite + cd mywebsite + docker compose up website + That's it! After that, the website can be opened in the browser. diff --git a/website/site/pages/2-doc/2-first-steps/3-installation.md b/website/site/pages/2-doc/2-first-steps/3-installation.md index c9bcd0ac..34d49a2d 100644 --- a/website/site/pages/2-doc/2-first-steps/3-installation.md +++ b/website/site/pages/2-doc/2-first-steps/3-installation.md @@ -14,7 +14,7 @@ These are: - PHP: >=8.0 - Composer: >=2.x -## Composer support +## With PHP and Composer The easiest way to install Herbie is with Composer. To do this, run the following command in the terminal: @@ -34,3 +34,16 @@ Then change to the `web` directory of the created project and start the internal php -S localhost:8888 index.php The website can now be opened in the browser at . + +## With Docker and Docker Compose + +Create project and install dependencies. + + docker run --rm -v $PWD:/app composer create-project --ignore-platform-reqs getherbie/start-website mywebsite + +Go to the `mywebsite` directory and start website. + + cd mywebsite + docker compose up website + +Open http://localhost:8888 with your browser. diff --git a/website/site/pages/2-doc/5-indepth/5-query-builder.md b/website/site/pages/2-doc/5-indepth/5-query-builder.md index 0b212538..1b10e7d9 100644 --- a/website/site/pages/2-doc/5-indepth/5-query-builder.md +++ b/website/site/pages/2-doc/5-indepth/5-query-builder.md @@ -9,31 +9,51 @@ Herbie provides a fluent query builder interacting with your content and data in ~~~php $data = [ - ['title' => 'Foo', 'layout' => 'blog'], - ['title' => 'Bar', 'layout' => 'news'], - ['title' => 'Baz', 'layout' => 'blog'], + ['title' => 'Foo', 'layout' => 'default'], + ['title' => 'Bar', 'layout' => 'blog'], + ['title' => 'Baz', 'layout' => 'default'], ]; -$entries = (new \herbie\QueryBuilder) + +var_dump( + (new \herbie\QueryBuilder) ->from($data) - ->where('layout=blog') - ->offset(10) - ->limit(10) + ->where('layout=default') + ->offset(1) + ->limit(1) ->order('title') ->all() +); ~~~ In Twig the same query builder can be instantiated using the `query` function. ~~~twig -{{ '{%' }} set entries = query(data).where("layout=blog").offset(10).limit(10).order('title').all() {{ '%}' }} +{{ '{%' }} set data = [ + { + 'title': 'Foo', + 'layout': 'default', + }, + { + 'title': 'Bar', + 'layout': 'blog', + }, + { + 'title': 'Baz', + 'layout': 'default', + } +] {{ '%}' }} + +{{ '{{' }} dump(query(data).where("layout=default").offset(1).limit(1).order('title').all()) {{ '}}' }} ~~~ Some list entites also have a built-in query method, so the query builder can be used as follows. ~~~twig -{{ '{%' }} set entries = site.page_list.where("layout=blog").offset(10).limit(10).order('title').all() {{ '%}' }} +{{ '{{' }} dump(site.page_list.query().where("layout=default").all()) {{ '}}' }} ~~~ +NOTE: We are using Twigs `dump` function in these examples. You have to enable the function by setting `components.twigRenderer.debug` to `true` in your configuration file. + ## Retrieving Data A query builder allows you to query, filter, and narrow down the results you desire. @@ -44,7 +64,7 @@ The page list query builder allows you to find all the entries in a collection, The query builder allows you to assemble a query, chain additional constraints onto it, and then invoke the `all` method to get the results: ~~~twig -{{ '{{' }} query(site.page_list).where("layout=blog").limit(5).all() {{ '}}' }} +{{ '{{' }} dump(query(site.page_list).where("layout=default").limit(5).all()) {{ '}}' }} ~~~ This would return a list of the queried items. @@ -56,7 +76,7 @@ If you only want to get a single record, you may use the `one` method. This method will return a single data object: ~~~twig -{{ '{{' }} query(site.page_list).where("layout=blog").one() {{ '}}' }} +{{ '{{' }} dump(query(site.page_list).where("layout=default").one()) {{ '}}' }} ~~~ ## Where @@ -92,19 +112,19 @@ The String format is best used to specify simple conditions. For example: ~~~twig -{{ '{{' }} query(data).where("layout=blog", "title*=news") {{ '}}' }} +{{ '{{' }} dump(query(data).where("layout=default", "title*=news")) {{ '}}' }} ~~~ You can chain where clauses, filtering records based on more than one condition with AND: ~~~twig -{{ '{{' }} query(data).where("layout=blog").where("title*=news").where("hidden=false") {{ '}}' }} +{{ '{{' }} dump(query(data).where("layout=default").where("title*=news").where("hidden=false")) {{ '}}' }} ~~~ Values are type hinted according to the type of the field and one of the scalar types bool, float, int, or string. ~~~twig -{{ '{{' }} query(data).where("hidden=false", "size=14.25", "age=24", "layout=blog") {{ '}}' }} +{{ '{{' }} dump(query(data).where("hidden=false", "size=14.25", "age=24", "layout=default")) {{ '}}' }} ~~~ #### Multiple Fields @@ -112,7 +132,7 @@ Values are type hinted according to the type of the field and one of the scalar If you want to match a value in one field or another, you may specify multiple fields separated by a pipe "|" symbol, i.e. ~~~twig -{{ '{{' }} query(data).where("name|title|menu_title=product") {{ '}}' }} +{{ '{{' }} dump(query(data).where("name|title|menu_title=product")) {{ '}}' }} ~~~ Using the above syntax, the condition will match any data that have a name, title, or menu_title field of "product" or "Product". @@ -122,7 +142,7 @@ Using the above syntax, the condition will match any data that have a name, titl You may also specify an either/or value, by separating each of the values that may match with a pipe character "|". ~~~twig -{{ '{{' }} query(data).where("layout=blog|news") {{ '}}' }} +{{ '{{' }} dump(query(data).where("layout=default|blog")) {{ '}}' }} ~~~ #### Array Fields @@ -130,7 +150,7 @@ You may also specify an either/or value, by separating each of the values that m If the queried field is an array, the operator is applied for each array items as OR conjunction. ~~~twig -{{ '{{' }} query(data).where("tags=blog") {{ '}}' }} +{{ '{{' }} dump(query(data).where("tags=blog")) {{ '}}' }} ~~~ Using the above syntax, the query will match if one of the tags equals to "blog". @@ -142,7 +162,7 @@ It is written as an array whose keys are column names and values the correspondi For example: ~~~twig -{{ '{{' }} query(data).where({layout: "blog", age: 24, size: 178.5, hidden: false}) {{ '}}' }} +{{ '{{' }} dump(query(data).where({layout: "default", age: 24, size: 178.5, hidden: false})) {{ '}}' }} ~~~ ### Operator Format @@ -151,7 +171,7 @@ The operator format is best used when you have more complex sub queries that are For example: ~~~twig -{{ '{{' }} query(data).where(["OR", "layout=blog", "title*=blog|news", "date>=2022-12-12") {{ '}}' }} +{{ '{{' }} dump(query(data).where(["OR", "layout=default", "title*=blog|news", "date>=2022-12-12"])) {{ '}}' }} ~~~ With the syntax above, the individual conditions are OR conjuncted. @@ -159,7 +179,7 @@ With the syntax above, the individual conditions are OR conjuncted. The AND/OR where clause operators can be nested: ~~~twig -{{ '{{' }} query(data).where(["OR", ["AND", "layout=blog", "title*=blog"], ["AND", "date>=2022-12-12", "cached=true"]]) {{ '}}' }} +{{ '{{' }} dump(query(data).where(["OR", ["AND", "layout=default", "title*=blog"], ["AND", "date>=2022-12-12", "cached=true"]])) {{ '}}' }} ~~~ ## Order @@ -172,14 +192,14 @@ Here are examples of its usage. Ordered by title descending: ~~~twig -{{ '{{' }} query(data).order("-title") {{ '}}' }} +{{ '{{' }} dump(query(data).order("-title")) {{ '}}' }} ~~~ Ordered by title ascending: ~~~twig -{{ '{{' }} query(data).order("title") {{ '}}' }} -{{ '{{' }} query(data).order("+title") {{ '}}' }} +{{ '{{' }} dump(query(data).order("title")) {{ '}}' }} +{{ '{{' }} dump(query(data).order("+title")) {{ '}}' }} ~~~ ## Limit @@ -187,7 +207,7 @@ Ordered by title ascending: You may limit the results by using the `limit` method: ~~~twig -{{ '{{' }} query(data).limit(10) {{ '}}' }} +{{ '{{' }} dump(query(data).limit(10)) {{ '}}' }} ~~~ ## Offset @@ -195,7 +215,7 @@ You may limit the results by using the `limit` method: You may skip results by using the `offset` method: ~~~twig -{{ '{{' }} query(data).offset(10).limit(10) {{ '}}' }} +{{ '{{' }} dump(query(data).offset(10).limit(10)) {{ '}}' }} ~~~ ## Count @@ -203,7 +223,7 @@ You may skip results by using the `offset` method: The query builder also provides a count method for retrieving the number of records returned. ~~~twig -{{ '{{' }} query(data).where("layout=blog").count() {{ '}}' }} +{{ '{{' }} dump(query(data).where("layout=default").count()) {{ '}}' }} ~~~ ## Paginate @@ -211,7 +231,7 @@ The query builder also provides a count method for retrieving the number of reco If you want to get paginated results on a query, you may use the `paginate` method and specify the desired number of results per page. ~~~twig -{{ '{{' }} query(data).where("layout=blog").paginate(10); {{ '}}' }} +{{ '{{' }} dump(query(data).where("layout=default").paginate(10)) {{ '}}' }} ~~~ This will return an instance of `herbie\Pagination` that you can use to assemble the pagination style of your choice.