diff --git a/README.md b/README.md index 78c4a3ec..583fb1f1 100644 --- a/README.md +++ b/README.md @@ -18,27 +18,35 @@ Add a new entry to the category's `articles` array in `src/App/src/Fixture/artic "isObsolete": false, "opengraph_img": null, "excerpt": "Short excerpt shown in listings.", - "tl_dr": "One or two sentence summary." + "tl_dr": "One or two sentence summary.", + "tags": [ + { + "name": "your tag", + "slug": "your-tag" + } + ] } ``` -`author.display_name` can either match an existing author or be a new name — `bin/doctrine-fixtures` creates a new `Author` automatically for any name not already in the database. The category (top-level `slug`) must already exist, though. The article's slug is derived automatically from the title (lowercased, non-alphanumeric characters collapsed to `-`) by `PostLoader::slugify()`. +`author.display_name` can either match an existing author or be a new name - `bin/doctrine-fixtures` creates a new `Author` automatically for any name not already in the database. The category (top-level `slug`) must already exist, though. The article's slug is derived automatically from the title (lowercased, non-alphanumeric characters collapsed to `-`) by `PostLoader::slugify()`. -`opengraph_img` is the image shown as the social-media (Twitter/OG) preview card. Leave it `null` to fall back to the site-wide default image (`config/autoload/local.php` → `application.meta.image`). To set one, put the image file at `public/opengraph/article/your-image.png` and reference it here as a root-relative path: `"opengraph_img": "/opengraph/article/your-image.png"`. This is unrelated to the in-article images described in step 3 — it is placed by hand, not by `bin/create-uploads-dir`. +`tags` can be left empty, but adding tags that describe the article's subject is useful - they show up on the article page and back its tag-resource pages. -**Important:** you can set `"post_status": "draft"` instead of `"publish"` to keep an article out of sight — anything other than `publish`/`private` is treated as a draft by `PostLoader`, and `getPublishedPosts()` (used by both `bin/generate-feed` and `bin/sitemap`) only returns posts with `publish` status. After changing it, follow the same steps: re-run `bin/doctrine-fixtures`, then `bin/generate-feed` and `bin/sitemap`. This applies generally, not just to status changes — **any** edit to `articles_cleaned.json` (title, excerpt, status, date, etc.) needs `bin/doctrine-fixtures` re-run to update the database, followed by re-running the 3 generators in step 4 so `feed.xml`/`sitemap.xml`/`llms-full.txt` reflect it. One exception: `bin/generate-llms-full` reads straight from the `.md` files on disk and does **not** check `post_status` at all — a `draft` article's `.md` file will still be included in `llms-full.txt` unless you also remove or rename that file. +`opengraph_img` is the image shown as the social-media (Twitter/OG) preview card. Leave it `null` to fall back to the site-wide default image (`config/autoload/local.php` → `application.meta.image`). To set one, put the image file at `public/opengraph/article/your-image.png` and reference it here as a root-relative path: `"opengraph_img": "/opengraph/article/your-image.png"`. This is unrelated to the in-article images described in step 3 - it is placed by hand, not by `bin/create-uploads-dir`. + +**Important:** you can set `"post_status": "draft"` instead of `"publish"` to keep an article out of sight - anything other than `publish`/`private` is treated as a draft by `PostLoader`, and `getPublishedPosts()` (used by both `bin/generate-feed` and `bin/sitemap`) only returns posts with `publish` status. After changing it, follow the same steps: re-run `bin/doctrine-fixtures`, then `bin/generate-feed` and `bin/sitemap`. This applies generally, not just to status changes - **any** edit to `articles_cleaned.json` (title, excerpt, status, date, etc.) needs `bin/doctrine-fixtures` re-run to update the database, followed by re-running the 3 generators in step 4 so `feed.xml`/`sitemap.xml`/`llms-full.txt` reflect it. One exception: `bin/generate-llms-full` reads straight from the `.md` files on disk and does **not** check `post_status` at all - a `draft` article's `.md` file will still be included in `llms-full.txt` unless you also remove or rename that file. ## 2. Create the templates -- `src/Blog/templates/page/blog-resource/{category-slug}/{article-slug}.html.twig` — the page body, extending `@layout/blog-post.html.twig`. -- `src/Blog/templates/page/JSON-LD/{category-slug}/{article-slug}.jsonld.twig` — the `@graph` of `TechArticle` + `BreadcrumbList` + `FAQPage` structured data. -- `public/md-articles/{category-slug}/{article-slug}.md` — the markdown version, with YAML front matter (`title`, `description`, `author`, `date_published`, `canonical_url`, `category`, `language`) followed by the article body (`TL;DR`, sections, `FAQ`). This feeds `llms-full.txt`. +- `src/Blog/templates/page/blog-resource/{category-slug}/{article-slug}.html.twig` - the page body, extending `@layout/blog-post.html.twig`. +- `src/Blog/templates/page/JSON-LD/{category-slug}/{article-slug}.jsonld.twig` - the `@graph` of `TechArticle` + `BreadcrumbList` + `FAQPage` structured data. +- `public/md-articles/{category-slug}/{article-slug}.md` - the markdown version, with YAML front matter (`title`, `description`, `author`, `date_published`, `canonical_url`, `category`, `language`) followed by the article body (`TL;DR`, sections, `FAQ`). This feeds `llms-full.txt`. Copy an existing set of these three files in the same category as a starting point, to match the established structure (FAQ block matching the `FAQPage` entries, etc.). -If the article body uses images (via `asset('uploads/article/' ~ article.id ~ '/filename.png')` in the `.html.twig`), just drop the image file anywhere under `public/uploads` — `bin/create-uploads-dir` (step 4) finds it by filename and copies it to the right place. No manual path/folder creation needed. +If the article body uses images (via `asset('uploads/article/' ~ article.id ~ '/filename.png')` in the `.html.twig`), just drop the image file anywhere under `public/uploads` - `bin/create-uploads-dir` (step 4) finds it by filename and copies it to the right place. No manual path/folder creation needed. -## 3. At deploy — run in this order +## 3. At deploy - run in this order ```shell php bin/doctrine-fixtures @@ -46,9 +54,9 @@ php bin/create-uploads-dir ``` - `bin/doctrine-fixtures` loads `articles_cleaned.json` into the database, creating the `Post` entity (with its database-generated UUID) for the new article. -- `bin/create-uploads-dir` must run *after* it — it resolves the post by slug to get that UUID, creates `public/uploads/article/{post-id}/`, and copies each image referenced in the `.html.twig` there from wherever it already lives under `public/uploads`. +- `bin/create-uploads-dir` must run *after* it - it resolves the post by slug to get that UUID, creates `public/uploads/article/{post-id}/`, and copies each image referenced in the `.html.twig` there from wherever it already lives under `public/uploads`. -## 4. Regenerate the public artifacts — any order +## 4. Regenerate the public artifacts - any order ```shell php bin/generate-feed @@ -62,11 +70,19 @@ php bin/generate-llms-full These three have no ordering dependency on each other, only on step 3 being done first. -None of this is wired into an automated deploy pipeline in this repository — there is no `deploy` script or CI job that runs these `bin/` scripts. `public/feed.xml`, `public/sitemap.xml`, and `public/llms-full.txt` are committed generated artifacts, so re-running these scripts leaves them modified in git until committed. +**`public/llms.txt` is not part of this - it is edited by hand, not generated.** It's a separate, curated index (one line per article, grouped by category) distinct from the full-text `llms-full.txt`. Whenever an article is added, add a matching entry under its category: + +```markdown +- [Your article title](https://www.dotkernel.com/{category-slug}/{article-slug}/): One-sentence description, similar to the excerpt. +``` + +Also bump that category's post count in its heading (e.g. `## Dotkernel (65 posts)`). Entries are ordered alphabetically by title within each category. + +None of this is wired into an automated deploy pipeline in this repository - there is no `deploy` script or CI job that runs these `bin/` scripts. `public/feed.xml`, `public/sitemap.xml`, and `public/llms-full.txt` are committed generated artifacts, so re-running these scripts leaves them modified in git until committed. ## 5. Scheduled jobs (cron) -- **`bin/generate-packages`** — the only script here actually wired into a cron job. It rebuilds the Dotkernel packages listing from the GitHub organisation, which changes independently of this repo, so it runs on a schedule instead of at deploy time: +- **`bin/generate-packages`** - the only script here actually wired into a cron job. It rebuilds the Dotkernel packages listing from the GitHub organisation, which changes independently of this repo, so it runs on a schedule instead of at deploy time: ```text 0 4 * * * cd /path/to/dotkernel.com && /usr/bin/php bin/generate-packages >> log/generate-packages.log 2>&1 ``` diff --git a/public/llms.txt b/public/llms.txt index bf4dee55..2f91346f 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -14,99 +14,42 @@ Content spans foundational PHP/middleware architecture (PSR-7, PSR-15, request l ## Categories -## Dotkernel (64 posts) +## Dotkernel (19 posts) *the core framework — releases, caching, sessions, auth, WURFL/device detection* - [Adding a CORS implementation to Zend Expressive](https://www.dotkernel.com/dotkernel/adding-a-cors-implementation-to-zend-expressive/): A guide on how to add a CORS implementation to an existing Dotkernel3 project using Tuupola's Cors Middleware package. -- [Adding a second caching layer to WURFL in Dotkernel using APC](https://www.dotkernel.com/dotkernel/adding-a-second-caching-layer-to-wurfl-in-dotkernel-using-apc/): How adding a small, custom APC-based caching layer on top of WURFL's own cache cut response time by an order of magnitude. - [Adding Composer support in your Dotkernel project](https://www.dotkernel.com/dotkernel/adding-composer-support-in-your-dotkernel-project/): The steps needed to add Composer support to a Dotkernel 1.x project, or 'composify' it. -- [Adding Windows 10 OS and Browser detection in Dotkernel projects](https://www.dotkernel.com/dotkernel/adding-windows-10-os-and-browser-detection-in-dotkernel-projects/): A guide to installing the patch that adds Windows 8, 8.1 and 10 OS icons and the Microsoft Edge browser icon in Dotkernel. - [Autologin using Cookie / Remember Me in Dotkernel](https://www.dotkernel.com/dotkernel/autologin-using-cookie-remember-me-in-dotkernel/): A step-by-step guide to implementing a Remember Me / autologin feature in Dotkernel Frontend. - [Avoid routing through bootstrap of non existent files](https://www.dotkernel.com/dotkernel/avoid-routing-through-bootstrap-of-non-existent-files/): How to stop missing static files from being routed through the bootstrap and logging out users whose session regenerates on each request. -- [Caching in Dotkernel using Zend Framework](https://www.dotkernel.com/dotkernel/caching-in-dotkernel-using-zend-framework/): How Dotkernel's upcoming 1.8 cache layer stores router, ACL, menu and other data between requests, using APC/APCU or file storage. -- [camelCase Table Names in MySQL on Windows](https://www.dotkernel.com/dotkernel/camelcase-table-names-in-mysql-on-windows/): How to fix MySQL on WAMP/XAMPP lowercasing camelCase table names by setting lower_case_table_names=2 in my.cnf. - [Commitment to PHP - new Zend Certified Engineers - ZCE - in our team](https://www.dotkernel.com/dotkernel/commitment-to-php-new-zend-certified-engineers-zce-in-our-team/): Two more team members passed the ZCE exam, bringing the team's total to 5 Zend Certified Engineers. -- [Configuring the Cache in Dotkernel](https://www.dotkernel.com/dotkernel/configuring-the-cache-in-dotkernel/): A configuration guide for Dotkernel's Zend Framework Cache-based caching layer, covering the main frontend settings and the optional per-backend settings. - [Dependency Injection made easy in Laminas/Mezzio applications](https://www.dotkernel.com/dotkernel/dependency-injection-made-easy-in-laminas-mezzio-applications/): Introduces Dotkernel's dot-dependency-injection package, which autowires constructor dependencies in Laminas/Mezzio applications via a PHP attribute instead of a hand-written factory per class. -- [Detecting Mobile Devices in Dotkernel 1.6.0](https://www.dotkernel.com/dotkernel/detecting-mobile-devices-in-dotkernel-1-6-0/): Explains how mobile device detection changed in Dotkernel 1.6.0 with the move to Wurfl Cloud, including the required application.ini settings and sample Dot_UserAgent usage code. -- [Disable Wurfl redirect for mobile browsers](https://www.dotkernel.com/dotkernel/disable-wurfl-redirect-for-mobile-browsers/): Shows the application.ini setting introduced in revision 408 to control Dotkernel's automatic Wurfl-based redirect of mobile visitors to the mobile site, and the code that checks it. - [Disambiguation: Dotkernel 1 and Dotkernel 3](https://www.dotkernel.com/dotkernel/disambiguation-dotkernel-1-and-dotkernel-3/): Clarifies what Dotkernel 1 and Dotkernel 3 are, how they differ architecturally, and which version is meant when someone simply says 'Dotkernel'. - [Doctrine cache using symfony/cache](https://www.dotkernel.com/dotkernel/doctrine-cache-using-symfony-cache/): How to enable and configure the dotkernel/dot-cache component, a wrapper around symfony/cache, to cache Doctrine's result, metadata, query, and hydration data in Dotkernel Admin. - [Doctrine enum implementation in Dotkernel](https://www.dotkernel.com/dotkernel/doctrine-enum-implementation-in-dotkernel/): How Dotkernel adopted Doctrine ORM 3.2's EnumType support to replace loosely-enforced string-based status columns with PHP enums backed by a custom DBAL type. -- [DotBoost Technologies : Products and Services North American Relaunch](https://www.dotkernel.com/dotkernel/dotboost-technologies-products-and-services-north-american-relaunch/): Dotboost Technologies announces its North American relaunch, centered on the source release of its in-house Dotkernel framework alongside expanded IT integration and consulting services. -- [Dotkernel 1.2.0 release](https://www.dotkernel.com/dotkernel/dotkernel-1-2-0-release/): Release notes for Dotkernel 1.2.0, covering database naming convention changes, the new 'dots' submodule concept, new and updated library classes, and the use of prepared statements for all SQL queries. -- [Dotkernel 1.2.2 release](https://www.dotkernel.com/dotkernel/dotkernel-1-2-2-release/): Dotkernel 1.2.2 is a bug-fix release closing five issues, including captcha error handling, a pagination bug, and a copyright line update that touched every PHP file. -- [Dotkernel 1.3.0 release](https://www.dotkernel.com/dotkernel/dotkernel-1-3-0-release/): Dotkernel 1.3.0 adds an admin skin switcher, a way to protect member-only links, and reorganizes resource.xml into route.xml and dots.xml, at the cost of backward compatibility. -- [Dotkernel 1.3.2 release](https://www.dotkernel.com/dotkernel/dotkernel-1-3-2-release/): Dotkernel 1.3.2 is a maintenance release with many bug fixes, a couple of minor features, and some refactoring, released just before the winter holidays. -- [Dotkernel 1.5.0 Released](https://www.dotkernel.com/dotkernel/dotkernel-1-5-0-released/): Dotkernel 1.5.0 skips version 1.4 entirely and brings a switch from Dojo to jQuery, redesigned admin and frontend, model inheritance via Dot_Model, dashed controller support, and a reorganized Zend Registry. -- [Dotkernel 1.8.0 LTS Released](https://www.dotkernel.com/dotkernel/dotkernel-1-8-0-lts-released/): Dotkernel 1.8.0 (LTS) introduces a plugin architecture, a redesigned mobile-friendly admin and frontend, APC/File caching for speed, a new Dot_Request class, and several security and alerting improvements. -- [Dotkernel 1.8.1 + Upgrade from 1.8.0 Released](https://www.dotkernel.com/dotkernel/dotkernel-1-8-1-upgrade-from-1-8-0-released/): Dotkernel 1.8.1 adds Enhanced Cache Support with cache tagging, and ships with a dedicated upgrade package for users coming from 1.8.0. -- [Dotkernel Coding Standard](https://www.dotkernel.com/dotkernel/dotkernel-coding-standard/): Dotkernel borrows the Zend Framework coding standard with a few exceptions, covering indentation, class/interface/file naming, and curly brace placement for control statements. -- [Dotkernel Database Naming Conventions for MySQL](https://www.dotkernel.com/dotkernel/dotkernel-database-naming-conventions-for-mysql/): Dotkernel borrows its database naming conventions from FaZend, covering singular table names, auto-incrementing id columns, foreign key and constraint naming patterns, and camelLetter casing. - [Dotkernel Light - Starting with Mezzio microframework and Laminas components](https://www.dotkernel.com/dotkernel/dotkernel-light-starting-with-mezzio-microframework-and-laminas-components/): Dotkernel Light is a stripped-down version of Dotkernel Frontend built on Mezzio and Laminas components, keeping only routing, templating, error handling, and tests, for a gentler learning curve. - [Dotkernel Light: the best choice for your presentation site](https://www.dotkernel.com/dotkernel/dotkernel-light-the-best-choice-for-your-presentation-site/): A walkthrough of using Dotkernel Light to build a simple presentation site: adding new pages, managing assets, and configuring Twitter/OpenGraph cards, the top menu, and the footer. -- [Dotkernel on Nginx](https://www.dotkernel.com/dotkernel/dotkernel-on-nginx/): A walkthrough of testing whether Dotkernel runs out of the box on Nginx, and how the Nginx configuration was set up as a substitute for Apache's .htaccess. -- [Dotkernel Reserved Variable Names for Caching](https://www.dotkernel.com/dotkernel/dotkernel-reserved-variable-names-for-caching/): A reference of the variables Dotkernel caches — router, ACL role, menu, options, and browser/OS data — and the cache keys they use. -- [Dotkernel Template Engine](https://www.dotkernel.com/dotkernel/dotkernel-template-engine/): Dotkernel Template Engine is an implementation of the PHPLib Template engine for PHP5, separating application code from the presentation layer. -- [Dotkernel version 1.0 in action](https://www.dotkernel.com/dotkernel/dotkernel-version-1-0-in-action/): An overview of Dotkernel 1.0, DotBoost's in-house framework built on Zend Framework, its simplified MVC architecture, and the specific Zend Framework classes it relies on. - [Forcing UTF8 connections and character set in MySQL](https://www.dotkernel.com/dotkernel/forcing-utf8-connections-and-character-set-in-mysql/): How to force the MySQL server's character set and collation to UTF8 via my.cnf, so every connecting script uses it regardless of client. -- [GeoIP City Removed From Dotkernel](https://www.dotkernel.com/dotkernel/geoip-city-removed-from-dotkernel/): Why the GeoIP City integration was removed from Dotkernel due to a segmentation fault with GeoIP extension 1.1.0+, and how to remove the affected code if you don't need GeoIP City. -- [GeoIP: Ip Address Location In Dotkernel](https://www.dotkernel.com/dotkernel/geoip-ip-address-location-in-dotkernel/): How Dotkernel's getCountryByIp function in library/Dot/Geoip.php uses MaxMind's GeoIP technology and its .dat files to determine a visitor's country. - [Handling and Logging errors with dot-errorhandler and dot-log](https://www.dotkernel.com/dotkernel/handling-and-logging-errors-with-dot-errorhandler-and-dot-log/): A guide to using dotkernel/dot-errorhandler alongside dot-log (or zend-log) to log errors in Zend Expressive applications, covering its two handler types, configuration, and how it was tested. -- [Highcharts Integration in Dotkernel 1.6.0](https://www.dotkernel.com/dotkernel/highcharts-integration-in-dotkernel-1-6-0/): Dotkernel 1.6.0 integrates the Highcharts charting library, adding interactive pie, column and line chart samples to the admin. +- [How to build this website starting from Dotkernel Light](https://www.dotkernel.com/dotkernel/how-to-build-this-website-starting-from-dotkernel-light/): How this blog itself came together: starting from the Dotkernel Light starter project, then following the Tutorial 101 to add Doctrine ORM and load real data into the database. - [How to group log files by date using dot-log](https://www.dotkernel.com/dotkernel/how-to-group-log-files-by-date-using-dot-log/): How dot-log Version 3.1.1 lets you use datetime formatter strings in the stream option of a log writer, so log files get grouped by date. -- [How to Set a Persistent Connection to Database with Zend Framework Zend_Db adapter](https://www.dotkernel.com/dotkernel/how-to-set-a-persistent-connection-to-database-with-zend-framework-zend-db-adapter/): How to configure a persistent database connection in application.ini using the Zend_Db adapter, and the option that will not work. -- [How to use Alerts in Dotkernel](https://www.dotkernel.com/dotkernel/how-to-use-alerts-in-dotkernel/): How the Dot_Alert system works in Dotkernel, used to e-mail developers when something goes wrong, illustrated with the failed-email-send use case. -- [Implementing the new Password Hashing API from PHP 5.5 in Dotkernel](https://www.dotkernel.com/dotkernel/implementing-the-new-password-hashing-api-from-php-5-5-in-dotkernel/): Dotkernel 1.8.0 refactors password handling to use PHP 5.5's Password Hashing API, using the Password Compat library for older PHP, with steps to upgrade existing systems. -- [Installing GeoIP extension in Zend Server 5.6 on Windows](https://www.dotkernel.com/dotkernel/installing-geoip-extension-in-zend-server-5-6-on-windows/): Step-by-step guide to testing, downloading, installing and enabling the php_geoip extension and MaxMind databases on Zend Server 5.6 for Windows. -- [Installing GeoIP extension in Zend Server 6 on Windows](https://www.dotkernel.com/dotkernel/installing-geoip-extension-in-zend-server-6-on-windows/): Update to the Zend Server 5.6 GeoIP guide, covering how to install and enable php_geoip on Zend Server 6.1 on Windows. - [Logging with dot-log in Zend Expressive and Dotkernel](https://www.dotkernel.com/dotkernel/logging-with-dot-log-in-zend-expressive-and-dotkernel/): How to wire up, configure and use the dot-log component (compatible with zend-log) within Dotkernel, Zend Expressive, or any project using Zend Service Manager. -- [Manual upgrade of WURFL xml file in Dotkernel](https://www.dotkernel.com/dotkernel/manual-upgrade-of-wurfl-xml-file-in-dotkernel/): How to manually upgrade the bundled WURFL XML file in Dotkernel now that its license has changed and Dotkernel no longer updates it. -- [Migration of Zend Framework 1 PEAR channel](https://www.dotkernel.com/dotkernel/migration-of-zend-framework-1-pear-channel/): The unofficial PEAR channel for Zend Framework 1 moved from Google Code to a new dedicated server, with instructions on how to switch to the new channel. -- [New Features in Zend Framework 1.12](https://www.dotkernel.com/dotkernel/new-features-in-zend-framework-1-12/): Overview of Zend Framework 1.12.0RC1, covering new components back ported from ZF2, the removal of the WurflApi adapter, and over 200 bug fixes. -- [PHP Formatter and Templates for Zend Studio 10.1](https://www.dotkernel.com/dotkernel/php-formatter-and-templates-for-zend-studio-10-1/): An updated PHP Formatter plugin and a Dotkernel coding standard templates file for Zend Studio 10.1, along with the required Formatter plugin change. -- [Protecting admin folder with .htaccess in Plesk](https://www.dotkernel.com/dotkernel/protecting-admin-folder-with-htaccess-in-plesk/): How to protect the /admin folder with HTTP Basic Auth in a Plesk vhost.conf file, and how to apply the change and finish setup with .htpasswd. - [Replacing laminas-mail with Symfony mailer in dot-mail](https://www.dotkernel.com/dotkernel/replacing-laminas-mail-with-symfony-mailer-in-dot-mail/): Why and how Dotkernel replaced the abandoned laminas/laminas-mail package with symfony/mailer inside dotkernel/dot-mail, including configuration changes and the upgrade path to version 5. -- [Scientia Mobile licensed its Wurfl Cloud PHP library to Dotkernel 1.6](https://www.dotkernel.com/dotkernel/scientia-mobile-licensed-its-wurfl-cloud-php-library-to-dotkernel-1-6/): Dotkernel 1.6.0 removed the obsolete GPL'ed WURFL PHP library and replaced it with Scientia Mobile's WURFL Cloud PHP library, under a special license limited to use with the Dotkernel framework. -- [Sending emails using Dot_Email component and Zend_Email](https://www.dotkernel.com/dotkernel/sending-emails-using-dot-email-component-and-zend-email/): Dot_Email extends Zend_Mail with two additional methods, setContent() and send(), and this article covers how to use it and which Zend_Mail methods are inherited. - [Templating in Dotkernel3](https://www.dotkernel.com/dotkernel/templating-in-dotkernel3/): Dotkernel3 replaces its 10-year-old templating engine with Twig, gaining layouts, loops, variables, and escaping while keeping the familiarity of HTML. - [Using Dotkernel with Composer Dependencies](https://www.dotkernel.com/dotkernel/using-dotkernel-with-composer-dependencies/): How to use external Composer dependencies in Dotkernel, demonstrated by rendering a barcode with both the non-namespaced Zend Framework 1 and the namespaced Zend Framework 2. -- [Using UTF8 charset in Dotkernel](https://www.dotkernel.com/dotkernel/using-utf8-charset-in-dotkernel/): How to enable UTF8 encoding in a Dotkernel-based system, covering both database collation and the application.ini charset setting. -- [Wurfl Cloud Integration in Dotkernel 1.6.0](https://www.dotkernel.com/dotkernel/wurfl-cloud-integration-in-dotkernel-1-6-0/): How WURFL Cloud, WURFL's cloud-based device detection service, was integrated as the default mobile detection method in Dotkernel 1.6.0. -- [WURFL PHP API license incompatible with Dotkernel](https://www.dotkernel.com/dotkernel/wurfl-php-api-license-incompatible-with-dotkernel/): The WURFL PHP API's license changed from GNU/GPL to AGPL in version 1.3.0, making it a trial-only library incompatible with keeping Dotkernel free. -- [WURFL Zend Framework Integration into Dotkernel](https://www.dotkernel.com/dotkernel/wurfl-zend-framework-integration-into-dotkernel/): Step-by-step tutorial on integrating WURFL into Dotkernel using the Zend_Http_UserAgent class from Zend Framework 1.11.0rc1. -- [Zend Framework dropped integration of WURFL adapter](https://www.dotkernel.com/dotkernel/zend-framework-dropped-integration-of-wurfl-adapter/): Zend Framework 1.12.0 drops the WURFL adapter from Zend_Http_UserAgent due to WURFL's licensing change to AGPL; Dotkernel is unaffected since it uses its own WURFL adapter. -- [Zend Registry usage in Dotkernel](https://www.dotkernel.com/dotkernel/zend-registry-usage-in-dotkernel/): The variables stored in Zend_Registry in Dotkernel and how to read them, either as a full instance or one value at a time. -- [Zend Studio PHP Formatter file for Dotkernel coding standard.](https://www.dotkernel.com/dotkernel/zend-studio-php-formatter-file-for-dotkernel-coding-standard/): A downloadable XML file for Zend Studio 9.x that configures the PHP code formatter to follow Dotkernel's coding standard. -- [Zend_Auth and Zend_Acl integrated in Dotkernel](https://www.dotkernel.com/dotkernel/zend-auth-and-zend-acl-integrated-in-dotkernel/): How Zend_Auth and Zend_Acl were integrated into Dotkernel 1.5.0 through the Dot_Auth and Dot_Acl classes for user authentication and access control. -- [Zend_Console implementation in Dotkernel](https://www.dotkernel.com/dotkernel/zend-console-implementation-in-dotkernel/): How Dotkernel's Console bootstrap lets you run PHP scripts from the command line, including its arguments and bundled example actions. -- [Zend_Session usage in Dotkernel - Refactor of Dot_Session class](https://www.dotkernel.com/dotkernel/zend-session-usage-in-dotkernel-refactor-of-dot-session-class/): A session cookie bug found in IE8/IE9 on Dotkernel 1.5.0, traced to redundant regenerateID()/rememberMe() calls in Dot_Session, and the fix shipped in 1.5.1. - -## PHP Development (20 posts) + +## PHP Development (8 posts) *general PHP tooling, environments, IDEs, security* - [AlmaLinux 9 in WSL2 : install PHP, Apache, MariaDB, Composer, PhpMyadmin](https://www.dotkernel.com/php-development/almalinux-9-in-wsl2-install-php-apache-mariadb-composer-phpmyadmin/): A step-by-step guide to installing AlmaLinux 9 under Windows Subsystem for Linux (WSL2) and provisioning it with Ansible to run PHP, Apache, MariaDB, Composer, and phpMyAdmin. -- [Aptana PHP installation in Aptana 2.x](https://www.dotkernel.com/php-development/aptana-php-installation-in-aptana-2-x/): A quick fix for restoring PHP support in Aptana 2.x after the bundled Aptana PHP plugin was discontinued in favor of PDT, plus adding SVN support via Subclipse. -- [Better Unicode Support in MySQL 5.5 UTF8MB4](https://www.dotkernel.com/php-development/better-unicode-support-in-mysql-5-5-utf8mb4/): How Dotkernel adopted MySQL 5.5's utf8mb4 character set for fuller Unicode support, and the config and column-length changes that switch requires. - [Database seeding: Doctrine data fixtures vs Phinx](https://www.dotkernel.com/php-development/database-seeding-doctrine-data-fixtures-vs-phinx/): Why Dotkernel moved database seeding from Phinx to doctrine/data-fixtures, the CLI package built to fill Doctrine's missing command-line interface, and how to install, use, and order fixtures. -- [End of Support for PHP 5.2.x Branch](https://www.dotkernel.com/php-development/end-of-support-for-php-5-2-x-branch/): PHP 5.2.14 marks the end of active support for the PHP 5.2 branch, with PHP 5.3.3 released and ready for upgrade. - [Floating-Point Arithmetic - Why is (int)((0.7+0.1)*10) = 7 ?](https://www.dotkernel.com/php-development/floating-point-arithmetic-why-is-int-0-7-0-1-10-7/): An explanation of why PHP's floating-point arithmetic and int casting can produce unexpected results like (int)((0.7+0.1)*10) = 7 instead of 8. -- [How To Upgrade Wamp to PHP 5.3.4](https://www.dotkernel.com/php-development/how-to-upgrade-wamp-to-php-5-3-4/): Step-by-step instructions for upgrading a WAMP server's PHP version to 5.3.4. - [Mezzio app development in WSL2](https://www.dotkernel.com/php-development/mezzio-app-development-in-wsl2/): A step-by-step guide to installing a Mezzio application (Dotkernel API) inside WSL2, running it on Ubuntu 20.04 LTS. -- [PHP 5.3.6 released. No upgrade possible for WampServer.](https://www.dotkernel.com/php-development/php-5-3-6-released-no-upgrade-possible-for-wampserver/): PHP 5.3.6 dropped Visual Studio C++ 6 Windows builds, making an in-place WampServer upgrade impossible since WampServer itself is built with VC++ 6. - [PHP Environment : Development Staging Production](https://www.dotkernel.com/php-development/php-environment-development-staging-production/): An overview of the development, staging and production server environments used to improve the development, testing and release process of client-server applications. -- [PHP support back in Aptana 3.0](https://www.dotkernel.com/php-development/php-support-back-in-aptana-3-0/): Aptana PHP support is coming back and will be integrated directly into the Studio 3 core rather than as a separate plugin. - [Protection against SQL Injection using PDO and Zend Framework](https://www.dotkernel.com/php-development/protection-against-sql-injection-using-pdo-and-zend-framework/): An overview of what SQL injection is, what PDO provides, and how prepared statements in Zend Framework help - but don't fully guarantee - protection against SQL injection. - [Protection against SQL Injection using PDO and Zend Framework - part 2](https://www.dotkernel.com/php-development/protection-against-sql-injection-using-pdo-and-zend-framework-part-2/): A closer look at Zend_Db's query, fetchAll, insert, update, and delete methods, and where SQL injection can still slip through even with prepared statements. -- [Remote connections to MySQL server on Plesk based servers](https://www.dotkernel.com/php-development/remote-connections-to-mysql-server-on-plesk-based-servers/): How to fix remote MySQL connection failures on Plesk-based Linux servers caused by the default old_passwords flag, by creating a user with a modern password hash. - [Static Analysis - Replacing Psalm with PHPStan](https://www.dotkernel.com/php-development/static-analysis-replacing-psalm-with-phpstan/): Why Dotkernel replaced Psalm with PHPStan for static analysis, and a walkthrough of updating composer.json, CI, and configuration files to run PHPStan checks. -- [Using Aptana to connect to Dotkernel tracker (Mantis)](https://www.dotkernel.com/php-development/using-aptana-to-connect-to-dotkernel-tracker-mantis/): A step-by-step guide to integrating the Aptana IDE with Dotkernel Tracker, a Mantis-based bug tracker, using the Mylyn plugin's Mantis connector. -- [Using PHP 7 Express in Zend Studio 13](https://www.dotkernel.com/php-development/using-php-7-express-in-zend-studio-13/): A walkthrough of Zend Studio 13's PHP 7 Express feature, covering test-project setup, PHP interpreter selection, adding Zend Framework 1, and running a PHP7 compatibility check. -- [Version Control Ignore Patterns in Zend Studio](https://www.dotkernel.com/php-development/version-control-ignore-patterns-in-zend-studio/): How to configure global 'Ignored Resources' patterns in Zend Studio so they apply across all projects, instead of setting them individually per project. -- [Welcome to the 10th Zend Certified Engineer in Dotboost Team](https://www.dotkernel.com/php-development/welcome-to-the-10th-zend-certified-engineer-in-dotboost-team/): Announcement that the 10th member of the Dotboost Technologies team has passed the Zend Certified Engineer exam, plus the team's next certification goals. -- [Zend Server 5.5 Quick Setup on Windows](https://www.dotkernel.com/php-development/zend-server-5-5-quick-setup-on-windows/): Three quick configuration steps to make a fresh Zend Server 5.5 install on Windows 7 ready for development: enabling mod_rewrite, tuning PHP directives, and enabling APC. ## How to's (14 posts) @@ -127,19 +70,15 @@ Content spans foundational PHP/middleware architecture (PSR-7, PSR-15, request l - [What is cross origin token redemption?](https://www.dotkernel.com/how-to/what-is-cross-origin-token-redemption/): An explanation of cross-origin token redemption, the technique for securely verifying and redeeming a token issued on one domain when it's used on another, including how JWT and OAuth 2.0 implement it. - [What is PSR-7 and how to use it](https://www.dotkernel.com/how-to/what-is-psr-7-and-how-to-use-it/): A practical reference to PSR-7's HTTP message interfaces and a cheatsheet-style walkthrough of working with headers and message bodies using Zend Diactoros. -## Best Practice (13 posts) +## Best Practice (9 posts) *coding standards and database access patterns* -- [Aptana - set SVN keywords](https://www.dotkernel.com/best-practice/aptana-set-svn-keywords/): How to set the svn:keywords property (e.g. - [Basic Security in Dotkernel Headless Platform](https://www.dotkernel.com/best-practice/basic-security-in-dotkernel-headless-platform/): A practical overview of software security practices implemented across the Dotkernel Headless Platform, covering input validation, content negotiation, CORS, RBAC, OAuth2, sessions, dependencies, and more. -- [Golden Rules of Professional PHP Coding](https://www.dotkernel.com/best-practice/golden-rules-of-professional-php-coding/): A short list of practical rules for professional PHP development: error reporting settings, fixing warnings, marking hacks, single-responsibility functions, version control, and IDE usage. - [htaccess 301 redirect non-www to www](https://www.dotkernel.com/best-practice/htaccess-301-redirect-non-www-to-www/): How to configure .htaccess RewriteCond/RewriteRule directives to redirect a non-www domain to its www version, or vice versa. - [INSERT, UPDATE, DELETE statements with Zend_Db](https://www.dotkernel.com/best-practice/insert-update-delete-statements-with-zend-db/): How to write INSERT, UPDATE, and DELETE (DML) statements using Zend_Db, alongside their equivalent raw SQL. - [SQL queries using Zend_Db – SELECT](https://www.dotkernel.com/best-practice/sql-queries-using-zend-db-select/): How to write SELECT queries with JOINs and WHERE IN clauses using Zend_Db, alongside their equivalent raw SQL. - [Subqueries with Zend_Db](https://www.dotkernel.com/best-practice/subqueries-with-zend-db/): How to build a query combining COUNT, LEFT JOIN, and GROUP BY across multiple tables using Zend_Db, including a subquery embedded as a column. -- [SVN Export in a virtual host](https://www.dotkernel.com/best-practice/svn-export-in-a-virtual-host/): How to export the contents of an SVN repository into a virtual host directory using the svn export command. -- [SVN keywords setup in PHP IDE ( Zend Studio)](https://www.dotkernel.com/best-practice/svn-keywords-setup-in-php-ide-zend-studio/): How to set SVN ignore, bug tracker, and svn:keywords properties per project in the Zend Studio PHP IDE. - [Using LIKE wildcards with Zend_Db](https://www.dotkernel.com/best-practice/using-like-wildcards-with-zend-db/): How to use the SQL LIKE condition and its _ and % wildcards, including NOT LIKE, with Zend_Db's quoteInto and quoteIdentifier methods. - [What are returning the FETCH functions from Zend_Db](https://www.dotkernel.com/best-practice/what-are-returning-the-fetch-functions-from-zend-db/): A side-by-side comparison of the legacy query()/next_record()/f() row-fetching style with the fetchAll, fetchAssoc, fetchCol, fetchOne, fetchPairs, and fetchRow methods of Zend_Db_Adapter_Abstract. - [Why use CURRENT_TIMESTAMP on a field that record date/time?](https://www.dotkernel.com/best-practice/why-use-current-timestamp-on-a-field-that-record-date-time/): Why a TIMESTAMP column should default to CURRENT_TIMESTAMP on insert, how ON UPDATE CURRENT_TIMESTAMP keeps it fresh on every update, and how the DEFAULT/ON UPDATE clause combinations behave. @@ -188,26 +127,18 @@ Content spans foundational PHP/middleware architecture (PSR-7, PSR-15, request l - [Shared Core Submodule in Dotkernel Headless Platform](https://www.dotkernel.com/headless-platform/shared-core-submodule-in-dotkernel-headless-platform/): An explanation of the Core submodule pattern in Dotkernel's Headless Platform, and step-by-step instructions for extracting it into a shared Git submodule. - [Version 7 adds PostgreSQL, Native UUID and PHP 8.5](https://www.dotkernel.com/headless-platform/version-7-adds-postgresql-native-uuid-and-php-8-5/): Overview of Dotkernel API and Admin's v7 release, which adds native UUID v7 support, PostgreSQL compatibility, PHP 8.5/8.4 support, and drops MySQL support. -## Zend Framework (8 posts) +## Zend Framework (2 posts) *Zend Framework 1 history and end-of-life notes* -- [Scienta ZF Debug Bar: A very helpfull ZF debug tool](https://www.dotkernel.com/zend-framework/scienta-zf-debug-bar-a-very-helpfull-zf-debug-tool/): A short note on discovering the Scienta ZF Debug Bar and Dotkernel's decision to replace its own basic debug bar with it. - [Sunsetting PEAR Channel for Zend Framework 1](https://www.dotkernel.com/zend-framework/sunsetting-pear-channel-for-zend-framework-1/): Dotkernel announces the sunsetting of its unofficial PEAR channel for Zend Framework 1, citing PHP 8 compatibility issues and aging server infrastructure. -- [WURFL PHP API libraries , GPL versions](https://www.dotkernel.com/zend-framework/wurfl-php-api-libraries-gpl-versions/): A brief announcement of GPL-licensed WURFL PHP API library versions, including which one Zend Framework's Zend_Http_UserAgent component uses, with a later edit noting the download's removal. - [Zend Framework 1 End-of-Life](https://www.dotkernel.com/zend-framework/zend-framework-1-end-of-life/): Announcement that Zend Framework 1 has reached End-of-Life (EOL) status following the release of Zend Framework 3, with security updates continuing only until 28 September 2016. -- [Zend Framework 1.12.4 Released with Security Fixes](https://www.dotkernel.com/zend-framework/zend-framework-1-12-4-released-with-security-fixes/): Matthew Weier O'Phinney announces Zend Framework 1.12.4, 2.1.6, and 2.2.6 with security updates, plus a follow-up 1.12.5 release fixing a backward compatibility issue. -- [Zend Framework 1.7.0 Released](https://www.dotkernel.com/zend-framework/zend-framework-1-7-0-released/): Short announcement of the Zend Framework 1.7.0 release, highlighting its new support for Adobe's Action Message Format (AMF) protocol in PHP 5 applications. -- [Zend Framework as PEAR accessible repository on Plesk server](https://www.dotkernel.com/zend-framework/zend-framework-as-pear-accessible-repository-on-plesk-server/): How to install Zend Framework as a PEAR-accessible repository on a Plesk server, so it doesn't need to be copied into every project and can be updated centrally. -- [Zend_Mail and Zend_Http Security Fixes in Zend Framework 1.12.12](https://www.dotkernel.com/zend-framework/zend-mail-and-zend-http-security-fixes-in-zend-framework-1-12-12/): Zend Framework 1.12.12 was released with security fixes for the Zend_Mail and Zend_Http components, and a follow-up 1.12.13 release soon after fixed a regression. -## Javascript (3 posts) +## Javascript (1 post) *frontend/JS topics* -- [Codelobster PHP Edition - Free PHP, HTML, CSS, JavaScript editor (IDE)](https://www.dotkernel.com/javascript/codelobster-php-edition-free-php-html-css-javascript-editor-ide/): An overview of Codelobster PHP Edition, a free multi-language code editor with autocompletion, debugging, SQL and FTP tools, and plugins for popular PHP frameworks and CMS platforms. - [Intro to jQuery](https://www.dotkernel.com/javascript/intro-to-jquery/): A short introduction to jQuery basics for early Dotkernel developers switching from Dojo, covering the jQuery object, selectors, DOM manipulation, events, and Ajax. -- [Javascript: Email Validator](https://www.dotkernel.com/javascript/javascript-email-validator/): A regex-based fix for email validation that allows the plus (+) and dash (-) characters in the appropriate parts of an email address. ## Middleware (3 posts) @@ -232,13 +163,6 @@ Content spans foundational PHP/middleware architecture (PSR-7, PSR-15, request l - [[FIX] Installing PEAR packages with PHP 7.2](https://www.dotkernel.com/php-troubleshooting/fix-installing-pear-packages-with-php-7-2/): How to fix the 'Cannot use result of built-in function in write context' PEAR error on PHP 7.2 by patching Archive_Tar's func_get_args() call, and how to reinstall the affected packages afterward. - [Where is the intl PHP extension? Problem solved!](https://www.dotkernel.com/php-troubleshooting/where-is-the-intl-php-extension-problem-solved/): Common causes of 'missing intl PHP extension' errors and step-by-step fixes for installing or enabling the Intl extension on Linux and Windows PHP setups. -## Android (2 posts) - -*Android install-referrer and broadcast receivers* - -- [Listen for Android install referrer](https://www.dotkernel.com/android/listen-for-android-install-referrer/): Android market broadcasts an intent containing referrer information at install time, before the app is opened, which can be used for install tracking. -- [Multiple broadcast receivers in the same app, for the same action](https://www.dotkernel.com/android/multiple-broadcast-receivers-in-the-same-app-for-the-same-action/): Using multiple broadcast receivers to listen separately for the same intent in the same Android app can lead to unexpected results, since one receiver may consume the broadcast and leave the others with nothing. - ## PHPStorm (1 post) *IDE setup* diff --git a/public/md-articles/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.md b/public/md-articles/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.md new file mode 100644 index 00000000..9ace04be --- /dev/null +++ b/public/md-articles/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.md @@ -0,0 +1,52 @@ +--- +title: "How to build this website starting from Dotkernel Light" +description: "How this blog itself came together: starting from the Dotkernel Light starter project, then following the Tutorial 101 to add Doctrine ORM and load real data into the database." +author: "stefan" +date_published: "2026-08-14" +canonical_url: "https://www.dotkernel.com/dotkernel/how-to-build-this-website-starting-from-dotkernel-light/" +category: "Dotkernel" +language: "en" +--- + +# How to build this website starting from Dotkernel Light + +## TL;DR + +This project started from the Dotkernel Light starter (Mezzio, Twig, FastRoute, PSR-7 via Laminas Diactoros) as a bare-bones website skeleton. +Following the official Tutorial 101, Doctrine ORM was added on top: entities for posts, categories, authors and tags, migrations to create the schema, and fixtures to load real content into the database. +The result is this: a Dotkernel Light project turned into a fully data-driven site. + +## Starting from Dotkernel Light + +This blog didn't start as a blog. It started as a bare [Dotkernel Light](https://docs.dotkernel.org/light-documentation/) installation — a minimal starter project built on Mezzio, with Twig for templating, FastRoute for routing, PSR-7 via Laminas Diactoros, and a PSR-11 container using Laminas Service Manager. No database, no posts, just the skeleton for a simple website. + +``` +git clone https://github.com/dotkernel/light.git dotkernel-light +``` + +At that point you have routing, templating and a working request lifecycle, but nothing to persist. Dotkernel Light is deliberately unopinionated about storage — it's up to the project to add a persistence layer if it needs one. + +## Adding Doctrine, following Tutorial 101 + +This project needed one: categories, authors, tags, and posts, all queryable and paginated. Rather than wiring Doctrine ORM in from scratch, the official [Tutorial 101](https://docs.dotkernel.org/tutorial-101/v1/introduction/) was followed, which walks through exactly this on top of a fresh Dotkernel Light install: + +1. Installing Doctrine ORM and wiring it into the container. +2. Defining entities and generating migrations to create the schema. +3. Loading fixture data and building the repositories/queries needed to list and display it. + +Following that path is what turned this project's `Category`, `Author`, `Tag` and `Post` entities, their migrations, and the repositories behind every listing and category page on this site into what they are now. + +## Where the data comes from + +The actual content — every article, its author, its category and tags — is authored as data in `src/App/src/Fixture/articles_cleaned.json` and loaded into the database with `php bin/doctrine-fixtures`. That file wasn't written from scratch: it was built from what already existed in dotkernel.com's own database, cleaned up and reshaped into fixture data so it could be loaded into this project's schema. Doctrine takes care of turning that into rows; the entities and repositories added while following Tutorial 101 take care of turning those rows back into the pages you're browsing right now. + +## FAQ + +**Q: What is Dotkernel Light?** +A: A minimal Mezzio-based starter project for building a simple website — routing (FastRoute), templating (Twig) and PSR-7 (Laminas Diactoros) out of the box, without a database layer. + +**Q: Why was Doctrine added on top?** +A: Dotkernel Light doesn't include persistence by default. This blog needed categories, authors, tags and posts stored and queried from a database, so Doctrine ORM was added following the official Tutorial 101. + +**Q: Where does the article content come from?** +A: From `src/App/src/Fixture/articles_cleaned.json`, loaded into the database via `php bin/doctrine-fixtures`. diff --git a/src/App/src/Fixture/articles_cleaned.json b/src/App/src/Fixture/articles_cleaned.json index 279de3ae..55e8834d 100644 --- a/src/App/src/Fixture/articles_cleaned.json +++ b/src/App/src/Fixture/articles_cleaned.json @@ -978,7 +978,7 @@ { "post_title": "Test article", "post_date": "2026-08-06 00:00:00", - "post_status": "publish", + "post_status": "draft", "author": { "display_name": "stefan", "github": "OStefan2001" @@ -988,6 +988,37 @@ "excerpt": "This is a test article used for fixture and testing purposes.", "tl_dr": "This is a test article added to the dotkernel category for testing purposes.", "tags": [] + }, + { + "post_title": "How to build this website starting from Dotkernel Light", + "post_date": "2026-08-14 00:00:00", + "post_status": "publish", + "author": { + "display_name": "stefan", + "github": "OStefan2001" + }, + "isObsolete": false, + "opengraph_img": null, + "excerpt": "How this blog itself came together: starting from the Dotkernel Light starter project, then following the Tutorial 101 to add Doctrine ORM and load real data into the database.", + "tl_dr": "This project started from the Dotkernel Light starter (Mezzio, Twig, FastRoute, PSR-7 via Laminas Diactoros) as a bare-bones website skeleton.\nFollowing the official Tutorial 101, Doctrine ORM was added on top: entities for posts, categories, authors and tags, migrations to create the schema, and fixtures to load real content into the database.\nThe result is this: a Dotkernel Light project turned into a fully data-driven site.", + "tags": [ + { + "name": "dotkernel light", + "slug": "dotkernel-light" + }, + { + "name": "doctrine", + "slug": "doctrine" + }, + { + "name": "tutorial 101", + "slug": "tutorial-101" + }, + { + "name": "getting started", + "slug": "getting-started" + } + ] } ] }, @@ -2875,4 +2906,4 @@ } ] } -] \ No newline at end of file +] diff --git a/src/Blog/templates/page/JSON-LD/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.jsonld.twig b/src/Blog/templates/page/JSON-LD/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.jsonld.twig new file mode 100644 index 00000000..1c05e3db --- /dev/null +++ b/src/Blog/templates/page/JSON-LD/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.jsonld.twig @@ -0,0 +1,51 @@ + diff --git a/src/Blog/templates/page/blog-resource/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.html.twig b/src/Blog/templates/page/blog-resource/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.html.twig new file mode 100644 index 00000000..0c4fedf6 --- /dev/null +++ b/src/Blog/templates/page/blog-resource/dotkernel/how-to-build-this-website-starting-from-dotkernel-light.html.twig @@ -0,0 +1,45 @@ +{% extends '@layout/blog-post.html.twig' %} + +{% block body %} +

