Написать письмо

TYPO3 подкаст #8. Модели, запросы, CRUD

Конструктор запросов (выбрать, обновить, добавить, удалить записи)

<?php
use Illuminate\Database\Capsule\Manager as DB;
use Litovchenko\AirTable\Domain\Model\Content\Pages;
use Mynamespace\Myext\Domain\Model\NewTable;

////////////////////////////////////////////////////////////////////////////////////////
// SELECT
// NewTable::recSelect('medthod', $id || $filter || $callback, $pluck = null); // return result
////////////////////////////////////////////////////////////////////////////////////////

Model::find(numeric); returns a object
Model::whereId(numeric)->first(); returns a object
Model::whereId(numeric)->get(); - returns a collection
Model::whereId(numeric); - returns a builder

$recordId = 7;
$rowFirst = NewTable::recSelect('first', $recordId);
$rowExists = NewTable::recSelect('exists', $recordId); // ->exists() (if), ->doesntExist() (if)
$rowsCount = NewTable::recSelect('count'); // count
$rowsGet = NewTable::recSelect('get'); // all
$obj = NewTable::recSelect('object')->...->get(); // return obj (to create subqueries)
$sql = NewTable::recSelect('object')->toSql();
$dd = NewTable::recSelect('object')->dd(); // debugging
$dump = NewTable::recSelect('object')->dump(); // debugging

$limit = 10;
$rowsResult = NewTable::recSelect('count,get', function ($q) use ($limit) { 
    $q->limit($limit); 
});

print "Count: " . $rowsResult['count'] . "<hr />";
foreach ($rowsResult['get'] as $row) {
    print $row['title'] . " // ";
    print $row['propref_NAME']['title'] . "<br />";
}

$filter = [];
$filter['withoutGlobalScopes'] = true; // or false
$filter['withoutGlobalScopes'] = ['FlagDeleted','FlagDeleted','DateStart', 'DateEnd', 'SwitcherStatus'];
$filter['withoutGlobalScope'] = 'FlagDeleted';

$filter['distinct'] = 'title';
$filter['select'] = ['uid','title', 'uid as aliasID'];
$filter['addSelect'] = ['pid','date_create']; // selectRaw()

$filter['whereUid'] = 1; // dynamic field name
$filter['wherePid'] = 1; // dynamic field name
$filter['whereTitle'] = []; // dynamic field name
$filter['whereFieldName'] = []; // dynamic field name

// Allowed operator parameter
// '=', '<', '>', '<=', '>=', '<>', '!=',
// 'like', 'like binary', 'not like', 'between', 'ilike',
// '&', '|', '^', '<<', '>>',
// 'rlike', 'regexp', 'not regexp',
// '~', '~*', '!~', '!~*', 'similar to',
// 'not similar to'
$filter['where.10'] = []; // ...
$filter['where.20'] = []; // ...
$filter['where'] = ['uid','>=',1]; // ->orWhere()
$filter['where'] = function($q) { 
    $q->where('pid','>=',0); 
    $q->orWhere('pid','<=',0);
};

$values = [
    ['type_a', 1],
    ['type_a', 2],
    ['type_b', 1],
    ['type_c', 1],
];

$filter['whereRowValues'] = [['column1', 'column2'],'=',['foo', 'bar']]; // orWhereRowValues()
$filter['whereInMultiple'] = ['morphable_type', 'morphable_id'], $values]; // ->whereNotInMultiple()
$filter['whereIn'] = ['uid',[1,2,3,4,5,6,7,8,9,10]]; // ->orWhereIn(), ->whereNotIn(), ->orWhereNotIn()
$filter['whereNull'] = 'keywords'; // ->orWhereNull(), ->whereNotNull(), ->orWhereNotNull()
$filter['whereBetween'] = ['uid',[1,1000]]; // ->whereNotBetween()
$filter['whereColumn'] = ['uid','!=','title'];

