Validate Laravel Nested Rules in Array - arrays

I'm with Laravel and I want to write elegant validation rules :) With this Framework its really easy, but I don't know how to approach this when facing 1:n relationships.
I have two Resources, User and Contact. An User can have multiple Contacts.
So, I want a Form where you can fill all User's fields AND all Contact's information.
To do that, I would like to write a Request like this:
UserRequest:
public function rules()
return [
'name' => 'required|string',
'email' => 'required|email|unique:exists:users,id',
'contacts' => 'array',
'contacts.*' => new ContactRequest() // This is the problem
]
My question is: How can I apply this type of validation? Specifically when using array, how can I make a Modular Validation to apply validations of nested Resources? Or should I develop a ContactRule instead?
Edit:
I want that front end send form like this:
` // POST: users
{
'name': 'UserName',
'email': 'user#mail.com'
'contacts': [
[
'email' => 'contac_1#mail.com',
'contact_type_id => 1
],
[
'email' => 'contac_2#mail.com',
'contact_type_id => 2
],
}
`
Thats all,
Thx!

We have an API with 100's of results in each request or perhaps post/patch.
We still use:
'data.relationships.users.data.*.id' => [
'string',
'unique:api_groups,name,' . ($this->route('group')->id ?? 0),
]
So for you
'contacts.*.email' => 'required|email|unique:exists:users,id'
Works perfectly. It doesn't get more complex or anything.

Related

How to add link to show action of the relation entity on relation field in SonataAdminBundle

Im making admin panel in SonataAdminBundle.
In User show action i have field companies which return array of companies assigned to the user.
It is a OneToMany relation. UserCompany has user_id and company_id.
I want to create link on each returned company name, which points to it's entity show action.
This is code from configureShowFields() function in UserAdmin class:
->with('Assigned organizers',['class' => 'col-md-6'])
->add('companies', null, [
'label' => 'Organizers',
])
->end()
I managed to create a link on a string field pointing to show action of an entity, but the id property is taken from the current entity view:
->with('Address', ['class' => 'col-md-6'])
->add('userProfile.locality', 'url', [
'route' => [
'name' => 'admin_app_employee_show',
'identifier_parameter_name' => 'id'
],
'label' => 'Localiy',
])
What's more Sonata Admin create links on related fields, when the relation is direct,
for example:
Company has many Employee. Then in Company show action on employees field
I see array with links already heading to edit action of Employee entty.
Maybe there is a possibility to override template for this field, but it seems unclear for me,
as the documentation lacks of more advanced examples.
This is how I tried to test overriding the template of a field:
->add('userProfile.street', null, array(
'label' => 'Street',
'template' => 'custom-field.html.twig',
))
Location of the template: App/templates/Admin/
Any help appreciated
SonataAdmin automatically creates links to related entities once it has all of them configured and added to services.
Then you can just change the route action of the link on the relation field as following:
->with('Assigned events', ['class' => 'col-md-6'])
->add('events', null, [
'route' => [
'name' => 'show'
],
'label' => 'Events',
])
->end()
You can also change the type of relation field eg.'many_to_one' instead of null which might help in some cases.

How to get the json data by yii2

Two question:
1.I use the post method of yii2 to get the json data, sent by front end with ngResource in Angularjs. And I configure the yii2 as follow:
'parsers' => [
'application/json' => 'yii\web\JsonParser',
'text/json' => 'yii\web\JsonParser',
]
But it doesn't work when I use $post = Yii::$app->request->post() to get the data. Additionally, the data is not serialized.
2.I configure the yii2
'response' => [
'formatters' => [
\yii\web\Response::FORMAT_JSON => [
'class' => 'yii\web\JsonResponseFormatter',
'prettyPrint' => YII_DEBUG,
]
]
],
When I find that it is different from
Yii::$app->response->format = Response::FORMAT_JSON;
before return some value. The former doesn't transform the data to json format. I don't know why?
1.I force the contentTye to application/x-www-form-urlencoded;charset=utf-8, it is so silly.
2.Formatters is different from format.

Cakephp 3 email validation

Guys folowing cakephp3 documentation for validation i try to validate my email field but that validation not work good.
How this can be valid email?
a#53%#sdasd#gmail.com
%321&%$sd#gmail.com
Form is successfull submited and data is saved to database. I think this validation is not good bcs i never see in my live email address like this above.
return $validator->requirePresence('email')
->notEmpty('email', __('Email is required field'))
->add('email', 'validFormat', [
'rule' => 'email',
'message' => 'E-mail must be valid'
]);
Here you can find regular expression that Cake uses for email validation:
https://github.com/cakephp/cakephp/blob/master/src/Validation/Validation.php#L567
If it does not satisfy your needs you can always provide your own.
Take a look on Email validation rule in CakePHP sources:
public static function email($check, $deep = false, $regex = null)
You can provide your own regular expression like this:
$validator->add("email", "validFormat", [
"rule" => ["email", false, $yourRegexp],
"message" => "Email must be valid."
])

CakePHP 3.0 Timestamp behavior

I would like to update a timestamp in a users table when a user logs in. I created a datetime field called 'lastLogin'.
From my users controller's login action I call:
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
$this->Users->touch($this->Users->get($user['id']), 'Users.afterLogin');
}
And in my Users table I have:
$this->addBehavior('Timestamp', [
'events' => [
'Model.beforeSave' => [
'created' => 'new',
'modified' => 'always',
],
'Users.afterLogin' => [
'lastLogin' => 'always'
]
]
]);
I have tested that the event is triggered and entity property is being updated. However it is not saved to the database.
Is this intended, i.e. do I have to explicitly save the entity, or am I missing something?
Thanks!
Andrius
The behavior only updates the field
It isn't really clear from the documentation, but the code only updates the field value. The behavior won't actually update the db, it's effectively assumed there would be a call to save later in the same request.

Cakephp recursive find including top model again

I have this cakephp find query:
$results = $this->Instrument->find('all', array('recursive' => 2, 'conditions' => array('OR' => array('Instrument.name' => $tag_search, 'Instrument.nameEN' => $tag_search))));
The Model Instrument has and belongs to many Instrumentbox. I want to find an Instrumentbox with all it's instruments searching for one instrument name with $tag_search.
It returns the Insrtumentboxes that have that instrument properly but it does not include all the instruments agaion in Instrument. Is there a way to tell cakephp to load the "top model" again so that I get the structure
$results = array(
0 => [
'Instrument' => [
'name' => "$tag_search value",
'...' => ...,
'Instrumentbox' => [
0 => [
'...' => '...', //everything else is properly included
'Instrument' => [...] //this is NOT included, how can I include it?
]
]
]
]
The same thing happens when I search it with tags, so imagine in the structure above 'Tag' instead of 'Instrument', then the instruments are included in the Instrumentbox but the tags are not. So the "top model" is not included again in the structure. Do I have to make that by hand or can I make cakephp do it?
Thanks in advance!
You Could try to do this with Contain. Its much better than using recursive over 1 anyway. You can control exactly the results you want to get, which is good for this sort of thing, and generally better for performance.
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
So, untested code:
//model
public $actsAs = array('Containable');
// controller
$this->Instrument->recursive=1;
$this->contain(array('Instrument'=> array('InstrumentBox'=> array('Instrument'))));

Resources