Setup: I have a slim application and I pulled in Illuminate DB and Twig view.
if (!$validator->passed()) {
$errors = $validator->errors();
$users = User::all();
return $this->view($response, 'auth.login', compact('errors','users'));
}
Problem: When I run the above code, I am able to retrieve the users variable in my view, but the errors variable throws the following error.
Notice: Array to string conversion in /Users/davidchen/Documents/sites/slim.com/vendor/twig/twig/lib/Twig/Environment.php(378) : eval()'d code
on line
70 Array
The errors variable returns a multidimensional array, below you'll find the result that I get from print_r($errors).
Array (
[username] => Array (
[0] => username already exists
)
[password] => Array (
[0] => password must consist of at least 6 characters
)
)
Here are my related project files:
Twig Setup File (app.php)
$c = $app->getContainer();
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection($config['config']['db']);
$capsule->setAsGlobal();
$capsule->bootEloquent();
$c['db'] = function($c) use ($capsule){
return $capsule;
};
$c['view'] = function($c){
$options['cache']=false;
$view = new \Slim\Views\Twig(__DIR__."/../views", $options);
$view->addExtension(new \Slim\Views\TwigExtension(
$c->router,
$c->request->getUri()
));
$view->getEnvironment()->addGlobal('flash', $c->flash);
return $view;
};
$c['flash'] = function($c){
return new Slim\Flash\Messages();
};
Validator Class
namespace App\Models\Auth;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Capsule\Manager as DB;
use Carbon\Carbon;
use DateTime;
class Validator extends Model
{
protected $field_name,
$data,
$errors = [];
/*
* Main validator
*/
public function __construct($request, $fields = []){
$data = $request->getParams();
$this->data = $data;
foreach ($fields as $field => $constraints) {
$this->field_name = $field;
if (isset($data[$field])) {
$field_value = $data[$field];
foreach (explode("|", $constraints) as $constraint) {
$obj = explode(":", $constraint);
$function_name = $obj[0];
if (isset($obj[1])) {
if(method_exists($this, $function_name))
{
$this->$function_name($obj[1],$field_value);
}
}
}
}else{
if (strpos($constraints, 'required') !== false) {
$validator->report($validator->field_name.' field is requried');
}
}
}
return $this;
}
/*
* Object Interface Methods
*/
private function report($message){
$this->errors[$this->field_name][]= $message;
}
public function errors(){
return $this->errors;
}
public function passed(){
if (!count($this->errors)) {
return true;
}
}
/*
* Validation Rules
*/
public function max($length,$value){
if (strlen($value)>$length) {
$this->report("{$this->field_name} must consist of less than {$length} characters");
}
}
public function min($length,$value){
if (strlen($value)<$length) {
$this->report("{$this->field_name} must consist of atleast {$length} characters");
}
}
public function distinct($tableName,$value){
if (DB::table($tableName)->where($this->field_name, $value)->exists()) {
$this->report("{$this->field_name} already exists");
}
}
public function date($format,$date){
if (!preg_match("/\d{4}-\d{2}-\d{2}\b/",$date)) {
$this->report("incorrect {$this->field_name} values");
}else{
$d = DateTime::createFromFormat($format, $date);
if ($d && $d->format($format) !== $date) {
$this->report("{$this->field_name} format should be {$format}");
}
}
}
public function match($matchField,$value){
if (isset($this->data[$matchField])) {
$valueTwo = $this->data[$matchField];
if ($value !== $valueTwo) {
$this->report("{$this->field_name} does not match {$matchField}");
}
}else{
$this->report("{$matchField} is required");
}
}
public function format($type,$value){
switch ($type) {
case 'noWhiteSpace':
if (preg_match("/\s/",$value)) {
$this->report("{$this->field_name} may not contain any spaces");
}break;
case 'alpha':
if (preg_match("/[^a-zA-Z]/",$value)) {
$this->report("{$this->field_name} may only contain letters");
}break;
case 'alphaNum':
if (preg_match("/[^a-zA-Z0-9]/",$value)) {
$this->report("{$this->field_name} may only contain letters");
}break;
case 'email':
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$this->report("in correct {$this->field_name} format");
}break;
default:
# code...
break;
}
}
}
Base Controller
namespace App\Controllers;
/**
*
*/
class Controller
{
protected $c;
function __construct($container)
{
$this->c = $container;
}
public function view($response, $path,$variables = []){
$this->c->view->render($response, str_replace(".","/",$path).".twig", $variables);
}
public function pathFor($routeName,$data = []){
return $this->c->router->pathFor($routeName,$data);
}
}
Auth Controller
namespace App\Controllers\Auth;
use App\Models\User\User;
use App\Controllers\Controller;
use App\Models\Auth\Validator;
/**
*
*/
class AuthController extends Controller
{
public function getLogin($request, $response){
return $this->view($response, 'auth.login');
}
public function postLogin($request, $response){
$validator = new Validator($request,[
'username'=>'required|min:3|max:64|format:alphaNum|distinct:users',
'password'=>'required|min:6|max:64|',
]);
if (!$validator->passed()) {
$errors = $validator->errors();
$users = User::all();
return $this->view($response, 'auth.login', compact('errors','users'));
}
return $this->view($response, 'home.login');
}
}
login.twig file
login.twig file
Hope one of you can shed some light on this problem. I've been struggling with this all morning.
You could try to loop over each item in a sequence. For example, to display a list of users provided in a variable called users:
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
Read more
Related
I can't understand why the data is not transmitted in the custom facade (Format) method parameter. I'm doing exception handling for the API and using my visualization handler (JsonExceptionFormatter).
Interface CanFormat:
interface CanFormat
{
public function format($data);
}
Facade Format:
class Format extends Facade
{
protected static function getFacadeAccessor(): string
{
return \Hopex\VkSdk\Foundation\Format::class;
}
}
Class Format:
namespace Hopex\VkSdk\Facades;
class Format implements CanFormat
{
private array $formatters = [];
public function with(string $formatter): static
{
$formatter = new $formatter();
if ($formatter instanceof CanFormat) {
$this->formatters[] = $formatter;
}
return $this;
}
public function format($data): mixed
{
foreach ($this->formatters as $formatter) {
$data = $formatter->format($data);
}
return $data;
}
}
Exception render method:
final public function render(Request $request)
{
if (env('LOG_LEVEL') === 'debug') {
dump($this->getMessage()); // added for test (next "dump 1")
return new JsonResponse(
Format::with(JsonExceptionFormatter::class)->format($this->getMessage()),
$this->getCode()
);
}
}
Visualization handler:
class JsonExceptionFormatter implements CanFormat
{
public function format($data): array
{
dump($data); // added for test (next "dump 2")
return [
'type' => 'error',
'message' => $data instanceof SdkException ? $data->getMessage() : $data
];
}
}
It's dumps:
[dump 1]: "ApiException: User authorization failed"
[dump 2]: []
P.S. Other formats work without problems.
In my Laravel application, I need submodels of the base ORM model, for specific types of item in my DB which is specified in 'type' column in database.
In my base model, I use this override for function newFromBuilder
// OVERRIDES
public function newFromBuilder($attributes = [], $connection = null)
{
$class = "\\App\\Models\\" . ucfirst($attributes->type);
if (class_exists($class)) {
$model = new $class();
} else {
$model = $this->newInstance([], true);
}
$model->setRawAttributes((array)$attributes, true);
$model->setConnection($connection ?: $this->getConnectionName());
$model->fireModelEvent('retrieved', false);
return $model;
}
but for some reason when i call save or update function in submodel nothing happen :( Each submodel should ingered save function of fase model s that right ? Could anybody help me to fix issue with save function ?
Base model:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;
use App\Models\Devices;
use App\Models\Records;
use App\Models\Rooms;
use App\Helpers\SettingManager;
use App\Types\GraphPeriod;
use App\Types\PropertyType;
class Properties extends Model
{
protected $fillable = [];
protected $table = 'sh_properties';
protected $primaryKey = 'id';
public $period = GraphPeriod::DAY;
//OVERIDES
public function newFromBuilder($attributes = [], $connection = null)
{
$class = "\\App\\Models\\" . ucfirst($attributes->type);
if (class_exists($class)) {
$model = new $class();
} else {
$model = $this->newInstance([], true);
}
$model->setRawAttributes((array)$attributes, true);
$model->setConnection($connection ?: $this->getConnectionName());
$model->fireModelEvent('retrieved', false);
return $model;
}
//NEW RELATIONS
public function records()
{
return $this->hasMany(Records::class, 'property_id');
}
public function latestRecord()
{
return $this->hasOne(Records::class, 'property_id')->latestOfMany();
}
public function device()
{
return $this->belongsTo(Devices::class);
}
public function room()
{
return $this->belongsTo(Rooms::class);
}
public function settings()
{
if ($settings = SettingManager::getGroup('property-' . $this->id)) {
return $settings;
}
return false;
}
//FUNCTIONS
public function getLatestRecordNotNull()
{
return Records::where("property_id", $this->id)->where("value", "!=", null)->where("value", "!=", 0)->first();
}
//Virtual Values
use HasFactory;
//Add Function for mutator for vaue (vith units) and rav value
public function values()
{
$dateFrom = Carbon::now()->subDays(1);
switch ($this->period) {
case GraphPeriod::WEEK:
$dateFrom = Carbon::now()->subWeek(1);
break;
case GraphPeriod::MONTH:
$dateFrom = Carbon::now()->subMonth(1);
break;
case GraphPeriod::YEAR:
$dateFrom = Carbon::now()->subYear(1);
break;
}
return $this->hasMany(Records::class, 'property_id')->whereDate('created_at', '>', $dateFrom)->orderBy('created_at', 'DESC');
}
public function getAgregatedValuesAttribute($period = GraphPeriod::DAY)
{
$dateFrom = Carbon::now()->subDays(1);
$periodFormat = "%Y-%m-%d %hh";
switch ($this->period) {
case GraphPeriod::WEEK:
$dateFrom = Carbon::now()->subWeek(1);
$periodFormat = "%Y-%m-%d";
break;
case GraphPeriod::MONTH:
$dateFrom = Carbon::now()->subMonth(1);
$periodFormat = "%Y-%m-%d";
break;
case GraphPeriod::YEAR:
$dateFrom = Carbon::now()->subYear(1);
$periodFormat = "%Y-%m";
break;
}
$agregatedData = Records::select(['value', 'done', 'created_at'])
->selectRaw("DATE_FORMAT(created_at, ?) as period", [$periodFormat])
->selectRaw("ROUND(MIN(value), 1) AS min")
->selectRaw("ROUND(MAX(value), 1) AS max")
->selectRaw("ROUND(AVG(value), 1) AS value")
->where('property_id', $this->id)
->orderBy('created_at', 'DESC')
->groupBy('period');
$agregatedData->where('created_at', '>=', $dateFrom);
return $agregatedData->get();
}
public function last_value()
{
return $this->hasOne(Records::class, 'property_id', 'id')->latest();
}
//Virtual Values
//Virtual Values
/**
* Minimum value that property had in past.
*
* #return int
*/
public function getMaxValueAttribute()
{
if ($this->records) {
return $this->records->max("value");
}
return false;
}
/**
* Maximum value that property had in past.
*
* #return int
*/
public function getMinValueAttribute()
{
if ($this->records) {
return $this->records->min("value");
}
return false;
}
/**
* step value used to increment each value usually used for range type or thermostats, graphs also.
*
* #return int
*/
public function getStepValueAttribute()
{
if ($step = SettingManager::get('step', 'property-' . $this->id)) {
return ($step->value < 1 ? $step->value : 1);
}
return false;
}
/**
* max set value for prop
*
* #return int
*/
public function getMaxValueSettingAttribute()
{
if ($step = SettingManager::get('max', 'property-' . $this->id)) {
return ($step->value > 1 ? $step->value : 1);
}
return false;
}
/**
* min set value for prop
*
* #return int
*/
public function getMinValueSettingAttribute()
{
if ($step = SettingManager::get('min', 'property-' . $this->id)) {
return ($step->value > 1 ? $step->value : 1);
}
return false;
}
public function setValue($value)
{
$record = new Records;
$record->value = $value;
$record->property_id = $this->id;
$record->save();
return true;
}
}
Submodel
namespace App\Models;
use App\Models\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Humi extends Properties
{
protected $historyDefault = 90;
protected $unitsDefault = "%";
protected $iconDefault = "";
public function save(array $options = [])
{
// before save code
$result = parent::save($options); // returns boolean
// after save code
return $result; // do not ignore it eloquent calculates this value and returns this, not just to ignore
}
}
Thank you in advance for any suggestions or help :)
When a new instance is created with the $this->newInstance() function, the $model->exists property is set to true. I think you should do the same in your if statement as well. Otherwise it will try to create a new record in the database.
It might be a good idea to copy the rest of the function as well to avoid any other problems it may cause.
if (class_exists($class)) {
$model = new $class();
// Important
$model->exists = true;
$model->setTable($this->getTable());
$model->mergeCasts($this->casts);
} else {
$model = $this->newInstance([], true);
}
I'm currently upgrading from Symfony 2.3 to 2.8 and are deprecating for the 3.0 update.
Under the link below, I rewrite Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList and Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList.
Among them, the following error occurred.
I wondered if I should add getChoices(), so I added it to ChoiceLoader.php, but I still got an error.
How should I solve it?
Also, choice_list will be abolished soon, so I plan to rewrite it.
https://github.com/symfony/symfony/blob/2.7/UPGRADE-2.7.md
Error
Attempted to call an undefined method named "getChoices" of class
"Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory"
ChoiceList->ChoiceLoader.php
namespace Ahi\Sp\AdminBundle\Form\ChoiceList;
//Remove
//use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
//use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList;
//Add
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
class StaffChoiceLoader implements ChoiceLoaderInterface
{
private $staffService;
private $loginStaff;
private $currentStaff;
public function __construct($staffService, $loginStaff)
{
$this->staffService = $staffService;
$this->loginStaff = $loginStaff;
}
public function loadChoiceList($value = null)
{
// Get the same shop staff as the login staff
$staffs = $this->staffService->getStaffByShop($this->loginStaff->getShop());
// If the current staff is not included in the acquired staff (due to transfer etc.), add it to the end
if ($this->currentStaff && !array_search($this->currentStaff, $staffs)) {
$staffs[] = $this->currentStaff;
}
//Remove
//return new ChoiceList($staffs, $staffs);
//Add
return new DefaultChoiceListFactory($staffs, $staffs);
}
//Add
public function loadChoicesForValues(array $values, $value = null)
{
if (empty($choices)) {
return array();
}
$values = array();
foreach ($choices as $person) {
$values[] = (string) $staff->getId();
}
return $values;
}
public function loadValuesForChoices(array $choices, $value= null)
{
if (empty($values)) {
return array();
}
return $this->staffService->getStaffByShop($this->loginStaff->getShop());
}
public function getChoices()
{
}
}
ArticleType.php
//Remove
//$authorChoiceList = new StaffChoiceLoader($this->staffService, $options['login_staff']);
//Add
$factory = new DefaultChoiceListFactory();
$authorChoiceList = $factory->createListFromLoader(new StaffChoiceLoader($this->staffService, $options['login_staff']));
$builder->add("author", "entity", array(
"required" => true,
"class" => "AhiSpCommonBundle:Staff",
"choice_list" => $authorChoiceList,
"empty_value" => "Please select",
));
I am using a Symfony form which is prepopulated by some data (if I can find user, I prepopulate it's data).
I am getting this error:
Unable to transform value for property path "[terms]": Expected a Boolean.
I am using field terms which is checkbox type. Symfony version is 2.8.28.
My code for controller is:
class SignupController extends ResourceController {
public function newSignupAction(Request $request)
{
$resource = new Signup();
$form = $this->createForm($this->createNewFormType(), $resource, array(
'action' => $url,
'method' => 'POST',
));
$form->add('submit', 'submit', array('label' => 'Create'));
if ($participant = $this->getUser()->getParticipant()) {
$participation = new Participation();
$participation->setParticipant($participant);
$signup->addParticipation($participation);
$form->setData($signup);
}
}
}
Signup class looks like this:
class Signup extends ExtraFieldEntity
{
public function addParticipation(Participation $participation)
{
$participation->setSignup($this);
$this->participations[] = $participation;
return $this;
}
}
class ParticipantBasicType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName')
->add('lastName')
->add('extraFields', 'extra_field_collection', array(
'group' => 'participant',
));
$builder->addEventListener(
FormEvents::POST_SET_DATA,
function (FormEvent $event) use ($builder) {
$form = $event->getForm();
if (!$data = $event->getData()) {
return;
}
/** #var PersistentCollection $extraFields */
$extraFields = $data->getExtraFields();
if ($extraFields->isEmpty()) {
return;
}
foreach ($extraFields->getValues() as $extraField) {
/** #var Value $extraField */
if ($form->get('extraFields')->has($extraField->getDefinition()->getIdentifier())) {
$form->get('extraFields')
->get($extraField->getDefinition()->getIdentifier())
->setData($extraField);
}
}
}
);
}
}
Extra fields should be rendered on the form. Building extra fields looks like this:
class ExtraFieldCollectionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
.....
$builder->add(
$builder->create(
$identifier,
$type,
$parameters
)->addModelTransformer(
new ScalarToExtraFieldValueTransformer($identifier, $definition, $type)
)
);
}
}
It calls a custom model transformer:
class ScalarToExtraFieldValueTransformer implements DataTransformerInterface
{
private $identifier;
private $definition;
private $type;
public function __construct($identifier, $definition, $type)
{
$this->identifier = $identifier;
$this->definition = $definition;
$this->type = $type;
}
public function transform($value)
{
$result = '';
if (is_null($value)) {
return $result;
}
if (is_object($value)) {
/* #var Value $value */
$result = $value->getValue();
} elseif (is_string($value)) {
if ($this->resolveType($this->type) == 'integer') {
$result = explode(',', $value);
}
}
settype($result, $this->resolveType($this->type));
return $result;
}
public function reverseTransform($value)
{
return new Value(
$value,
$this->definition
);
}
private function resolveType($type)
{
switch ($type) {
case 'choice':
return 'string';
case 'checkbox':
return 'boolean';
break;
default:
return 'string';
break;
}
}
}
As I could track down the problem, it breaks here just for checkbox type:
vendor/symfony/symfony/src/Symfony/Component/Form/Form.php
in this method:
private function normToView($value)
{
// Scalar values should be converted to strings to
// facilitate differentiation between empty ("") and zero (0).
// Only do this for simple forms, as the resulting value in
// compound forms is passed to the data mapper and thus should
// not be converted to a string before.
if (!$this->config->getViewTransformers() && !$this->config->getCompound()) {
return null === $value || is_scalar($value) ? (string) $value : $value;
}
try {
foreach ($this->config->getViewTransformers() as $transformer) {
$value = $transformer->transform($value);
}
} catch (TransformationFailedException $exception) {
throw new TransformationFailedException(
'Unable to transform value for property path "'.$this->getPropertyPath().'": '.$exception->getMessage(),
$exception->getCode(),
$exception
);
}
return $value;
}
Which is calling vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php
Any advice on what am I doing wrong? Thanks!
Addition (definition of Participant object)
class Participant extends ExtraFieldEntity
{
/**
* #ORM\ManyToMany(targetEntity="\Entity\ExtraField\Value", cascade={"persist", "remove"})
*/
protected $extraFields;
public function __construct()
{
parent::__construct();
$this->participations = new ArrayCollection();
}
public function addParticipation(Participation $participations)
{
$this->participations[] = $participations;
return $this;
}
}
I have currently two classes.
the ArrayCompare class:
<?php
namespace App\Tools\RegexExtract;
class ArrayCompare
{
public function compare(Array $arrayToCompare)
{
$elementData = new ElementMetaData();
$metaData = $elementData->extract($arrayToCompare[0], [], $initial=true);
foreach ($arrayToCompare as $currentElement) {
$metaData = $elementData->extract($currentElement, $metaData);
}
return $metaData;
}
}
which uses the ElementMetaData class
<?php
/**
* A class for extracting meta data from an element.
*/
namespace App\Tools\RegexExtract;
class ElementMetaData
{
public function extract($element, $metaDataToCompare = [], $initial = false)
{
if ($initial == true) {
$this->isInteger($element) ? $returnMetaData['isInteger'] = $this->isInteger($element) : null;
$returnMetaData['length'] = $this->length($element);
}
else {
$returnMetaData=$metaDataToCompare;
if ($returnMetaData != []) {
if (isset ($returnMetaData['isInteger']) && !$this->isInteger($element)) {
unset($returnMetaData['isInteger']);
}
if (isset ($returnMetaData['length']) && $this->length($element) != $returnMetaData['length']) {
unset($returnMetaData['length']);
}
}
}
return $returnMetaData;
}
private function isInteger($element)
{
return is_int($element);
}
private function length($element)
{
return strlen($element);
}
}
the basic functionality is:
given I have an array
$arr=[1,2,3];
I want to get the "similarities" between ALL Elements. According to a an array i Predefine...so this would deliver this result:
$metaArray=['isInteger'=>true,'length'=>1];
and this would deliver just length as similarity:
$arr=[1,2,'D'];
$metaArray=['length'=>1];
While this array would deliver an empty result []
$arr=[1,2,'3D']; // result is [] since not all integers or not all of same length.
Now my solution does not use recursive functions...but I am sure it can be used somehow.
Also, I want to add more "criteria"....So "isEmailAdress", "beginswithA"....etc....and this would make my if statements a horror....so what is the best strategy/design pattern to follow here?
#deceze beat me to it by fair margin... but I'll still post my solution that works basically with the same principles.
abstract class abstractComparer
{
private $array;
private $result = true;
protected $name;
public function compareArray($array)
{
$current = null;
foreach ($array as $index => $value)
{
$this->result = $this->result && $this->compareValues($index, $current, $value);
$current = $value;
}
}
public function getResult()
{
return $this->result;
}
public function getName()
{
return $this->name;
}
public abstract function compareValues($index, $value1, $value2);
public abstract function getSuccessValue();
}
class intComparer extends abstractComparer
{
protected $name = "isInteger";
public function compareValues($index, $value1, $value2)
{
return is_int($value2);
}
public function getSuccessValue()
{
return true;
}
}
class lengthComparer extends abstractComparer
{
protected $name = "length";
protected $length = 0;
public function compareValues($index, $value1, $value2)
{
$this->length = strlen($value2);
return $index == 0 || strlen($value1) == $this->length;
}
public function getSuccessValue()
{
return $this->length;
}
}
And do the actual processing like this:
$temp = [1,2,3];
$comparers = [new intComparer(), new lengthComparer()];
$result = array();
foreach ($comparers as $comparer)
{
$comparer->compareArray($temp);
if ($comparer->getResult())
{
$result[$comparer->getName()] = $comparer->getSuccessValue();
}
}
//var_dump($result);
I don't see any need for recursion here, so I'll just make a suggestion for a design approach:
Implement each criterion as a class:
abstract class Criterion {
protected $valid = true;
abstract public function initialize($value);
abstract public function check($value);
public function isValid() {
return $this->valid;
}
}
class Length extends Criterion {
protected $length;
public function initialize($value) {
$this->length = strlen($value);
}
public function check($value) {
if ($this->length != strlen($value)) {
$this->valid = false;
}
}
}
You then make an array of all your criteria:
$criteria = [new Length, ...];
foreach ($criteria as $criterion) {
$criterion->initialize($values[0]);
}
And slowly whittle them down through your values:
foreach ($values as $value) {
foreach ($criteria as $criterion) {
$criterion->check($value);
}
}
$commonCriteria = array_filter($criteria, function (Criterion $criterion) {
return $criterion->isValid();
});