Lumen 5.3: How to extend validation class - laravel

Validation class has a couple of functions to retrieve errors, how can I extend this class to manipulate array structure of error messages:
$v = Validatior::make($input, $rules);
if($v->fails()){
// Instead of
print_r($v->errors()->messages());
// Have
print_r($v->getErrorsWithMyPreferedStructure());
}
I want to add my own function to validation class. Obviousely one of the possible solutions is extending validation class and ... But it's not what I'm searching for. I'm looking for a way to extend validation class via it's own methods, if any!

Related

Accessor overrides custom validation rule

I have created a custom rule to make sure the number is of two decimal places. The database has numbers stored as decimal(19,4). To display the number with only two decimal places, I also have put an accessor in place. Now the problem is that the accessor overrides the custom validation rule.
the relevant part from custom validation rule
public function passes($attribute, $value)
{
$precision = Config::get('accounting.decimal');
return preg_match('/^\d+(\.\d{1,'.$precision.'})?$/',$value);
}
the accessor in model
public function getRateAttribute($value)
{
$precision = Config::get('accounting.decimal');
return round($value, $precision);
}
the validation rule in the livewire component
public function rules()
{
return [
'editing.rate' => ['required', new NumberFormat()],
];
}
Desired behavior:
Whenever a user enters a number with more than two decimal places, it should throw the customer validation error.
Every time the field is used anywhere else to display, it should show the number with two decimal places. For eg: 78.9800 should be displayed as 78.98.
any ideas why this is not happening?
Edit:
Did a little more testing and this seems to be a laravel livewire issue. I am binding data directly to the model property. Because of that, when I edit the field, the accessor is immediately called before validation occurs.
Workaround:
I canceled the data binding to the model property. This solved the issue.
Still is there a better way to use laravel-livewire data binding to model property and use an accssor that would not override the validation rule.

Validate when fields depend on one another

I am passing a request object name Person to controller. Lets say the object has 2 two fields. The following business rule apply:
If field age has a value < 18, the field sin should be left blank;
If not, it will produce exception with message the sin should be blank with age < 18 or another way is to set the field sin to empty string("").
What is the best way for me to validate those inputs when they depend on each other. My way to deal with them is to validate them inside the controller method. So it should look something like that
#GetMapping("/..."
public ResponseEntity<PersonResponse> getPersonResult(GetPersonRequest request)
{
if (request.getAge() < 18)
{
if (request.getSin.length > 0)
request.setSin("")
}
PersonResponse response = callThirdPartyAPIToRetrieveInformationAboutThatPerson(request)
return response ;
}
Is there any more elegant way to code ? Is it ok for the controller method to contain any validation logic like that ? am i violating the Single Responsibility in SOLID design ?
Yes, of course! And this is a good approach: single responsibility of classes - a controller is responsible for handling data, validator - for validation of data; open-closed principle - validated data is unchangeable by controller's method; Liskov principle correlates with the base OOP principles - a validator is separated entity and can be changed to another one without any additional manipulations; Interface Segregation is clear without any description (fully separated classes); Depency Inversion is also understandable - using annotation interface, controller does not know anything about its implementation. So, it's a really good approach from ideology and language syntax.
Implementation.
Create class-level #interface. All fields are accessible.
Create ConstraintValidator class with validation logic.
Set this annotation for #RequestBody in the controller method.
Add validation functionality for controller: #Validated for controller class and #Valid for #RequestBody entity in controller method.
If you need to handle validation exceptions, just throw a new exception and handle it in #ControllerAdvise class, no handling code in validation or controller classes.
Example of creation class-level validator in the official resource.

Eloquent model method or attribute for calculation

I'm looking for a way to define a custom Eloquent method which only returns a calculation based on several columns in the according database table. I also tried setting it in the models attributes, but neither seem to work. Maybe I'm missing something, here's what I got so far:
<?php
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
public function difference() {
return $this->goals_f - $this->goals_a;
}
}
The error message I'm recieving is:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
Your error makes it sound to me like you are trying to call your method like a property" $team->difference. You would instead need to call it like: $team->difference(). If you want to get the difference as if it was a property, then you would need to define an accessor:
public function getDifferenceAttribute(){
return $this->goals_f - $this->goals_a;
}
Then you could call it like $team->difference.
You could also define a protected $appends property to your model so that the difference property is subsequently visible in it's JSON representation:
protected $appends = ['difference'];
More information: https://laravel.com/docs/5.2/eloquent-mutators#accessors-and-mutators

zf2 call a method from a Model in another Model

I have a couple of modules in ZF2 project. Each module has different model classes performing different required functions. Now I have method in a model class of first module which I want to call in the model class of second module. Is it possible to do so? if yes, how?
This should be fairly simple. Firstly you need to include the two modules in your application.config.php
'modules' => array(
'Module1',
'Module2'
)
Then as a very basic example taken from your question:
<?php
namespace Module2\Model;
use Module1\Model\Class1;
class Class2
{
public function doSomething()
{
$class1 = new Class1();
$class1->doSomething();
}
}

Extending Laravel's Validator Class

I am using the Laravel's validator class, and when validation fails I print out the errors with this method:
$validator->messages();
The method returns a multi dimensional array, I need a single dimensional array.
$validator->net_method();
How will I go about extending a new method to return the errors in a different format?

Resources