$filter['whereRaw'] = ['(uid > ? and uid < ?)', [1,1000]]; // DB::raw(1)
$filter['whereRaw'] = ["FROM_UNIXTIME(date_create, '%j') = ?", 11]; // %d -> with zero
$filter['whereRaw'] = ["FROM_UNIXTIME(date_create, '%n') = ?", 1]; // %m -> with zero
$filter['whereRaw'] = ["FROM_UNIXTIME(date_create, '%Y') = ?", 2021];

$filter['whereExists'] = function($q) { // ->orWhereExists(), ->whereNotExists(), ->orWhereNotExists()
    $q->select(DB::raw(1))->from('tablename')->whereRaw('uid > 0'); 
};

$filter['whereNested'] = function($query){
    $query->where('title', 'like', '1');
};

// Todo
// ->where created_at between (new DateTime("2021-01-13"))->getTimestamp() and (new DateTime("2021-01-14"))->getTimestamp()
// ->where('created_at', '=', date('Y-m-d')); 
// $q->whereDay('created_at', '=', date('d'));
// $q->whereMonth('created_at', '=', date('m'));
// $q->whereYear('created_at', '=', date('Y'));
// $q->where(DB::raw("DATE(created_at) = '".date('Y-m-d')."'"));
 
// whereDate() // ->whereDate('created_at', date('Y-m-d'))
// whereMonth() // ->whereMonth('created_at', '05')
// whereDay() // ->whereDay('created_at', '05')
// whereYear() // ->whereYear('created_at', '05')
// whereTime() // ->whereTime('created_at', '=', '1:20:45')
// protected $dates = [‘edited_at’];
// The following are the comparison functions of Carbon.
eq() - equals
ne() - not equals
gt() - greater than
gte() - greater than or equals
lt() - less than
lte() - less than or equals
Example:
if($model->edited_at->gt($model->created_at)){
// edited at is newer than created at
}

$filter['inRandomOrder'] = false; // true
$filter['orderBy.10'] = ['uid','desc'];
$filter['orderBy.20'] = ['title','desc'];
$filter['groupBy'] = 'title';

$filter['limit'] = 3;
$filter['offset'] = 0;
$filter['having'] = ['aliasID', '>', 0]; // orHaving, havingRaw

// ->with(), ->has(), ->whereHas(), orWhereHas()
// ->doesntHave(), ->whereDoesntHave(), ->withCount()
// ->wherePivot(), wherePivotIn()
$filter['with.10']  = [
    'propref_NAMEA' => function($q) {
        $q->with('propref_INNERNAME');
        $q->where('uid','>',0);
        $q->where('pid','>',0);
    }
];
$filter['with.20'] = 'propref_NAMEB.propref_INNERNAME';
$filter['with.30'] = 'propref_NAMEC';
$filter['with.40'] = 'propref_NAMED';

// Todo -> https://github.com/Waavi/model
// $posts = Post::whereNotRelated('author', 'name', '=', 'John')->get();
// $comments = Comment::whereRelated('post.author', 'name', '=', 'John')->get();
// WaaviModel::whereRelated($relationshipName, $column, $operator, $value);
// WaaviModel::orWhereRelated($relationshipName, $column, $operator, $value);
// WaaviModel::whereNotRelated($relationshipName, $column, $operator, $value);
// WaaviModel::orWhereNotRelated($relationshipName, $column, $operator, $value);

// ->unionAll() // $subQ = NewTable::recSelect('object', $filter);
$filter['union'] = ...;
$filter['join'] = ...;
$filter['leftJoin'] = ...;
$filter['crossJoin'] = ...;

$filter['mySelectMinimize'] = true; // or false
$filter['myWhereFlagDeletedIn'] = [0,1]; // 0, 1, [0,1]
$filter['myWhereFlagDisabledIn'] = [0,1]; // 0, 1, [0,1]
$filter['myPagination'] = [1,30]; // $pagePosition, $pageLimit, // ->forPage($page, $perPage);

$count = NewTable::recSelect('count', $filter);
$rows = NewTable::recSelect('get', $filter);

