Skip to content
Grav 2.0 is officially stable. Read the announcement →

Community guidelines

Please keep discussions civil and on-topic. Repeated violations may lead to a temporary ban.

General

Twig template not showing content of yaml file from themes directory

Started by b 1 year ago · 1 replies · 57 views
1 year ago

okay i have a form to save a yaml file to my themes directory with order information in it. the form saves the file into my themes directory at /user/themes/sr/data/orders/{{ grav.user.username }}.yaml that is working using a plugin i created called ordersaver. i do not for the life of me can figure out how to display the order information from that yaml file in a twig template called orders. I can get the twig template called orders to show the contents if the orders are in the page frontmatterpage.header.orders of the page .md file but does NOT showing from the themes .yaml file i mentioned earlier. I will post my code below the plugin .php file and the order-form for submitting the order data in pages frontmatter and finnally the template twig file for rendering the order data. i have done plenty of troubleshooting and am able to get the resloved path to show correctly my twig template is finding the .yaml file in my themes folder but will not render the darn contents of the file. another thing is that all orders will be placed in this themes folder and the twig template will loop through finding orders with the logged in users name to know which details to display from the file.

odersaver.php

PHP

<?php
namespace Grav\Plugin;

use Composer\Autoload\ClassLoader;
use Grav\Common\Filesystem\Folder;
use Grav\Common\Grav;
use Grav\Common\Page\Page;
use Grav\Common\Plugin;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\File\YamlFile;
use Symfony\Component\Yaml\Yaml;

class OrdersaverPlugin extends Plugin
{
public static function getSubscribedEvents(): array
{
return [
// For general plugin initialization
'onPluginsInitialized' => [
// Uncomment next line if needed for Grav < 1.7
// ['autoload', 100000],
['onPluginsInitialized', 0]
],
// For form processing logic
'onFormProcessed' => ['onFormProcessed', 0]
];
}

PHP
/**
 * Optional: Composer autoload
 */
public function autoload(): ClassLoader
{
    return require __DIR__ . '/vendor/autoload.php';
}

public function onPluginsInitialized(): void
{
    // Skip execution in the admin panel
    if ($this->isAdmin()) {
        return;
    }

    // Enable any future front-end events if needed
    $this->enable([
        // Future front-end events can go here
    ]);
}

/**
 * Custom form action handler to append order data to a single YAML file
 */
public function onFormProcessed(Event $event): void

{
$action = $event['action'];
$form = $event['form'];

PHP
if ($action !== 'saveOrderToThemeYaml') {
    return;
}

$user = $this->grav['user'];
if (!$user || !$user->authenticated) {
    return;
}

$username = $user->username;
$data = $form->getData()->toArray();

$data['user'] = $username;
$data['date'] = date('Y-m-d');
$data['orderid'] = uniqid();

$theme = $this->config->get('system.pages.theme');
$file = GRAV_ROOT . "/user/themes/{$theme}/data/orders/{$username}.yaml";

$existing = [];
if (file_exists($file)) {
    $existing = Yaml::parse(file_get_contents($file)) ?? [];
}

$existing[] = $data;

file_put_contents($file, Yaml::dump($existing, 10, 2));

}
}

TXT

> order-form

title: 'Place Order'
form:
name: order
fields:

YAML
        type: section
        title: 'Shipping Address'
        underline: true
    -
        name: shipping_address.name
        type: text
        label: 'Recipient Name'
    -
        name: shipping_address.phone
        type: text
        label: 'Phone Number'
    -
        name: shipping_address.street
        type: text
        label: 'Street Address'
    -
        name: shipping_address.city
        type: text
        label: City
    -
        name: shipping_address.state
        type: text
        label: State
    -
        name: shipping_address.postal_code
        type: text
        label: 'Postal Code'
    -
        name: shipping_address.country
        type: text
        label: Country
    -
        type: section
        title: 'Order Details'
        underline: true
    -
        name: total_amount
        type: number
        label: 'Total Amount'
    -
        name: currency
        type: text
        label: Currency
        default: USD
    -
        name: payment_method
        type: text
        label: 'Payment Method'
        default: Stripe
    -
        name: tracking_number
        type: text
        label: 'Tracking Number'
    -
        name: notes
        type: textarea
        label: Notes
