How to fetch data from database in Laravel 8 Jetstream register page? - laravel-blade

So I have a model named Role. I want to show a dropdown where the roles are visible from the Role model. How can I get all the data from the roles model in my registration page? I want to show them on a dropdown select menu. My question is how to get data from the Role Model in my register.blade.php file?
Below is my CreateNewUser.php code-
public function create(array $input)
{
dd($input);
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'business_name' => ['required', 'string', 'max:255'],
'category_id' => ['required'],
'role_id' => ['required'],
'phone' => ['required', 'string', 'regex:/(01)[0-9]{9}/','max:11','unique:users'],
'address' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
])->validate();
return User::create([
'name' => $input['name'],
'business_name' => $input['business_name'],
'category_id' => $input['category_id'],
'role_id' => $input['role_id'],
'phone' => $input['phone'],
'address' => $input['address'],
'email' => $input['email'],
'password' => Hash::make($input['password'])
]);
}

Jetstream I think use Fortify package for auth backend logic. So, if this is the case you must have in App\Providers\JetstreamServiceProvider
public function boot()
{
Fortify::registerView(function () {
return view('auth.register');
});
}
then in this you can pass the data to the register view like:
public function boot()
{
Fortify::registerView(function () {
$roles = Role::all();
return view('auth.register',compact('roles'));
});
}
add in the register view the select element
//.....
<select name="role_id">
<option value="">Select</option>
#foreach($roles as $item)
<option value="{{ $item->id }}">{{ $item->name }}</option>
#endforeach
</select>
//.....

Related

Sonata ModelAutocompleteType result affected by getFilterParameters

I have this form field of a type ModelAutocompleteType that is supposed to show the result filtered by the "search" datagrid field of related admin:
class OperationAdmin extends AbstractAdmin
{
// ...
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('business', ModelAutocompleteType::class, [
'label' => 'Business',
'property' => 'search'
]);
}
// ...
}
In this related "business" admin I have few filters defined as:
class BusinessAdmin extends AbstractAdmin
{
// ...
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('search', CallbackFilter::class, [
'label' => 'Search',
'show_filter' => true,
'advanced_filter' => false,
'callback' => function($qb, $alias, $field, $value) {
if (!$value['value']) return;
// ...
return true;
}
])
->add('state', ChoiceFilter::class, [
'label' => 'State',
'show_filter' => true,
'advanced_filter' => false,
'field_options' => ['choices' => Business::STATES],
'field_type' => 'choice'
]);
}
// ...
}
Now, if I set the default "state" datagrid field value using getFilterParameters to filter business list by state on initial page load:
public function getFilterParameters()
{
$this->datagridValues = array_merge([
'state' => ['type' => '', 'value' => 'active']
], $this->datagridValues);
return parent::getFilterParameters();
}
The related ModelAutocompleteType form field's result will also be filtered by "state" field even tho it's property is set to search.
How do I apply default filter values JUST to list view and nothing else? And why ModelAutocompleteType result depends on other datagrid fields even tho property is set to one?
In the end I left getFilterParameters method in to filter list by default, which is what I wanted:
public function getFilterParameters()
{
$this->datagridValues = array_merge([
'state' => ['type' => '', 'value' => 'active']
], $this->datagridValues);
return parent::getFilterParameters();
}
Unfortunatelly, that was also affecting ModelAutocompleteFilter and ModelAutocompleteType results, filtering them by 'active' state too, which I did not want.
To solve that I had to pass a callback property to ModelAutocompleteType field, to reset datagrid state value:
class OperationAdmin extends AbstractAdmin
{
// ...
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('business', ModelAutocompleteType::class, [
'label' => 'Business',
'property' => 'search',
'callback' => [$this, 'filterAllBusinessesCallback']
]);
}
public function filterAllBusinessesCallback(AdminInterface $admin, $property, $value)
{
$datagrid = $admin->getDatagrid();
$datagrid->setValue($property, null, $value);
$datagrid->setValue('state', null, null);
}
// ...
}

How can I change error message in Symfony