print "Count: " . $count . "<hr />";
foreach ($rows as $row) {
    print $row['title'] . " // ";
    print $row['propref_NAME']['title'] . "<br />";
}

...->encrypt('id')->get();
...->exclude('id', 'email')->get();
...->addScope('active')->get();
...->addScope('formatDate', 'd-m-Y')->get();

////////////////////////////////////////////////////////////////////////////////////////
// SELECT EAV 
// Entity–attribute–value
////////////////////////////////////////////////////////////////////////////////////////

$filter = [];
$filter['select'] = ['title','RType'];
$filter['selectAttributeAll'] = true; // attr.*' // Todo
$filter['selectAttribute.10'] = ['attr_color'];
$filter['selectAttribute.20'] = ['attr_email'];
$filter['where'] = ['RType',6]; // tx_data type
$filter['whereAttribute'] = ['attr_color', '#000000'];
$filter['orWhereAttribute'] = ['attr_color', '#eeeeee'];
$filter['orWhereAttribute'] = ['attr_color', '#3d0d0d'];
$filter['orderByAttribute'] = ['attr_color', 'desc'];

$rows = \Litovchenko\AirTable\Domain\Model\Content\Data::recSelect('get', $filter);
$count = \Litovchenko\AirTable\Domain\Model\Content\Data::recSelect('count', $filter);

////////////////////////////////////////////////////////////////////////////////////////
// INSERT
// ModelName::recInsert($data); // return last insert id
////////////////////////////////////////////////////////////////////////////////////////

$data = [];
$data['uid'] = uniqid('NEW_'); // :)
$data['title'] = '-- TITLE --';
$insertId = NewTable::recInsert($data);

$data = [];
$data[]['title'] = '-- TITLE №1 --';
$data[]['title'] = '-- TITLE №2 --';
$data[]['title'] = '-- TITLE №3 --';
$insertIds = NewTable::recInsertMultiple($data); // Inserted ID 99,9% authenticity :)

////////////////////////////////////////////////////////////////////////////////////////
// UPDATE
// ModelName::recUpdate($id || $filter || $callback, $data); // return affectedCount
////////////////////////////////////////////////////////////////////////////////////////

$recordId = 7;
$data = [];
$data['title'] = '-- TITLE --';
$affectedCount = NewTable::recUpdate($recordId, $data);
if ($affectedCount > 0) {
    echo 'Successfully ' . $affectedCount;
}

$data = [];
$data['title'] = '-- TITLE --';
$affectedCount = NewTable::recUpdate('full'); // Update all

////////////////////////////////////////////////////////////////////////////////////////
// DELETE 
// ModelName::recDelete($id || $filter || $callback, $destroy); // return affectedCount
////////////////////////////////////////////////////////////////////////////////////////

$recordId = 7;
$destroy = true; // If use \Litovchenko\AirTable\Domain\Model\Traits\Deleted;
$affectedCount = NewTable::recDelete($recordId, $destroy);
if ($affectedCount > 0) {
    echo 'Successfully ' . $affectedCount;
}

$destroy = true; // If use \Litovchenko\AirTable\Domain\Model\Traits\Deleted;
$affectedCount = NewTable::recDelete('full',$destroy); // Truncate
$affectedCount = NewTable::recDelete('full');

////////////////////////////////////////////////////////////////////////////////////////
// RELATIONSHIPS ->withoutGLobalScopes() always!!!
// Create and remove links between table records
////////////////////////////////////////////////////////////////////////////////////////

// !!! WARNING !!! ->withoutGLobalScopes() always !!! - sys_file_reference
// $relationship, $recordId, $idsToAttach(Detach) - sys_file
NewTable::mediaAttach('propmedia_NAME', 1, [1, 2, 3]);
NewTable::mediaAttach('propmedia_NAME', 1, 'fileadmin/ftpupload/1.jpg'); // or 1:/ftpupload/1.jpg
NewTable::mediaDetach('propmedia_NAME', 1, [1, 2, 3]);
NewTable::mediaDetach('propmedia_NAME', 1, null || 'all'); // detach all
NewTable::mediaDetach('propmedia_NAME', 1, 'fileadmin/ftpupload/1.jpg');

