Skip to content

Own columns

When no format of the TextColumn fits, write a column type of your own, e.g. a rating with stars. Pictures and progress bars are built in: ImageColumn and ProgressColumn.

Terminal window
php spark make:anvil-column Rating
namespace App\Columns;
use Anvil\Collection\Columns\Column;
final class Rating extends Column
{
public function text(array|object $record): string
{
return $this->stars($record) . ' / 5';
}
public function html(array|object $record): string
{
$stars = $this->stars($record);
// Escape every value, also numbers: the code stays safe when it changes.
return '<span class="text-warning" aria-hidden="true">' . str_repeat('★', $stars) . str_repeat('☆', 5 - $stars) . '</span>'
. '<span class="visually-hidden">' . esc($this->text($record)) . '</span>';
}
public function exportValue(array|object $record): int
{
return $this->stars($record);
}
private function stars(array|object $record): int
{
$value = $this->value($record);
return max(0, min(5, is_numeric($value) ? (int) $value : 0));
}
}
Rating::make('rating')->label('Rating')->sortable(),
Method Purpose
text($record) the value as plain text (required); used for search hits, titles, cards and – by default – exports
html($record) the value as safe HTML for table and cards; default: escaped text(). Escape every value with esc()
exportValue($record) value for exports; return numbers as numbers; default: text() or null
prepare(Resource $resource, array $records) called once per page with the shown records before rendering, e.g. to load related data in one query (see CountColumn)
value($record) the raw value: state() or the attribute of the column name
render($record) final: html() plus link, icon and colour – what tables and cards show; use it in own card views

All options of every column come from Column and work unchanged: labels, sorting, searching, state(), color(), icon(), description(), link().

  • html() must return safe HTML. Never put a value into markup without esc(): text content with esc($value), attributes with esc($value, 'attr') – as in the example, also for numbers that cannot contain markup today.
  • No inline styles or scripts: the Content Security Policy blocks them. Use classes of Bootstrap or of your own stylesheet.
  • Load related data in prepare(), not per row in html().
  • Respect permissions: data from other tables must be read through their resource or with the same checks.

More on generators and own building blocks: Extending Anvil.