I create a form and then when I click on submit button, show this error message:
Please select an item in the list.
How can I change this message and style it ( with CSS )?
Entity:
...
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank(message="Hi user, Please select an item")
*/
private $name;
...
Controller:
...
public function index(Request $request)
{
$form = $this->createForm(MagListType::class);
$form->handleRequest($request);
return $this->render('index.html.twig', [
'form' => $form->createView()
]);
}
...
Form:
...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', EntityType::class,[
'class' => InsCompareList::class,
'label' => false,
'query_builder' => function(EntityRepository $rp){
return $rp->createQueryBuilder('u')
->orderBy('u.id', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'id',
'required' => true,
])
->add('submit', SubmitType::class, [
'label' => 'OK'
])
;
...
}
In order to use custom messages, you have to put 'novalidate' on your HTML form. For example:
With Twig:
{{ form_start(form, {attr: {novalidate: 'novalidate'}}) }}
{{ form_widget(form) }}
{{ form_end(form) }}
Or in your controller:
$form = $this->createForm(MagListType::class, $task, array( //where task is your entity instance
'attr' => array(
'novalidate' => 'novalidate'
)
));
This Stackoverflow answer has more info on how to use novalidate with Symfony. You can also check the docs for more info.
As for the styling, you can use JavaScript to trigger classes, which you can then style in your CSS, like in this example taken from Happier HTML5 Form Validation . You can also take a look at the documentation on MDN and play with the :valid and :invalid selectors.
const inputs = document.querySelectorAll("input, select, textarea");
inputs.forEach(input => {
input.addEventListener(
"invalid",
event => {
input.classList.add("error");
},
false
);
});
EDIT:
You are probably not seeing your custom message because it comes from server side, the message that you're currently seeing when submitting your form is client-side validation. So you can either place novalidate on your field, or you can override the validation messages on the client side by using setCustomValidity(), as described in this SO post which also contains many useful links. An example using your Form Builder:
$builder
->add('name', EntityType::class,[
'class' => InsCompareList::class,
'label' => false,
[
'attr' => [
'oninvalid' => "setCustomValidity('Hi user, Please select an item')"
]
],
'query_builder' => function(EntityRepository $rp){
return $rp->createQueryBuilder('u')
->orderBy('u.id', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'id',
'required' => true,
])
->add('submit', SubmitType::class, [
'label' => 'OK'
]);

How to apply InputFilter validators to fieldset elements in ZF3

I had a form that had two fields. An InputFilter with validators was applied to it. It was working fine. Then I moved the fields to a fieldset and added the fieldset to the form. Now the assignment validators to the fields is not present. The validator objects isValid method is not triggered at all. So how to apply the InputFilter validators to fields in a fieldset? Here you are the classes:
Text class Validator
namespace Application\Validator;
use Zend\Validator\StringLength;
use Zend\Validator\ValidatorInterface;
class Text implements ValidatorInterface
{
protected $stringLength;
protected $messages = [];
public function __construct()
{
$this->stringLengthValidator = new StringLength();
}
public function isValid($value, $context = null)
{
if (empty($context['url'])) {
if (empty($value)) return false;
$this->stringLengthValidator->setMin(3);
$this->stringLengthValidator->setMax(5000);
if ($this->stringLengthValidator->isValid($value)) {
return true;
}
$this->messages = $this->stringLengthValidator->getMessages();
return false;
}
if (!empty($value)) return false;
return true;
}
public function getMessages()
{
return $this->messages;
}
}
Test class InputFilter
namespace Application\Filter;
use Application\Fieldset\Test as Fieldset;
use Application\Validator\Text;
use Application\Validator\Url;
use Zend\InputFilter\InputFilter;
class Test extends InputFilter
{
public function init()
{
$this->add([
'name' => Fieldset::TEXT,
'required' => false,
'allow_empty' => true,
'continue_if_empty' => true,
'validators' => [
['name' => Text::class],
],
]);
$this->add([
'name' => Fieldset::URL,
'required' => false,
'allow_empty' => true,
'continue_if_empty' => true,
'validators' => [
['name' => Url::class],
],
]);
}
}
Test class Fieldset
namespace Application\Fieldset;
use Zend\Form\Fieldset;
class Test extends Fieldset
{
const TEXT = 'text';
const URL = 'url';
public function init()
{
$this->add([
'name' => self::TEXT,
'type' => 'textarea',
'attributes' => [
'id' => 'text',
'class' => 'form-control',
'placeholder' => 'Type text here',
'rows' => '6',
],
'options' => [
'label' => self::TEXT,
],
]);
$this->add([
'name' => self::URL,
'type' => 'text',
'attributes' => [
'id' => 'url',
'class' => 'form-control',
'placeholder' => 'Type url here',
],
'options' => [
'label' => self::URL,
],
]);
}
}
Test class Form
namespace Application\Form;
use Application\Fieldset\Test as TestFieldset;
use Zend\Form\Form;
class Test extends Form
{
public function init()
{
$this->add([
'name' => 'test',
'type' => TestFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
$this->add([
'name' => 'submit',
'attributes' => [
'type' => 'submit',
'value' => 'Send',
],
]);
}
}
TestController class
namespace Application\Controller;
use Application\Form\Test as Form;
use Zend\Debug\Debug;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class TestController extends AbstractActionController
{
private $form;
public function __construct(Form $form)
{
$this->form = $form;
}
public function indexAction()
{
if ($this->getRequest()->isPost()) {
$this->form->setData($this->getRequest()->getPost());
Debug::dump($this->getRequest()->getPost());
if ($this->form->isValid()) {
Debug::dump($this->form->getData());
die();
}
}
return new ViewModel(['form' => $this->form]);
}
}
TestControllerFactory class
namespace Application\Factory;
use Application\Controller\TestController;
use Application\Form\Test;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class TestControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$form = $container->get('FormElementManager')->get(Test::class);
return new TestController($form);
}
}
Test class
namespace Application\Factory;
use Application\Filter\Test as Filter;
use Application\Entity\Form as Entity;
use Application\Form\Test as Form;
use Interop\Container\ContainerInterface;
use Zend\Hydrator\ClassMethods;
use Zend\ServiceManager\Factory\FactoryInterface;
class Test implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return (new Form())
->setHydrator($container
->get('HydratorManager')
->get(ClassMethods::class))
->setObject(new Entity())
->setInputFilter($container->get('InputFilterManager')->get(Filter::class));
}
}
Test Fieldset
namespace Application\Factory;
use Application\Entity\Fieldset as Entity;
use Application\Fieldset\Test as Fieldset;
use Interop\Container\ContainerInterface;
use Zend\Hydrator\ClassMethods;
use Zend\ServiceManager\Factory\FactoryInterface;
class TestFieldset implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return (new Fieldset())
->setHydrator($container->get('HydratorManager')->get(ClassMethods::class))
->setObject(new Entity());
}
}
UPDATE
I updated the fieldset class accordingly to #Nukeface advise by adding setInputFilter(). But it did not worked. It even had not executed InpuFilter class init method. Perhaps I did in wrong:
<?php
namespace Application\Fieldset;
use Application\Filter\Test as Filter;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterAwareTrait;
class Test extends Fieldset
{
use InputFilterAwareTrait;
const TEXT = 'text';
const URL = 'url';
public function init()
{
$this->add([
'name' => self::TEXT,
'type' => 'textarea',
'attributes' => [
'id' => 'text',
'class' => 'form-control',
'placeholder' => 'Type text here',
'rows' => '6',
],
'options' => [
'label' => self::TEXT,
],
]);
$this->add([
'name' => self::URL,
'type' => 'text',
'attributes' => [
'id' => 'url',
'class' => 'form-control',
'placeholder' => 'Type url here',
],
'options' => [
'label' => self::URL,
],
]);
$this->setInputFilter(new Filter());
}
}
Tried an answer before and ran out of chars (30k limit), so created a repo instead. The repo contains abstraction of the answer below, which is a working example.
Your question shows you having the right idea, just not yet the implementation. It also contains a few mistakes, such as setting a FQCN for a Fieldset name. Hopefully the below can have you up and running.
As a use case, we'll have a basic Address form. Relationships for Country, Timezones and other things I'll leave out of the scope. For more in depth and nesting of Fieldsets (also with Collections) I'll refer you to my repo.
General setup
First create the basic setup. Create the Entity and configuration.
Basic Entity
namespace Demo\Entity;
class Address
{
protected $id; // int - primary key - unique - auto increment
protected $street; // string - max length 255 - not null
protected $number; // int - max length 11 - not null
protected $city; // string - max length 255 - null
// getters/setters/annotation/et cetera
}
To handle this in a generic and re-usable way, we're going to need:
AddressForm (general container)
AddressFormFieldset (form needs to be validated)
AddressFieldset (contains the entity inputs)
AddressFieldsetInputFilter (must validate the data entered)
AddressController (to handle CRUD actions)
Factory classes for all of the above
a form partial
Configuration
To tie these together in Zend Framework, these need to be registered in the config. With clear naming, you can already add these. If you're using something like PhpStorm as your IDE, you might want to leave this till last, as the use statements can be generated for you.
As this is an explanation, I'm showing you now. Add this to your module's config:
// use statements here
return [
'controllers' => [
'factories' => [
AddressController::class => AddressControllerFactory::class,
],
],
'form_elements' => [ // <-- note: both Form and Fieldset classes count as Form elements
'factories' => [
AddressForm::class => AddressFormFactory::class,
AddressFieldset::class => AddressFieldsetFactory::class,
],
],
'input_filters' => [ // <-- note: input filter classes only!
'factories' => [
AddressFormInputFilter::class => AddressFormInputFilterFactory::class,
AddressFieldsetInputFilter::class => AddressFieldsetInputFilterFactory::class,
],
],
'view_manager' => [
'template_map' => [
'addressFormPartial' => __DIR__ . '/../view/partials/address-form.phtml',
],
];
Fieldset
First we create the Fieldset (and Factory) class. This is because this contains the actual object we're going to handle.
AddressFieldset
// other use statements for Elements
use Zend\Form\Fieldset;
class AddressFieldset extends Fieldset
{
public function init()
{
parent::init(); // called due to inheritance
$this->add([
'name' => 'id',
'type' => Hidden::class,
]);
$this->add([
'name' => 'street',
'required' => true,
'type' => Text::class,
'options' => [
'label' => 'Name',
],
'attributes' => [
'minlength' => 1,
'maxlength' => 255,
],
]);
$this->add([
'name' => 'number',
'required' => true,
'type' => Number::class,
'options' => [
'label' => 'Number',
],
'attributes' => [
'step' => 1,
'min' => 0,
],
]);
$this->add([
'name' => 'city',
'required' => false,
'type' => Text::class,
'options' => [
'label' => 'Name',
],
'attributes' => [
'minlength' => 1,
'maxlength' => 255,
],
]);
}
}
AddressFieldsetFactory
// other use statements
use Zend\ServiceManager\Factory\FactoryInterface;
class AddressFieldsetFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$this->setEntityManager($container->get(EntityManager::class));
/** #var AddressFieldset $fieldset */
$fieldset = new AddressFieldset($this->getEntityManager(), 'address');
$fieldset->setHydrator(
new DoctrineObject($this->getEntityManager())
);
$fieldset->setObject(new Address());
return $fieldset;
}
}
InputFilter
Above we created the Fieldset. That allows for the generation of the Fieldset for in a Form. At the same time, Zend Framework also has defaults already set per type of input (e.g. 'type' => Text::class). However, if we want to validate it to our own, more strict, standards, we need to override the defaults. For this we need an InputFilter class.
AddressFieldsetInputFilter
// other use statements
use Zend\InputFilter\InputFilter;
class AddressFieldsetInputFilter extends InputFilter
{
public function init()
{
parent::init(); // called due to inheritance
$this->add([
'name' => 'id',
'required' => true,
'filters' => [
['name' => ToInt::class],
],
'validators' => [
['name' => IsInt::class],
],
]);
$this->add([
'name' => 'street',
'required' => true,
'filters' => [
['name' => StringTrim::class], // remove whitespace before & after string
['name' => StripTags::class], // remove unwanted tags
[ // if received is empty string, set to 'null'
'name' => ToNull::class,
'options' => [
'type' => ToNull::TYPE_STRING, // also supports other types
],
],
],
'validators' => [
[
'name' => StringLength::class, // set min/max string length
'options' => [
'min' => 1,
'max' => 255,
],
],
],
]);
$this->add([
'name' => 'number',
'required' => true,
'filters' => [
['name' => ToInt::class], // received from HTML form always string, have it cast to integer
[
'name' => ToNull::class, // if received is empty string, set to 'null'
'options' => [
'type' => ToNull::TYPE_INTEGER,
],
],
],
'validators' => [
['name' => IsInt::class], // check if actually integer
],
]);
$this->add([
'name' => 'city',
'required' => false, // <-- not required
'filters' => [
['name' => StringTrim::class], // remove whitespace before & after string
['name' => StripTags::class], // remove unwanted tags
[ // if received is empty string, set to 'null'
'name' => ToNull::class,
'options' => [
'type' => ToNull::TYPE_STRING, // also supports other types
],
],
],
'validators' => [
[
'name' => StringLength::class, // set min/max string length
'options' => [
'min' => 1,
'max' => 255,
],
],
],
]);
}
}
AddressFieldsetInputFilterFactory
// other use statements
use Zend\ServiceManager\Factory\FactoryInterface;
class AddressFieldsetInputFilterFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// Nothing else required in this example. So it's as plain as can be.
return new AddressFieldsetInputFilter();
}
}
Form & Validation
So. Above we created the Fieldset, it's InputFilter and 2 required Factory classes. This already allows us to do a great deal, such as:
use the InputFilter in stand-alone setting to dynamically validate an object
re-use Fieldset + InputFilter combination in other Fieldset and InputFilter classes for nesting
Form
use Zend\Form\Form;
use Zend\InputFilter\InputFilterAwareInterface;
// other use statements
class AddressForm extends Form implements InputFilterAwareInterface
{
public function init()
{
//Call parent initializer. Check in parent what it does.
parent::init();
$this->add([
'type' => Csrf::class,
'name' => 'csrf',
'options' => [
'csrf_options' => [
'timeout' => 86400, // day
],
],
]);
$this->add([
'name' => 'address',
'type' => AddressFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
$this->add([
'name' => 'submit',
'type' => Submit::class,
'attributes' => [
'value' => 'Save',
],
]);
}
}
Form Factory
use Zend\ServiceManager\Factory\FactoryInterface;
// other use statements
class AddressFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** #var AbstractForm $form */
$form = new AddressForm('address', $this->options);
$form->setInputFilter(
$container->get('InputFilterManager')->get(ContactFormInputFilter::class);
);
return $form;
}
}
Making it all come together
I'll show just the AddressController#addAction
AddressController
use Zend\Mvc\Controller\AbstractActionController;
// other use statements
class AddressController extends AbstractActionController
{
protected $addressForm; // + getter/setter
protected $entityManager; // + getter/setter
public function __construct(
EntityManager $entityManager,
AddressForm $form
) {
$this->entityManager = $entityManager;
$this->addressForm = $form;
}
// Add your own: index, view, edit and delete functions
public function addAction () {
/** #var AddressForm $form */
$form = $this->getAddressForm();
/** #var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$entity = $form->getObject();
$this->getEntityManager()->persist($entity);
try {
$this->getEntityManager()->flush();
} catch (\Exception $e) {
$this->flashMessenger()->addErrorMessage($message);
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
$this->flashMessenger()->addSuccessMessage(
'Successfully created object.'
);
return $this->redirect()->route($route, ['param' => 'routeParamValue']);
}
$this->flashMessenger()->addWarningMessage(
'Your form contains errors. Please correct them and try again.'
);
}
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
}
AddressControllerFactory
class AddressControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** #var AddressController $controller */
$controller = new AddressController(
$container->get(EntityManager::class),
$container->get('FormElementManager')->get(AddressForm::class);
);
return $controller;
}
}
Display in addressFormPartial
$this->headTitle('Add address');
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formRow($form->get('csrf'));
echo $this->formRow($form->get('address')->get('id'));
echo $this->formRow($form->get('address')->get('street'));
echo $this->formRow($form->get('address')->get('number'));
echo $this->formRow($form->get('address')->get('city'));
echo $this->formRow($form->get('submit'));
echo $this->form()->closeTag($form);
To use this partial, say in a add.phtml view, use:
<?= $this->partial('addressFormPartial', ['form' => $form]) ?>
This bit of code will work with the demonstrated addAction in the Controller code above.
Hope you found this helpful ;-) If you have any questions left, don't hesitate to ask.
Just use the InputFilterProviderInterface class to your fieldset. This implements the getInputFilterSpecification method to your fieldset, which executes the input filters mentioned in this method.
class MyFieldset extends Fieldset implements InputFilterProviderInterface
{
public function init()
{
$this->add([
'name' => 'textfield',
'type' => Text::class,
'attributes' => [
...
],
'options' => [
...
]
]);
}
public function getInputFilterSpecification()
{
return [
'textfield' => [
'required' => true,
'filters' => [
...
],
'validators' => [
[
'name' => YourTextValidator::class,
'options' => [
...
],
],
],
],
];
}
}
AS long as you add this fieldset in your form the bound filters and validators will be executed on the isValid method call of your form.