// !!! WARNING !!! ->withoutGLobalScopes() always !!!
// $relationship, $recordId, $idsToAttach(Detach)
NewTable::refAttach('propref_NAME', 1, [3, 4]);
NewTable::refDetach('propref_NAME', 1, 4);
NewTable::refDetach('propref_NAME', 1, null || 'all'); // detach all
NewTable::refCollection('propref_NAME', 1);
NewTable::refUpdatePivot(); // todo
NewTable::refSort(); // todo

 * Rel_1To1 / hasOne()
 * Rel_1ToM / hasMany()
   -------------------------------------------------------------------------------------------

 * Rel_MTo1 / belongsTo()
 * Rel_1To1_Inverse / belongsTo()
 * Rel_1ToM_Inverse / belongsTo()
   -------------------------------------------------------------------------------------------

 * Rel_MToM / belongsToMany()
 * Rel_MToM_Inverse / belongsToMany()
 * Pivot model: [Litovchenko\AirTable\Domain\Model\SysMm], pivot table: [sys_mm]
   -------------------------------------------------------------------------------------------

 * Rel_Poly_1To1 / morphOne()
 * Rel_Poly_1ToM / morphMany()
 * Rel_Poly_MToM // todo
 * Rel_Poly_1To1_Inverse // todo
 * Rel_Poly_1ToM_Inverse // todo
 * Rel_Poly_MToM_Inverse // todo
   -------------------------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////////////
// ADDING CUSTOM FUNCTIONS TO THE MODEL
////////////////////////////////////////////////////////////////////////////////////////

// A) Global scope (user function global scope register)
// See example: globalScopeFlagDeleted();
// $rows = NewTable::get(); // Results sorted by default by uid field
// $rows = NewTable::withoutGlobalScope('mySorting')->get(); // No sorting by default
public function globalScopeMySorting($builder) {
    $builder->orderBy('uid','desc');
}

// B) Local scope (user function local scope register)
// See example: scopeMyPagination();
// $rows = NewTable::myWhereActive(1,2)->get();
public function scopeMyWhereActive($query, $agr1 = 5, $arg2 = 4){
    return $query->where('uid','>',$agr1)->where('uid','<',$arg2);
}

// C) Relationship (user function register)
// $rows = NewTable::with('myref_relationship')->get();
public function myref_relationship() {
    return $this->refProvider('propref_***'); // Rel_1To1, Rel_1ToM, Rel_MTo1...
}

// D) Repository Pattern (getBy***)
// Todo
// Лучше использовать recSelect() + ...->addScope('active');
// --- $result_1 = NewTable::getById(230,'title'); // $id, $fields
// --- $result_2 = NewTable::getByList('title'); // $fields...

// E) Nested Set
// Todo 

////////////////////////////////////////////////////////////////////////////////////////
// OTHER
////////////////////////////////////////////////////////////////////////////////////////

$recordId = 18;
$is = NewTable::recIsDeleted($recordId); // If use \Litovchenko\AirTable\Domain\Model\Traits\Deleted;
if($is === true) {
    echo 'Yes';
}

$recordId = 18;
$is = NewTable::recIsDisabled($recordId); // If use \Litovchenko\AirTable\Domain\Model\Traits\Disabled;
if($is === true) {
    echo 'Yes';
}

$recordId = 18;
$is = NewTable::recIsPublished($recordId); // If use \Litovchenko\AirTable\Domain\Model\Traits\DateStart and DateEnd;
if($is === true) {
    echo 'Yes';
}

Стандартные модели, зарегестрированные в системе

\Litovchenko\AirTable\Domain\Model\Content\Data;
\Litovchenko\AirTable\Domain\Model\Content\DataCategory;
\Litovchenko\AirTable\Domain\Model\Content\Pages;
\Litovchenko\AirTable\Domain\Model\Content\TtContent;

