Custom Field PHP Formatting
PHP based formatting provides a lot of flexibility for customizing the output of custom fields.
Overview
Output formatting for custom fields refer to the field output, rather than input presentation in forms. There are three types of customizable output formatting available:
Output Format
Allows using HTML and pre-defined tags to build simple layouts. Works in both standard and Early Access modes.
Blade Template Formatting (Early Access)
Template-based system using Blade syntax. Only available when the Early Access listing detail page is enabled.
PHP Based Formatting (Standard Mode)
Provides access to raw data for the field and the associated entry (listing or review) so you can create complex logic and mould the output to your specific needs. Only available when Early Access is disabled.
Choosing a Formatting Approach
| Approach | When to Use | Mode |
|---|---|---|
| Output Format | Simple HTML layouts with tags like {fieldtext}, {listing_id} |
Both |
| Blade Templates | Complex logic with Early Access listing detail page enabled | Early Access |
| PHP Format | Complex logic when Early Access is disabled | Standard |
The formatting options are located in Custom Fields → Edit Field → Advanced Settings tab.
Blade Template Formatting (Early Access)
When Early Access is enabled, the Advanced Settings tab shows two new options for custom field output:
- Blade template code - Code editor for writing Blade syntax directly (replaces "PHP output format")
- Field output Blade template - Dropdown to select pre-made Blade template files (replaces "Field output template")
Blade Template Code Setting
The "Blade template code" setting provides an inline editor where you can write Blade syntax directly. This is convenient for simpler formatting requirements.
Basic Example
<div class="custom-field-output">
{{ $data }}
</div>
With Conditionals
@if ($data)
<span class="field-value">{{ $data }}</span>
@else
<span class="no-value">Not specified</span>
@endif
Field Output Blade Template Setting
For more complex formatting, you can create template files and select them from the "Field output Blade template" dropdown.
Template files should be placed in your custom theme's fields_phpformat/ folder:
Joomla
templates/jreviews_overrides/views/themes/{your-theme}/fields_phpformat/my-template.blade.php
WordPress
jreviews_overrides/views/themes/{your-theme}/fields_phpformat/my-template.blade.php
After creating a template file, clear the file registry in JReviews administration to make it appear in the dropdown.
Available Variables (Blade)
The following variables are available within Blade templates:
| Variable | Description |
|---|---|
$data |
(mixed) For FormBuilder fields, JSON is already decoded into an array. For regular fields, equals $value. |
$value |
(mixed) Raw field value (same as PHP format $value) |
$field |
(array) Field configuration data |
$listing |
(object) Eloquent Listing model instance (for listing custom fields). Access properties with arrow syntax: $listing->title, $listing->featured |
$comment |
(object) Eloquent Comment model instance (for review custom fields). Access properties with arrow syntax: $comment->id, $comment->rating |
$route |
(object) Current route context |
$attributes |
(object) HTML attributes bag |
Blade Syntax Reference
Variable Output
{{ $data }} {{-- Escaped output --}}
{!! $data !!} {{-- Unescaped HTML output --}}
Conditionals
@if ($data)
...
@elseif ($condition)
...
@else
...
@endif
@isset($listing->title)
{{ $listing->title }}
@endisset
@empty($data)
No data available
@endempty
Loops
@foreach ($data as $item)
<div>{{ $item['name'] }}</div>
@endforeach
@forelse ($data as $item)
<div>{{ $item['name'] }}</div>
@empty
<p>No items found</p>
@endforelse
PHP Blocks
@php
$total = count($data);
$formatted = number_format($total);
@endphp
<span>Total: {{ $formatted }}</span>
Props Declaration
When creating template files, declare expected variables at the top:
@props(['data', 'listing' => null, 'comment' => null, 'route' => null])
<div data-formbuilder="inventory">
@foreach ($data as $item)
<div>{{ $item['name'] }}</div>
@endforeach
</div>
Blade Examples
Business Hours (Blade)
@php
$periods = $data['periods'] ?? $data;
$OpeningHours = (new OpeningHours())->addPeriods($periods);
$days = $OpeningHours->twentyfour(false)->getOrderedPeriods();
@endphp
<ul data-formbuilder="businesshours">
@foreach (range(1,7) as $dayNumber)
<li>
<span data-businesshours-day="{{ $dayNumber }}">
@lang('site.temporal.days_short.'.$dayNumber)
</span>
<span data-businesshours-hour-period>
@isset($days[$dayNumber])
{{ implode(', ', $days[$dayNumber]) }}
@else
@lang('site.status.closed')
@endisset
</span>
</li>
@endforeach
</ul>
Inventory List (Blade)
@props(['data', 'listing' => null])
<div data-formbuilder="inventory" class="grid gap-2">
@foreach ($data as $item)
<div class="flex justify-between p-2 border rounded">
<span>{{ $item['name'] }}</span>
<span class="font-bold">${{ number_format($item['price'], 2) }}</span>
</div>
@endforeach
</div>
Conditional Based on Listing Data (Blade)
@if ($listing && $listing->featured)
<div class="featured-badge">
<span>{{ $value }}</span>
<span class="badge">Featured</span>
</div>
@else
<span>{{ $value }}</span>
@endif
PHP Format System (Standard Mode)
When Early Access is disabled, the Advanced Settings tab shows the traditional PHP formatting options:
- PHP output format - Code editor for writing PHP code directly
- Field output template - Dropdown to select PHP template files
PHP Output Format Setting
With the PHP Output Format setting you can add write PHP code directly within the field's settings using the PHP editor.
It's important to note that the editor is ready for you to write PHP code without having to add an opening <?php tag. You can pass all your output into a variable and return it, or you can echo your variables.
Both of these are valid within the built-in editor:
Echoed Output
?>
<span>Label:</span> <span><?php echo $text; ?></span>
When using this option, you need to take into account that there is already an opening php tag, so if you want to add text or HTML code, you need to close it first.
Returned Output
return "<span>Label:</span> <span>{$text}</span>";
Field Output Template Setting
With template formatting you can create a custom template with your custom code and add the name of the template in the Template Name setting. Don't include the file extension, just the name.
While this approach requires a bit of extra work to create the template, it's also much easier to work with if your custom code is longer than a few lines. Template formatting also allows sharing a single template with multiple custom fields.
Any template file you create for custom field formatting goes inside your custom theme's fields_phpformat folder in overrides.
Joomla
templates/jreviews_overrides/views/themes/{your-theme}/fields_phpformat/
WordPress
jreviews_overrides/views/themes/{your-theme}/fields_phpformat/
Available Variables (PHP Format)
The following variables are available within the PHP format scope:
| Variables | Description |
|---|---|
$name |
(string) custom field name. |
$entry |
(array) associated listing or review. |
$listing |
(array) same as $entry and only available in listing custom fields. |
$review |
(array) same as $entry and only available in review custom fields. |
$field |
(array) field data |
$fields |
(array) fields data for $entry |
$value |
(mixed) selected field values. |
$text |
(mixed) current field text. |
$image |
(mixed) current field option image names |
$output |
(array) standard output |
$params |
(array) contains contextual page info useful to write custom logic. Keys in the array include route, controller, action, viewVars, viewSuffix, listview. |
$value,$textand$imagevariables are arrays for checkboxes and multiple select custom fields, and strings for all other fields.$valueand$textare identical for fields without pre-defined options (e.g. text, decimal, integer, etc)- The
CustomFieldsHelperPHP class is available in the PHP format scope by using the$CustomFieldsobject instance.
If you want to inspect the contents of any of the above variables you can use either the prx and dd functions in the code editor:
// Dumps the contents of the variable and stops code execution
dd($params);
// Outputs the contents of the variable and continues
prx($params);
Comparison: Blade vs PHP Format
The following table highlights the key differences between the two formatting systems:
| Aspect | Blade Templates (Early Access) | PHP Format (Standard) |
|---|---|---|
| Mode | Early Access ON | Early Access OFF |
| Data variable | $data (FormBuilder) or $value (regular fields) |
$text (raw string) |
| Output syntax | {{ $var }} |
<?php echo $var; ?> |
| Conditionals | @if ... @endif |
<?php if (...): ?> ... <?php endif; ?> |
| Loops | @foreach ... @endforeach |
<?php foreach (...): ?> ... <?php endforeach; ?> |
| FormBuilder JSON | Already decoded in $data |
Need json_decode($text, true) |
| File extension | .blade.php |
.thtml |
| Review variable | $comment (model) |
$review (array) |
| Listing access | $listing->title (model) |
$listing['Listing']['title'] (array) |
Side-by-Side Example
PHP Format (Standard Mode)
<?php
$inventory = json_decode($text, true);
?>
<div class="jrTableGrid">
<?php foreach ($inventory AS $item): ?>
<div class="jrRow">
<div class="jrCol"><?php echo $item['name'];?></div>
<div class="jrCol">$<?php echo $item['price'];?></div>
</div>
<?php endforeach;?>
</div>
Blade Template (Early Access)
@props(['data', 'listing' => null])
<div data-formbuilder="inventory" class="grid">
@foreach ($data as $item)
<div class="row">
<div>{{ $item['name'] }}</div>
<div>${{ $item['price'] }}</div>
</div>
@endforeach
</div>
Migration Guide
This section helps you migrate custom field formatting from PHP format to Blade templates when enabling Early Access.
Understanding the Scope
Who needs to migrate:
- Only users who have added custom code in individual custom field's Advanced Settings using the "PHP output format" editor or "Field output template" dropdown
- Fields without custom code in these settings continue working normally - no migration needed
- This is a per-field migration, not a site-wide change
What happens when you enable Early Access:
- "PHP output format" and "Field output template" settings are ignored
- Affected fields gracefully fall back to their "Output format" setting (the simpler HTML/tags option)
- No errors occur, but custom formatting is lost until migrated
- Fields without customizations in these settings are unaffected
Prerequisites
Before migrating:
- Backup your site - Ensure you have complete backups that can be restored
- Test on staging first - Never enable Early Access on production without testing
- Identify affected fields - Check each custom field's Advanced Settings for code in "PHP output format" or a selection in "Field output template"
- Document your custom code - Copy the existing PHP code for each affected field
Step-by-Step Conversion
-
Identify fields with custom formatting
- Go to Custom Fields in JReviews administration
- Open each field's settings and check the Advanced Settings tab
- Note which fields have code in "PHP output format" or a selection in "Field output template"
-
Copy existing PHP code
- For each affected field, copy the custom PHP code for reference
- Save it in a text file for the conversion process
-
Convert to Blade syntax
- Use the AI-Assisted Migration tool below, or
- Manually convert using the Common Patterns reference
-
Enable Early Access (on staging first)
- Enable the Early Access listing detail page in JReviews administration
-
Add converted code
- Open each affected custom field's settings
- Go to the Advanced Settings tab
- Paste the converted Blade code into "Blade template code", or
- Create a
.blade.phptemplate file and select it from "Field output Blade template"
-
Test thoroughly
- View listings that use the custom fields
- Verify the output matches your expectations
- Test different scenarios (empty data, multiple values, etc.)
Common Patterns
| PHP Format | Blade Format |
|---|---|
$text |
$data |
$review |
$comment |
json_decode($text, true) |
Use $data directly (already decoded) |
<?php echo $var; ?> |
{{ $var }} |
<?php if (...): ?> ... <?php endif; ?> |
@if (...) ... @endif |
<?php foreach (...): ?> ... <?php endforeach; ?> |
@foreach (...) ... @endforeach |
<?php ... ?> |
@php ... @endphp |
AI-Assisted Migration
You can use AI to help convert your PHP format code to Blade syntax. Copy the prompt below, paste it into Claude, ChatGPT, or your preferred AI assistant, and add your PHP code at the end.
AI Migration Prompt:
I need help converting JReviews custom field PHP format code to the new Blade template format.
## Context
When JReviews Early Access is enabled, the custom field formatting system changes:
- OLD: PHP format with `$text` variable containing raw data (JSON string for FormBuilder fields)
- NEW: Blade templates with `$data` or `$value` variable
## Variable Mappings
PHP Format (old) → Blade Format (new):
- `$text` → `$value` for regular fields, `$data` for FormBuilder fields (already decoded array)
- `$value` → `$value` (raw value, same in both)
- `$entry` → `$listing` or `$comment` (depending on context)
- `$review` → `$comment` (renamed, now an Eloquent model)
- `$field` → `$field` (same)
## IMPORTANT: Model Access Syntax
In Blade templates, `$listing` and `$comment` are Eloquent model instances, NOT arrays.
WRONG (array syntax):
- `$listing['title']`
- `$listing['featured']`
- `$comment['id']`
CORRECT (model syntax):
- `$listing->title`
- `$listing->featured`
- `$comment->id`
## Common Listing Properties
- `$listing->id` - Listing ID
- `$listing->title` - Listing title
- `$listing->alias` - URL alias
- `$listing->summary` - Summary text
- `$listing->description` - Full description
- `$listing->featured` - Featured status (boolean)
- `$listing->created` - Created date
- `$listing->updated` - Modified date
## Common Comment Properties
- `$comment->id` - Comment/Review ID
- `$comment->rating` - User rating
- `$comment->title` - Review title
- `$comment->comment` - Review text
- `$comment->created` - Created date
## Syntax Conversions
- `<?php ?> blocks` → `@php @endphp` (only when needed)
- `<?php echo $var; ?>` → `{{ $var }}`
- `<?php if (): ?> <?php endif; ?>` → `@if () @endif`
- `<?php foreach (): ?> <?php endforeach; ?>` → `@foreach () @endforeach`
- `json_decode($text, true)` → Use `$data` directly (already parsed for FormBuilder fields)
## Your Code to Convert
Please convert this PHP format code to Blade template format:
[PASTE YOUR PHP FORMAT CODE HERE]
After the AI converts your code, test it thoroughly on a staging site with Early Access enabled before using it on production.
Real Migration Examples
Inventory Field Migration
Before (PHP Format)
<?php
$inventory = json_decode($text, true);
?>
<div class="jrTableGrid">
<?php foreach ($inventory AS $item): ?>
<div class="jrRow">
<div class="jrCol"><?php echo $item['name'];?></div>
<div class="jrCol">$<?php echo $item['price'];?></div>
</div>
<?php endforeach;?>
</div>
After (Blade)
@props(['data', 'listing' => null])
<div data-formbuilder="inventory" class="grid">
@foreach ($data as $item)
<div class="row flex justify-between">
<div>{{ $item['name'] }}</div>
<div>${{ $item['price'] }}</div>
</div>
@endforeach
</div>
Authentication Conditional Migration
Before (PHP Format)
$auth = S2Object::make('auth');
return $auth->guest ? false : $output;
After (Blade)
@auth
{{ $data }}
@endauth
PHP Format Examples
The following examples apply to the PHP format system when Early Access is disabled.
- Default Output
- Hide Output
- Authentication Conditionals
- Show Ouput if More than One Option Selected
- Custom Images For Select List using Bannner
- Show Output Only When Another Field Option is Selected
- Concatenate Fields
- Hide Output Until Click
- Link to Listing Category
- Link to Other Listings By Same Owner
- Calculate Totals Sales Based on Price and Volume
- Calculate Age Based on Birth Date
Show Default Output
To show the default field output, return the $output array. This is useful when creating conditional logic to show a custom output in some instances, otherwise show the default output.
return $output;
Hide Output
To completely hide the field output, return a boolean false or a empty string.
return false;
Authentication Conditionals
For authentication conditionals, based on the logged in user, we use the auth service.
Hide Output for Guests
$auth = S2Object::make('auth');
return $auth->guest ? false : $output;
Show Log in Message to Guests
$auth = S2Object::make('auth');
return $auth->guest ? "Log in to view this field" : $output;
Show Ouput if More than One Option Selected
For checkbox and multiple select lists
$count = is_array($output) ? count($output) : 1;
return $count > 1 ? $output : false;
Custom Images For Select List using Bannner
The code below goes inside a banner custom field, and we use the output of a jr_city field to check the selected options.
$city = $CustomFields->fieldValue('jr_city',$entry);
switch($city) {
case 'san-francisco':
$banner = "sanfrancisco.jpg";
break;
case 'new-york':
$banner = "newyork.jpg";
break;
default: // All other cities display the default banner output
return $output;
break;
}
$banner = '/media/banners' . $banner;
return "<img src=".$banner." />";
Show Output Only When Another Selected
Checkbox and Multiple Select Lists
In this example, the field output is only shown when the email value is checked in the jr_checkbox field.
$checkboxes = $CustomFields->fieldValue('jr_checkbox',$entry);
return in_array('email',$checkboxes) ? $output : false;
Radiobutton and Single Select List
$selected = $CustomFields->fieldValue('jr_radio',$entry);
return $selected == 'yes' ? $output : false;
Concatenate Fields
Using a banner custom field to concatenate values with commas, or any other specific format, but not all fields are required.
$out = [];
$names = [
'jr_addressline1',
'jr_addressline2',
'jr_town',
'jr_city',
'jr_county',
'jr_postcode'
];
foreach ($names AS $name)
{
$out[] = $CustomFields->fieldValue($name, $entry);
}
$out = array_filter($out);
$out = implode(', ', $out);
return $out != '' ? $out : false;
Hide Output Until Click
The code below can be used with a text-based fields or fields with single choice selections (single select, radiobutton).
return '<span class="jrButton" data-value="'.$text.'" onclick="jQuery(this).html(jQuery(this).data(\'value\')).removeClass(\'jrButton\');">Click to reveal info</span>';
Link to Listing Category
$Routes = new RoutesHelper;
return $Routes->category($entry, $entry['Category']);
$Routes = new RoutesHelper;
$url = $Routes->category($entry, array('return_url'=>'true'));
return sprintf('<a href="%s">Custom Text</a>',$url);
Link to Other Listings By Same Owner
$Routes = new RoutesHelper;
return $Routes->myListings($entry['User']['name'], $entry['User']['user_id']);
Calculate Totals Sales Based on Price and Volume
Using a banner custom field.
$price = $CustomFields->fieldValue('jr_price',$entry);
$volume = $CustomFields->fieldValue('jr_volume',$entry);
$total = $price * $volume;
return $total;
If one of the values is zero, you can display the default output of the banner instead, or if you prefer to hide the output, return false instead.
$price = $CustomFields->fieldValue('jr_price',$entry);
$volume = $CustomFields->fieldValue('jr_volume',$entry);
$total = $price * $volume;
return $total > 0 ? $total : $output;
Calculate Age Based on Birth Date
$bday = new DateTime($text);
$today = new DateTime();
$diff = $today->diff($bday);
return $diff->y;