Silex 2/Symfony: Check CSRF token from security login form

I do not use the "Form Service Provider" and manually output the CSRF token to my twig login form:
$csrf_token = $app['csrf.token_manager']->getToken('token_id'); //'TOKEN'
And in the login.html.twig:
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}">
The manual (https://silex.symfony.com/doc/2.0/providers/csrf.html) says, that it's possible to check the token like this:
$app['csrf.token_manager']->isTokenValid(new CsrfToken('token_id', 'TOKEN'));
But the whole login process is handled by the security component. How do I add the CSRF check to it?
This is my firewall setup:
$app['security.firewalls'] = array(
'login' => array(
'pattern' => '^/user/login$',
),
'secured_area' => array(
'pattern' => '^.*$',
'anonymous' => false,
'remember_me' => array(),
'form' => array(
'login_path' => '/user/login',
'check_path' => '/user/login_check',
),
'logout' => array(
'logout_path' => '/user/logout',
'invalidate_session' => true
),
'users' => function () use ($app) {
return new UserProvider($app['db']);
},
));
And the Login controller:
$app->get('/user/login', function(Request $request) use ($app) {
$csrf_token = $app['csrf.token_manager']->getToken('token_id'); //'TOKEN'
return $app['twig']->render('login.html.twig', array(
'csrf_token' => $csrf_token,
));
});
Try to add csrf options to security config:
$app['security.firewalls'] = array(
....
'form' => array(
'login_path' => '/user/login',
'check_path' => '/user/login_check',
'with_csrf' => true,
'csrf_parameter' => '_csrf_token', // form field name
'csrf_token_id' => 'token_id'
),
....

Sonata admin bundle get class object

I'm using sonata admin bundle for my project, in my admin class, I'm trying to get the class object to get data like:
$this->getSubject()->getName();
However, the out come is:
FatalErrorException: Error: Call to a member function getName() on a non-object in MyAdmin.php line 169
Anyone know what's wrong? Appreciate!
Updated 21/09/2014
Here is what I am tying to do:
public function getExportFields() {
$this->getSubject()->getPurchasePerItem; //Here return error!
return [
$this->getTranslator()->trans('Order Number') => 'id',
$this->getTranslator()->trans('First Name') => 'customer.First_name',
$this->getTranslator()->trans('Last Name') => 'customer.Last_name',
$this->getTranslator()->trans('Contact') => 'customer.contact',
$this->getTranslator()->trans('Email') => 'customer.email',
$this->getTranslator()->trans('Street') => 'customer.street',
$this->getTranslator()->trans('Town') => 'customer.town',
$this->getTranslator()->trans('State') => 'customer.state',
$this->getTranslator()->trans('Postcode') => 'customer.postcode',
//items may more than one
$this->getTranslator()->trans('Item') => 'purchasePerItem[0].product.model',
$this->getTranslator()->trans('Item_Qty') => 'purchasePerItem[0].quantity',
$this->getTranslator()->trans('Item_price') => 'purchasePerItem[0].product.price',
$this->getTranslator()->trans('Total') => 'total_amount',
$this->getTranslator()->trans('Shipping') => 'delivery_fee',
$this->getTranslator()->trans('Order time') => 'createdAt',
$this->getTranslator()->trans('Last Update') => 'updatedAt',
];

Resources