buttons:
    -
        type: submit
        value: Send
process:
    -
        saveOrderToThemeYaml: true
    -
        message: 'Order submitted!'
    -
        redirect: /orders

twig_first: true
never_cache_twig: true
cache_enable: false
visible: true

TXT

> twig template

{% extends 'partials/base.html.twig' %}

{% block content %}
<section class="section">
<div class="container">
<h1 class="title">My Orders</h1>

TWIG
{% set user_orders = [] %}

{# Load orders from the theme directory #}
{% set order_data = yaml('theme://data/orders/' ~ grav.user.username ~ '.yaml') %}

{% for order in order_data %}
  {% if order.user == grav.user.username %}
    {% set user_orders = user_orders|merge([order]) %}
  {% endif %}
{% endfor %}

{% if user_orders|length > 0 %}
  {% for order in user_orders %}
    <div class="box mb-5">
      <h2 class="subtitle">Order #{{ order.orderid }}</h2>
      <p><strong>Status:</strong> {{ order.status }}</p>
      <p><strong>Date:</strong> {{ order.date }}</p>
      <p><strong>Total:</strong> {{ order.total_amount }} {{ order.currency }}</p>
      <p><strong>Payment Method:</strong> {{ order.payment_method }}</p>
      <p><strong>Tracking Number:</strong> {{ order.tracking_number }}</p>

      <h3 class="subtitle is-6 mt-4">Shipping Address</h3>
      <ul>
        <li>{{ order.shipping_address.name }}</li>
        <li>{{ order.shipping_address.street }}</li>
        <li>{{ order.shipping_address.city }}, {{ order.shipping_address.state }} {{ order.shipping_address.postal_code }}</li>
        <li>{{ order.shipping_address.country }}</li>
        <li>Phone: {{ order.shipping_address.phone }}</li>
      </ul>

      {% if order.notes %}
        <p class="mt-3"><strong>Notes:</strong> {{ order.notes }}</p>
      {% endif %}

      <h3 class="subtitle is-6 mt-4">Items</h3>
      <table class="table is-fullwidth is-bordered is-striped">
        <thead>
          <tr>
            <th>Name</th>
            <th>Category</th>
            <th>SKU</th>
            <th>Price</th>
            <th>Qty</th>
            <th>Subtotal</th>
          </tr>
        </thead>
        <tbody>
          {% for item in order.items %}
            <tr>
              <td>{{ item.name }}</td>
              <td>{{ item.category }}</td>
              <td>{{ item.sku }}</td>
              <td>{{ item.price }}</td>
              <td>{{ item.quantity }}</td>
              <td>{{ (item.price * item.quantity)|number_format(2, '.', '') }}</td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
  {% endfor %}
{% else %}
  <p class="has-text-grey">You have no orders yet.</p>
{% endif %}

</div>
</section>
{% endblock %}

YAML

> saved yaml file in themes folder i am trying to display in the twig

0:
  shipping_address:
    name: asd
    phone: asd
    street: asd
    city: asd
    state: asd
    postal_code: asdasd
    country: asdas
  total_amount: 2322
  currency: USD
  payment_method: Stripe
  tracking_number: asdasd
  notes: asdasd
  user: digital1
  date: '2025-05-03'
  orderid: 6816f538cad20

last edited 05/04/25 by b
1 year ago

here is working twig template with the orders palced in the pages frontmatter so you can see what the end goal is here...

Basically i want the orders data placed in a file in my themes folder and then use my twig template to iterate over the orders and pull orders matching the logged in user to display past orders.

orders page frontmatter

YAML
title: Orders
twig_first: true
never_cache_twig: true
cache_enable: false
visible: true
access:
site.login: true
orders:
-
user: digital1
orderid: '12345'
date: '2025-04-20'
status: Completed
total_amount: 1039.99
currency: USD
payment_method: Stripe
tracking_number: TRACK123456789
items:
-
name: Laptop
price: 999.99
quantity: 1
-
name: Mouse
price: 20
quantity: 2
shipping_address:
name: 'John Doe'
phone: '+1 555-123-4567'
street: '123 Main Street'
city: 'Los Angeles'
state: CA
country: USA
postal_code: '90001'
notes: 'Leave package at the front door.'
-
user: digital1
orderid: '12345'
date: '2025-04-20'
status: Completed
total_amount: 1039.99
currency: USD
payment_method: Stripe
tracking_number: TRACK123456789
items:
-
name: Laptop
price: 999.99
quantity: 1
-
name: Mouse
price: 20
quantity: 2
shipping_address:
name: 'John Doe'
phone: '+1 555-123-4567'
street: '123 Main Street'
city: 'Los Angeles'
state: CA
country: USA
postal_code: '90001'
notes: 'Leave package at the front door.'

orders.html.twig

TWIG

{% extends 'partials/base.html.twig' %}

{% block content %}
<section class="section">
<div class="container">
<h1 class="title">My Orders</h1>

TWIG
{% set user_orders = [] %}

{% for order in page.header.orders %}
  {% if order.user == grav.user.username %}
    {% set user_orders = user_orders|merge([order]) %}
  {% endif %}
{% endfor %}
{% if user_orders|length > 0 %}
  {% for order in user_orders %}
    <div class="box mb-5">
      <h2 class="subtitle">Order #{{ order.orderid }}</h2>
      <p><strong>Status:</strong> {{ order.status }}</p>
      <p><strong>Date:</strong> {{ order.date }}</p>
      <p><strong>Total:</strong> {{ order.total_amount }} {{ order.currency }}</p>
      <p><strong>Payment Method:</strong> {{ order.payment_method }}</p>
      <p><strong>Tracking Number:</strong> {{ order.tracking_number }}</p>

      <h3 class="subtitle is-6 mt-4">Shipping Address</h3>
      <ul>
        <li>{{ order.shipping_address.name }}</li>
        <li>{{ order.shipping_address.street }}</li>
        <li>{{ order.shipping_address.city }}, {{ order.shipping_address.state }} {{ order.shipping_address.postal_code }}</li>
        <li>{{ order.shipping_address.country }}</li>
        <li>Phone: {{ order.shipping_address.phone }}</li>
      </ul>

      {% if order.notes %}
        <p class="mt-3"><strong>Notes:</strong> {{ order.notes }}</p>
      {% endif %}

      <h3 class="subtitle is-6 mt-4">Items</h3>
      <table class="table is-fullwidth is-bordered is-striped">
        <thead>
          <tr>
            <th>Name</th>
            <th>Category</th>
            <th>SKU</th>
            <th>Price</th>
            <th>Qty</th>
            <th>Subtotal</th>
          </tr>
        </thead>
        <tbody>
          {% for item in order.items %}
            <tr>
              <td>{{ item.name }}</td>
              <td>{{ item.category }}</td>
              <td>{{ item.sku }}</td>
              <td>{{ item.price }}</td>
              <td>{{ item.quantity }}</td>
              <td>{{ (item.price * item.quantity)|number_format(2, '.', '') }}</td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
  {% endfor %}    {% else %}
  <p class="has-text-grey">You have no orders yet.</p>
{% endif %}

</div>
</section>
{% endblock %}

TXT

Suggested topics

Topic Participants Replies Views Activity
General · by Jerry Hunt, 4 days ago
2 101 16 hours ago
General · by pamtbaau, 22 hours ago
1 68 21 hours ago
General · by Andy Miller, 1 day ago
0 53 1 day ago
General · by Marcel, 12 months ago
6 361 5 days ago
General · by Duc , 6 days ago
3 49 6 days ago