$db field not returning value in template

In my static $db array I have 14 fields. All of them contain a value and all but one display their respective values in the template.ss file as expected. The exception being ‘MonthHash’

$db array:

The value for this field is created from within an onBeforeWrite method (as are other fields):

In the CMS I’m also printing the values to a ‘ReadonlyField’ so I can be sure a value was created:

Which displays as expected when the record is created:

In my template.ss file I’m referencing that field {$MonthHash}:

But the result is always empty on the front end:
6results

I have even tried just placing $MonthHash on it’s own line, by itself in the template and I still get nothing. When I replace $MonthHash with any other value from the $db array that value displays as expected.

What could I possibly be doing wrong? Any help would be appreciated.

What do you see if you add the following in your Product.php controller

use SilverStripe\Dev\Debug;

Debug::show($this);

It would be good to see your whole template.ss file too.

Is MonthHash a function anywhere in your code?

Have you tried all the usual things e.g. dev/build/?flush=1

Thanks for your reply. I still have not solved this issue. My code below as well as a screenshot of the pertinent cols in my db.

The pertinent parts are:
In Product.php I’m creating a default record inside an onBeforeWrite() method.

$this->MonthHash = hash_hmac(‘sha256’, $prodcode.‘sub_frequency1m’, $apiKey);

Then in Product.ss I’m calling that record in my select menu:

    <select name="sub_frequency">
        <option value>One-time</option>
        <option value="1m||{$MonthHash}">Monthly Subscription</option>
    </select>

And as you can see that record is in fact in my db:

And again, ALL other records from that table are successfully being inserted into the template when the page loads in the browser. Only the $MonthHash fails to be inserted. I can even move $MonthHash to it’s own line in the template and it never gets populated.

And yes, I’ve /dev/build?flush=1 many times.

I fell like I’m missing something really obvious.

Thanks for your help.

Product.php
<?php
use SilverStripe\ORM\DataObject;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\OptionsetField;
use SilverStripe\Forms\ListboxField;
use SilverStripe\Assets\Image;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\Forms\ReadonlyField;
use SilverStripe\Forms\LiteralField;

class Product extends Page {
    private static $db = [
        'Price'        => 'Decimal',
        'Weight'       => 'Decimal',
        'Measure'      => 'Varchar(4)',
        'ProdCode'     => 'Varchar(25)',
        'Type'         => 'Enum(array("Sticks","Biscuits","Toppings","Variety"))',
        // Hashes
        'TitleHash'    => 'Varchar(64)',
        'PriceHash'    => 'Varchar(64)',
        'ProdCodeHash' => 'Varchar(64)',
        'ProdImgHash'  => 'Varchar(64)',
        'QuantityHash' => 'Varchar(64)',
        'ShipHash'     => 'Varchar(64)',
        'SubHash'      => 'Varchar(64)',
        'DefHash'      => 'Varchar(64)',
        'MonthHash'    => 'Varchar(64)'
    ];

    private static $has_one = [
        'ProductImage' => Image::class
    ];

    private static $many_many = [
        'Recipes'      => Recipe::class
    ];

    private static $owns = [
        'ProductImage'
    ];

    private static $default_parent = 'ProductHolder';