\Litovchenko\AirTable\Domain\Model\Fal\SysFile;
\Litovchenko\AirTable\Domain\Model\Fal\SysFileMetadata;
\Litovchenko\AirTable\Domain\Model\Fal\SysFileReference;
\Litovchenko\AirTable\Domain\Model\Fal\SysFileStorage;
\Litovchenko\AirTable\Domain\Model\Fal\SysFilemounts;

$recordId = 1774; // or path: "fileadmin/ftpupload/6/look.com.ua-74892.jpg"
$image = $this->request->getArgument('form')['image']; // <f:form.upload property="image" />
SysFile::cmdAddToIndex('fileadmin/ftpupload/6/look.com.ua-74892.jpg'); // return $id; ! Registering a file if the file was added via FTP 
SysFile::cmdUpload($image,'fileadmin/ftpupload/8/', 'rename || replace || cancel'); // return $id;
SysFile::cmdCreate('', '-- CONTENT --'); // Todo...
SysFile::cmdUpdate('', '-- NEW CONTENT --', 'overwrite'); // Todo...
SysFile::cmdExists($recordId); // return true || false;
SysFile::cmdRename($recordId,'new-name5.jpg');
SysFile::cmdCopy($recordId,'fileadmin/new-name5.jpg', 'rename || replace || cancel');
SysFile::cmdMove($recordId, 'fileadmin/ftpupload/7/', 'rename || replace || cancel');
SysFile::cmdReplace($recordId); // Todo...
SysFile::cmdDownload($recordId); // Todo...
SysFile::cmdDelete($recordId);
SysFile::getPathById(1774);
SysFile::getIdByPath('fileadmin/ftpupload/6/look.com.ua-74892.jpg');

// Todo - https://laravel.su/docs/5.0/filesystem (Working with directories "SysFileStorage")
SysFileStorage::cmdDirCreate;
SysFileStorage::cmdDirRename;
SysFileStorage::cmdDirDelete;
...

\Litovchenko\AirTable\Domain\Model\SysMm; // All links of type "Rel_MToM" are stored here
\Litovchenko\AirTable\Domain\Model\SysNote;
\Litovchenko\AirTable\Domain\Model\SysRedirect;

\Litovchenko\AirTable\Domain\Model\Users\BeGroups;
\Litovchenko\AirTable\Domain\Model\Users\BeUsers;
\Litovchenko\AirTable\Domain\Model\Users\FeGroups;
\Litovchenko\AirTable\Domain\Model\Users\FeUsers;

// Other table
$filter = [];
$filter['select'] = ['id','identifier','tag'];
$filter['from'] = ['cache_pages_tags'];
$rows = \Litovchenko\AirTable\Domain\Model\DynamicModelCrud::recSelect('get',$filter); // Any tables 
// $rows = DB::table('cache_pages_tags'); // use Illuminate\Database\Capsule\Manager as DB; 

Валидация данных

<?php
////////////////////////////////////////////////////////////////////////////////////////
// VALIDATION
// v1) ModelCrud::validator($data=[], $context='default', $params=[], called_class()); // see "public static function validationRules($params=[])"
// v2) ModelForm::validator($data=[], $context='default', $params=[], called_class()); // see "public static function validationRules($params=[])"
// v3) \Litovchenko\AirTable\Validation\Validator::validator($data = [], $rules=[]);
// v4) MyValidatorName extends \Litovchenko\AirTable\Validation\Validator
////////////////////////////////////////////////////////////////////////////////////////

// ----------------
// v1, v2
// ----------------

$data = [];
$data['title'] = 'My Title';

$validator = NewTable::validator($data, 'checkPreInsert'); // class NewTable extends \Litovchenko\AirTable\Domain\Model\ModelCrud
$validator = NewForm::validator($data, 'checkPreInsert'); // class NewForm extends \Litovchenko\AirTable\Domain\Form\ModelForm
if ($validator->passes()) { } //ok
if ($validator->fails()) // error
{
    if ($validator->errors()->has('email')) {} // Check has error field
    $validator->errors()->add('field', 'Something is wrong with this field!'); // Add error
    $validator->errors()->toArray();
    $validDataAr = $validator->valid(); // Valid data
    $invalidDataAr = $validator->invalid(); // Invalid data
}