This blog didn't start as a blog. It started as a bare Dotkernel Light installation — a minimal starter project built on Mezzio, with Twig for templating, FastRoute for routing, PSR-7 via Laminas Diactoros, and a PSR-11 container using Laminas Service Manager. No database, no posts, just the skeleton for a simple website.

+ +

Starting from Dotkernel Light

+

The setup itself is a single clone away:

+
git clone https://github.com/dotkernel/light.git dotkernel-light
+

At that point you have routing, templating and a working request lifecycle, but nothing to persist. Dotkernel Light is deliberately unopinionated about storage — it's up to the project to add a persistence layer if it needs one.

+ +

Adding Doctrine, following Tutorial 101

+

This project needed one: categories, authors, tags, and posts, all queryable and paginated. Rather than wiring Doctrine ORM in from scratch, the official Tutorial 101 was followed, which walks through exactly this on top of a fresh Dotkernel Light install:

+
    +
  1. Installing Doctrine ORM and wiring it into the container.
  2. +
  3. Defining entities and generating migrations to create the schema.
  4. +
  5. Loading fixture data and building the repositories/queries needed to list and display it.
  6. +
+

Following that path is what turned this project's Category, Author, Tag and Post entities, their migrations, and the repositories behind every listing and category page on this site into what they are now.

+ +

Where the data comes from

+

The actual content — every article, its author, its category and tags — is authored as data in src/App/src/Fixture/articles_cleaned.json and loaded into the database with php bin/doctrine-fixtures. That file wasn't written from scratch: it was built from what already existed in dotkernel.com's own database, cleaned up and reshaped into fixture data so it could be loaded into this project's schema. Doctrine takes care of turning that into rows; the entities and repositories added while following Tutorial 101 take care of turning those rows back into the pages you're browsing right now.

+ +

Frequently Asked Questions

+ +
+
+ What is Dotkernel Light? + +
+

A minimal Mezzio-based starter project for building a simple website — routing (FastRoute), templating (Twig) and PSR-7 (Laminas Diactoros) out of the box, without a database layer.

+
+
+
+ Why was Doctrine added on top? + +
+

Dotkernel Light doesn't include persistence by default. This blog needed categories, authors, tags and posts stored and queried from a database, so Doctrine ORM was added following the official Tutorial 101.

+
+
+
+ Where does the article content come from? + +
+

From src/App/src/Fixture/articles_cleaned.json, loaded into the database via php bin/doctrine-fixtures.

+
+
+
+{% endblock %}