1. Go to this page and download the library: Download survos/field-bundle library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
survos / field-bundle example snippets
use Survos\FieldBundle\Attribute\Field;
use Survos\FieldBundle\Enum\Widget;
class Tenant
{
#[Field(searchable: true, sortable: true, order: 10)]
public string $name = '';
#[Field(filterable: true, widget: Widget::Select, facet: true, order: 20)]
public string $status = '';
#[Field(sortable: true, format: 'date', order: 30)]
public \DateTimeImmutable $createdAt;
}
use Survos\FieldBundle\Attribute\Field;
use Survos\FieldBundle\Enum\Widget;
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD)]
class Field
{
public function __construct(
?string $transKey = null, // translation key override (looked up in 'fields' domain)
bool $searchable = false, // ible = true, // show by default (false = hidden but toggleable)
int $order = 100, // column display position (lower = further left)
?string $width = null, // CSS width hint, e.g. '8rem'
?string $format = null, // display format: 'date', 'datetime', 'currency', etc.
) {}
}
use Survos\FieldBundle\Attribute\EntityMeta;
#[EntityMeta(
icon: 'mdi:building',
group: 'Content',
order: 10,
label: 'Tenant',
description: 'A workspace that can own projects and members.',
adminBrowsable: true,
)]
class Tenant { ... }
use Survos\FieldBundle\Attribute\RouteIdentity;
// Simple: single field
#[RouteIdentity(field: 'code')]
class Tenant implements RouteParametersInterface
{
use RouteIdentityTrait;
#[ORM\Column] public string $code;
}
// Nested: child entity walks the parent chain automatically
#[RouteIdentity(field: 'code', parents: ['tenant'], key: 'projectCode')]
class Project implements RouteParametersInterface
{
use RouteIdentityTrait;
#[ORM\ManyToOne] public Tenant $tenant;
#[ORM\Column] public string $code;
}
// $project->getRp() → ['tenantId' => 'acme', 'projectCode' => 'photo-archive']
// No manual merge — the parent chain resolves automatically.
use Survos\CoreBundle\Entity\RouteParametersInterface;
use Survos\FieldBundle\Attribute\RouteIdentity;
use Survos\FieldBundle\Entity\RouteIdentityTrait;
#[RouteIdentity(field: 'id')]
class Image implements RouteParametersInterface
{
use RouteIdentityTrait;
#[ORM\Id]
#[ORM\Column(length: 26)]
public string $id;
}
#[Route('/image/{imageId}')]
final class ImageController extends AbstractController
{
#[Route('/show', name: 'image_show')]
public function show(Image $image): array
{
return ['image' => $image];
}
}
#[RouteIdentity(field: 'code', key: 'intakeCode', parents: ['tenant'])]
class Intake implements RouteParametersInterface
{
use RouteIdentityTrait;
}
#[Route('/{tenantId}/i/{intakeCode}')]
final class IntakeController extends AbstractController
{
#[Route('/show', name: 'intake_show')]
public function show(Intake $intake): array
{
return ['intake' => $intake];
}
}
// Before (core-bundle)
class Owner implements RouteParametersInterface
{
use RouteParametersTrait;
public const array UNIQUE_PARAMETERS = ['ownerId' => 'code'];
}
// After (field-bundle)
#[RouteIdentity(field: 'code')]
class Owner implements RouteParametersInterface
{
use RouteIdentityTrait;
}
use Survos\FieldBundle\Attribute\RouteMeta;
use Survos\FieldBundle\Enum\Audience;
use Survos\FieldBundle\Enum\Purpose;
#[Route('/tenant/{tenantId}', name: 'tenant_show')]
#[RouteMeta(
description: 'Public overview page for a tenant.',
entity: Tenant::class,
purpose: Purpose::Show,
audience: Audience::Public,
sitemap: true,
changefreq: 'weekly',
)]
public function show(Tenant $tenant): array { ... }
use Survos\FieldBundle\Attribute\ControllerMeta;
#[Route('/tenant/{tenantId}')]
#[ControllerMeta(entity: Tenant::class, audience: Audience::Authenticated)]
final class TenantController extends AbstractController
{
#[Route('', name: 'tenant_show')]
#[RouteMeta(description: 'Tenant detail page', purpose: Purpose::Show, audience: Audience::Public)]
public function show(Tenant $tenant): array { ... }
// Inherits entity: Tenant::class, audience: Audience::Authenticated from ControllerMeta
#[Route('/edit', name: 'tenant_edit')]
#[RouteMeta(description: 'Edit tenant settings', purpose: Purpose::Edit)]
public function edit(Tenant $tenant, Request $request): array|RedirectResponse { ... }
}
use Survos\FieldBundle\Service\FieldReader;
use Survos\FieldBundle\Model\FieldDescriptor;
class MyService
{
public function __construct(private readonly FieldReader $fieldReader) {}
public function buildSearchConfig(string $class): array
{
$descriptors = $this->fieldReader->getDescriptors($class);
return [
'searchable' => array_map(fn (FieldDescriptor $d) => $d->name,
array_filter($descriptors, fn ($d) => $d->searchable)),
'sortable' => array_map(fn (FieldDescriptor $d) => $d->name,
array_filter($descriptors, fn ($d) => $d->sortable)),
];
}
// Get a single property descriptor
public function getLabel(string $class, string $property): string
{
$d = $this->fieldReader->getDescriptor($class, $property);
return $d?->getFallbackLabel() ?? $property;
}
}
$d->getTranslationKey() // transKey ?? name
$d->getTranslationDomain() // 'fields' (always)
$d->getFallbackLabel() // TitleCase of name, e.g. 'accountType' → 'Account Type'
$d->resolvedWidget() // widget ?? inferred from type (null when not filterable)
$d->inputType() // HTML input type: 'email'|'url'|'number'|'datetime-local'|'text'
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.