print '<hr >';

// ----------------
// v3, v4
// ----------------

// $data = $this->request->getArgument('form');
$data = []; 
$data['title'] = 'My Title';
$rules = [];
$rules = [
    'title' => [
        'name' => '--- NAME ---',
        'bail' => true, // Stop on first error 
        'required' => 'MSG ERROR - required',
        'min:1' => 'MSG ERROR - min', 
        'max:5' => 'MSG ERROR - max',
        'custom_rule:p1,p2,p3..' => 'MSG ERROR - my rule'
    ],
    // <f:form.upload property="image" />
    'image' => [
        'name' => '--- ONE IMAGE ---',
        'required' => 'MSG ERROR - required',
        // 'file' => 'MSG ERROR - only file', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'image' => 'MSG ERROR - only image', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'max:100' => 'MSG ERROR - max size', // max:10240 = max 10 MB. three zero "000"
        'mimes:png,jpg,jpeg,gif' => 'MSG ERROR - png,jpg,jpeg,gif'
    ],
    // <f:form.upload property="images" multiple="true" />
    'images' => [
        'name' => '--- MANY IMAGES ---',
        'required' => 'MSG ERROR - required',
        'min:3' => 'MSG ERROR - min', 
        'max:5' => 'MSG ERROR - max',
    ],
    'images.*' => [
        'required' => 'MSG ERROR - required',
        // 'file' => 'MSG ERROR - only file', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'image' => 'MSG ERROR - only image', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'max:100' => 'MSG ERROR - max size', // max:10240 = max 10 MB. three zero "000"
        'mimes:png,jpg,jpeg,gif' => 'MSG ERROR - png,jpg,jpeg,gif',
        'dimensions:min_width=100,min_height=100,max_width=1000,max_height=1000' => 'MSG ERROR - dimensions'
    ]
    // ... ... ...
];

$validator = \Litovchenko\AirTable\Validation\Validator::validator($data, $rules);
$validator->addExtension('custom_rule', function($attribute, $value, $parameters) // or "public function custom_rule_name($attribute, $value, $parameters, $validator) {}
{
    // return $value == $parameters[0];
    // return true; // or false
    if ($value == 'TYPO3') {
        return true; // Good
    } else {
        return false;
    }
});

// ??? addRule() ??? // Todo
// ??? validate() ??? // Todo
$v->sometimes('VAT', 'required|max:50', function ($input) {
    return $input->account_type == 'business';
});

if ($validator->passes()) { } //ok
if ($validator->fails()) // error
{
    if ($validator->errors()->has('email')) {} // Check has error field
    $validator->errors()->add('field', 'Something is wrong with this field!'); // Add error
    $validator->errors()->toArray();
    $validDataAr = $validator->valid(); // Valid data
    $invalidDataAr = $validator->invalid(); // Invalid data
}

VALIDATION (Laravel)

<?php
////////////////////////////////////////////////////////////////////////////////////////
// VALIDATION
// v1) ModelCrud::validator($data=[], $context='default', $params=[], called_class()); // see "public static function validationRules($params=[])"
// v2) ModelForm::validator($data=[], $context='default', $params=[], called_class()); // see "public static function validationRules($params=[])"
// v3) \Litovchenko\AirTable\Validation\Validator::validator($data = [], $rules=[]);
// v4) MyValidatorName extends \Litovchenko\AirTable\Validation\Validator
////////////////////////////////////////////////////////////////////////////////////////

// ----------------
// v1, v2
// ----------------

$data = [];
$data['title'] = 'My Title';