    public function onBeforeWrite() {
        parent::onBeforeWrite();
        // get api key
        $siteConfig         = SiteConfig::current_site_config();
        $apiKey             = $siteConfig->FoxyAPI;
        $servername         = 'https://'.$_SERVER['SERVER_NAME'].'/';
        // get image url
        if(DataObject::get_by_id(Image::class, $this->ProductImageID)) {
            $prodimg        = DataObject::get_by_id(Image::class, $this->ProductImageID);
            $prodfilename   = $prodimg->Filename;
            $prodimgurl     = $servername.$prodfilename;
        } else {
            // create empty var when page is instantiated to prevent CMS errors
            $prodimgurl = '';
        }
        // get form data
        $prodcode           = $this->ProdCode;
        $price              = $this->Price;
        $title              = $this->Title;
        // create hashes
        $this->TitleHash    = hash_hmac('sha256', $prodcode.'name'.$title, $apiKey);
        $this->PriceHash    = hash_hmac('sha256', $prodcode.'price'.$price, $apiKey);
        $this->ProdCodeHash = hash_hmac('sha256', $prodcode.'code'.$prodcode, $apiKey);
        $this->ProdImgHash  = hash_hmac('sha256', $prodcode.'image'.$prodimgurl, $apiKey);
        $this->QuantityHash = hash_hmac('sha256', $prodcode.'quantity--OPEN--', $apiKey);
        $this->ShipHash     = hash_hmac('sha256', $prodcode.'shipto--OPEN--', $apiKey);
        $this->DefHash      = hash_hmac('sha256', $prodcode.'category'.'DEFAULT', $apiKey);
        $this->SubHash      = hash_hmac('sha256', $prodcode.'category'.'SUBSCRIPTIONS', $apiKey);
        $this->MonthHash    = hash_hmac('sha256', $prodcode.'sub_frequency1m', $apiKey);
    }

    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields->addFieldToTab('Root.Main', OptionsetField::create('Type', 'Type',
            $this->dbObject('Type')->enumValues()), 'Content');
        $fields->addFieldToTab('Root.Recipes',
            ListboxField::create(
                'Recipes',
                'Recipes',
                Recipe::get()
            )
        );
        // Shopping cart data
        $fields->addFieldToTab('Root.CartData', TextField::create('ProdCode', 'Product Code'));
        $fields->addFieldToTab('Root.CartData', TextField::create('Price', 'Price $'));
        $fields->addFieldToTab('Root.CartData', TextField::create('Weight', 'Weight'));
        $fields->addFieldToTab('Root.CartData', OptionsetField::create('Measure', 'Measure',
            [
                'oz'   => 'oz',
                'lb'   => 'lb',
                'each' => 'each'
            ]
        ));
        $fields->addFieldToTab('Root.CartData', $prodImg = UploadField::create('ProductImage', 'Product Image (1000x750, .jpg, .gif or .png only)'), 'Content');
        $prodImg->setFolderName('Product Images')->getValidator()->setAllowedExtensions = ['jpg', 'jpeg', 'gif', 'png'];
        // Hashes - read only
        $fields->addFieldToTab('Root.CartData', LiteralField::create('ReadOnly', 'These values are read-only. They are provided for troubleshooting purposes only.'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('TitleHash', 'Title Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('PriceHash', 'Price Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('ProdCodeHash', 'Product Code Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('ProdImgHash', 'Image URL Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('QuantityHash', 'Quantity Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('ShipHash', 'Ship-to Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('DefHash', 'Default Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('SubHash', 'Subscription Hash'));
        $fields->addFieldToTab('Root.CartData', ReadonlyField::create('MonthHash', 'Month Hash'));
        return $fields;
    }
}

Product.ss
The forum refuses to allow me to paste in my code even using the preformat tool, so here’s a Pastebin link. Sorry.
Product.ss (https://pastebin.com/a9h70qUk) Line 29

Nothing obvious is jumping out to me either…

As a quick test, have you tried changing the field name to something else? (eg. MyMonthHash) You might have found some weird reserved / in-use variable collision.

You could also maybe try your own getter for the field… again, you might have hit some weird pre-existing magic function somehwere:

public function getSafeMonthHash() {
  return $this->MonthHash;
}

Then in the template just change to $SafeMonthHash

Long-shots, but you never know!

Did you say putting it on a line on its own didn’t work?

It’s the only variable in the template with a number value preceding it… I wonder if the double pipe is being parsed as an ‘OR’ operation and hence not rendering something due to the 1 at the start.

OK…I’m choosing this answer as the “solution” because it led me to the fix, but I suspect there was an issue I couldn’t see.

I’m a stickler for cleanly formatted code (uniform indentation, 4 spaces vs. tabs, etc…sorry tabs people!) and I just happened to notice in my Pastbin that there was some non uniform indentation starting on line 12. I simply removed lines 12-34, pasted them into a new document, removed all spaces, reformatted, pasted the code back into the template, ran /dev/build and bam! Works like expected.

I’m guessing hidden character? Tag out of place? Aliens?

Anyway, it’s working now.

Thanks @Jellygnite and @Tim for your time looking and your responses. Tonight, somewhere in California some dude you don’t know is going to raise a glass of Bourbon in your honor.

Cheers,
Chris

1 Like