$validator = NewTable::validator($data, 'checkPreInsert'); // class NewTable extends \Litovchenko\AirTable\Domain\Model\ModelCrud
$validator = NewForm::validator($data, 'checkPreInsert'); // class NewForm extends \Litovchenko\AirTable\Domain\Form\ModelForm
if ($validator->passes()) { } //ok
if ($validator->fails()) // error
{
    if ($validator->errors()->has('email')) {} // Check has error field
    $validator->errors()->add('field', 'Something is wrong with this field!'); // Add error
    $validator->errors()->toArray();
    $validDataAr = $validator->valid(); // Valid data
    $invalidDataAr = $validator->invalid(); // Invalid data
}

print '<hr >';

// ----------------
// v3, v4
// ----------------

// $data = $this->request->getArgument('form');
$data = []; 
$data['title'] = 'My Title';
$rules = [];
$rules = [
    'title' => [
        'name' => '--- NAME ---',
        'bail' => true, // Stop on first error 
        'required' => 'MSG ERROR - required',
        'min:1' => 'MSG ERROR - min', 
        'max:5' => 'MSG ERROR - max',
        'custom_rule:p1,p2,p3..' => 'MSG ERROR - my rule'
    ],
    // <f:form.upload property="image" />
    'image' => [
        'name' => '--- ONE IMAGE ---',
        'required' => 'MSG ERROR - required',
        // 'file' => 'MSG ERROR - only file', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'image' => 'MSG ERROR - only image', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'max:100' => 'MSG ERROR - max size', // max:10240 = max 10 MB. three zero "000"
        'mimes:png,jpg,jpeg,gif' => 'MSG ERROR - png,jpg,jpeg,gif'
    ],
    // <f:form.upload property="images" multiple="true" />
    'images' => [
        'name' => '--- MANY IMAGES ---',
        'required' => 'MSG ERROR - required',
        'min:3' => 'MSG ERROR - min', 
        'max:5' => 'MSG ERROR - max',
    ],
    'images.*' => [
        'required' => 'MSG ERROR - required',
        // 'file' => 'MSG ERROR - only file', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'image' => 'MSG ERROR - only image', // new \Symfony\Component\HttpFoundation\File\UploadedFile();
        'max:100' => 'MSG ERROR - max size', // max:10240 = max 10 MB. three zero "000"
        'mimes:png,jpg,jpeg,gif' => 'MSG ERROR - png,jpg,jpeg,gif',
        'dimensions:min_width=100,min_height=100,max_width=1000,max_height=1000' => 'MSG ERROR - dimensions'
    ]
    // ... ... ...
];

$validator = \Litovchenko\AirTable\Validation\Validator::validator($data, $rules);
$validator->addExtension('custom_rule', function($attribute, $value, $parameters) // or "public function custom_rule_name($attribute, $value, $parameters, $validator) {}
{
    // return $value == $parameters[0];
    // return true; // or false
    if ($value == 'TYPO3') {
        return true; // Good
    } else {
        return false;
    }
});

// ??? addRule() ??? // Todo
// ??? validate() ??? // Todo
$v->sometimes('VAT', 'required|max:50', function ($input) {
    return $input->account_type == 'business';
});

if ($validator->passes()) { } //ok
if ($validator->fails()) // error
{
    if ($validator->errors()->has('email')) {} // Check has error field
    $validator->errors()->add('field', 'Something is wrong with this field!'); // Add error
    $validator->errors()->toArray();
    $validDataAr = $validator->valid(); // Valid data
    $invalidDataAr = $validator->invalid(); // Invalid data
}

Todo (задокументировать)

        //////////////////////////////////////
        // prop_*
        //////////////////////////////////////
        'dataFields' => [
            // Input
            'prop_nameinput' => [
                'type' => 'Input', // || Input.Int || Input.Number || Input.Float || Input.Link || Input.Color || Input.Email || Input.Password || Input.InvisibleInt || Input.Invisible
                'name' => 'Field Input',
                'max' => 100,
                'size' => 24,
                'liveSearch' => 1,

                //////////////////////////////////////
                // General settings for all types of fields
                //////////////////////////////////////
                'description' => '-------Description-------',
                'placeholder' => '-------Placeholder-------',
                'default' => '-------Default value-------',
                'show' => 1, // Show field in lists
                'required' => 1, // Required to fill
                'readOnly' => 1,
                'validationRules' => [
                    'required' => 1, // Todo Validator
                    'ruleName' => 1, // Todo Validator
                ],
                'onChangeReload' => 1, // Reload the form when the field value changes
                'displayCond' => 'USER:Litovchenko\AirTable\Domain\Model\Content\Data->isVisibleDisplayConditionMatcher:tx_data', // Example
                'exclude' => 1, // Todo

                // Required parameter - if typing of records ("RType") and (or) "tabs" is defined
                // Example 'position' => ['fields']['prop_***']['position'][][type|tab|position'] add to type "1" (RType)
                // Example 'position' => ['fields']['prop_***']['position'][]['*|mytab|100'] "*" adding to all types
                // Example 'position' => ['fields']['prop_***']['position'][]['1|mytab|100'] add to type "1" (RType)
                'position' => '*|props|10', // '<RType>|<Tab>|<Num>'
                // 'position' => [
                    // '*|props|10',
                    // 'news|props|10',
                    // 'article|props|10',
                    // ...
                // ],
            ],
            // Text
            'prop_nametext' => [
                'type' => 'Text', // || Text.Rte || Text.Code || Text.Table || Text.Invisible
                'name' => 'Field Text',
                'show' => 1,
                'liveSearch' => 1,
                'format' => 'css || html || javascript || php || typoscript || xml', // Text.Rte
                'preset' => 'default || full || default || ext_myext_preset', // Text.Code
            ],
            // Date
            'prop_namedate' => [
                'type' => 'Date', // || Date.DateTime || Date.Time || Date.TimeSec || Date.Year
                'name' => 'Field Date',
                'show' => 1,
            ],
            // Flag
            'prop_nameflag' => [
                'type' => 'Flag',
                'name' => 'Field Flag',
                'show' => 1,
                'items' => [
                    1 => 'Checked',
                ],
            ],
            // Switcher
            'prop_nameswitcher' => [
                'type' => 'Switcher', // || Switcher.Int
                'name' => 'Field Switcher',
                'show' => 1,
                'itemsProcFunc' => 'Mynamespace\Myext\Domain\Model\[SubFolder]\NewTable->doItems',
                'itemsModel' => 'Mynamespace\Myext\Domain\Model\###',
                'itemsWhere' => [
                    'where' => [
                        0 => 'table.field > 5'
                    ],
                    'orderBy' => [
                        0 => 'table.field desc'
                    ]
                ],
                'items' => [
                    0 => 'Zero',
                    1 => 'One',
                    2 => 'Two',
                    3 => 'Three',
                ],
            ],
            // Enum
            'prop_nameenum' => [
                'type' => 'Enum',
                'name' => 'Field Enum',
                'show' => 1,
                'itemsProcFunc' => 'Mynamespace\Myext\Domain\Model\[SubFolder]\NewTable->doItems',
                'itemsModel' => 'Mynamespace\Myext\Domain\Model\###',
                'itemsWhere' => [
                    'where' => [
                        0 => 'table.field > 5'
                    ],
                    'orderBy' => [
                        0 => 'table.field desc'
                    ]
                ],
                'items' => [
                    1 => 'One',
                    2 => 'Two',
                    3 => 'Three',
                ],
            ],
            // ...
        ],
    ];
    
    /// --- ПЕРЕНЕСТИ НА ОТДЕЛЬНЫЙ ФАЙЛ ---

    /**
     * Custom value set (user func)
     * It is possible to use a selection from the database
     * return $config
     */
    public static function doItems($config)
    {
        $itemList = []; // If database
        $config['items'][] = [100, 'New item 100'];
        $config['items'][] = [200, 'New item 200'];
        $config['items'][] = [300, 'New item 300'];
        return $config;
    }
}
« Обратно

Powered by TYPO3 v10, EXT:air_table
© 2022 «Iv-Litovchenko.Ru», карта сайта