There is a delivery service, customers are registered in it, each client can add several recipients by filling out a form in his office.

Here is the table for Recipients:

CREATE TABLE x_receivers ( id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, id_client bigint(20) UNSIGNED NOT NULL, surname varchar(255) NOT NULL, name varchar(255) NOT NULL, patronymic varchar(255) NOT NULL, ps_type tinyint(1) UNSIGNED NOT NULL COMMENT 'тип документа', ps_serial varchar(255) NOT NULL, ps_num varchar(255) NOT NULL, ps_code varchar(255) NOT NULL, ps_who varchar(255) NOT NULL, ps_when char(14) NOT NULL, postcode char(12) NOT NULL, country varchar(255) NOT NULL, area varchar(255) NOT NULL, city varchar(255) NOT NULL, street varchar(255) NOT NULL, house char(12) NOT NULL, room char(12) NOT NULL, sort tinyint(3) UNSIGNED NOT NULL, scan_1 varchar(255) NOT NULL COMMENT 'скан первой стр. паспорта', scan_2 varchar(255) NOT NULL COMMENT 'скан прописки', inn varchar(255) DEFAULT NULL, house_korp varchar(255) DEFAULT NULL, citizenship varchar(255) DEFAULT NULL, b_date char(14) DEFAULT NULL COMMENT 'Дата рождения', phone varchar(255) DEFAULT NULL, email varchar(255) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE = MYISAM, AUTO_INCREMENT = 37299, AVG_ROW_LENGTH = 341, CHARACTER SET utf8, CHECKSUM = 0, COLLATE utf8_general_ci; ALTER TABLE x_receivers ADD INDEX id_client (id_client); 

client model (a piece with saving and writing data to the database)

  /** * Получаем сохраненные адреса покупателя * * @deprecated * * @param bool $id * * @return mixed */ public static function getAddresses($id = false) { $user_id = $id ? (int)$id : (int)Client::get('id'); return DB::fetch('select address from #prefix#addresses where id_client = ? order by sort asc', $user_id); } /** * Сохраняем паспортные данные получателей * * @param array $receivers */ public static function saveReceivers(&$receivers = array()) { $user_id = (int)Client::get('id'); $receivers_ids = DB::shift_array('select id from #prefix#receivers where id_client = ?', $user_id); $receivers_ids = $receivers_ids ? $receivers_ids : array(); DB::execute('delete from #prefix#receivers where id_client = ?', $user_id); if ( $receivers ) { foreach( $receivers as $i => $receiver ) { $fields = array(); foreach( $receiver as $key => $field ) { if ( $key == 'id' ) { // если передается id, проверяем, чтобы он ранее пренадлежал текущему пользователю; // т.о. защищаем подмену чужого получателя if ( array_search((int)$field, $receivers_ids) === false ) { continue; } } // фильтруем значение от всякого мусора $fields[ $key ] = "'" . preg_replace('#[^\w\d\s\-\.\,\@\/]#ui', '', $field) . "'"; } $fields['sort'] = $i; // insert по одному, потому что у каждой записи может быть разный набор заполненных полей DB::execute('insert into #prefix#receivers (id_client, ' . join(', ', array_keys($fields)) . ") values ($user_id, " . join(', ', $fields) . ')'); // \clients\ReceiversHistory::saveItem(DB::last_id()); } } @setcookie('receivers', count($receivers), time() + conf('General', 'session_duration'), '/', $_SERVER['HTTP_HOST'], false, true); } /** * Получаем данные всех получателей клиента * * @param int|bool $id * @param bool $all * * @return object|bool */ public static function getReceivers($id = false, $all = false) { $user_id = $id ? (int)$id : (int)Client::get('id'); if ( $id && !$all ) { // получаем данные конкретного получателя return DB::single('select * from #prefix#receivers where id = ? order by sort asc', $user_id); } $receivers = DB::fetch('select * from #prefix#receivers where id_client = ? order by surname', $user_id); if ($receivers) { foreach( $receivers as $item ) { $item->regionid=Cities::getregionid($item->city,$item->country); } } @setcookie('receivers', count($receivers), time() + conf('General', 'session_duration'), '/', $_SERVER['HTTP_HOST'], false, true); return $receivers; } /** * Имеются ли у текущего пользователя получатели * * @return bool */ public static function hasReceivers() { if ( empty(self::getReceivers()) ) { return false; } return true; } /** * Принадлежит ли указанный получатель текущему пользователю * * @param int $receiver_id * * @return boolean */ public static function receiverExist($receiver_id) { return !!DB::shift('select id from #prefix#receivers where id_client = ? and id = ? order by sort asc limit 1', Client::$user->id, (int)$receiver_id); } 

The problem occurs when the client has 40+ recipients, that is, if you fill out a form for 41 recipients, it does not get into the database. If you do the opposite (add directly through the database), then 41 recipients will be visible. What could be the problem? What and how is it worth it first?

  • mariadb 10.1
  • php 7.0
  • elefantcms
  • one
    With the code I will not tell you, but according to the general logic, something like this. If you immediately send a bunch of requests, some may not be processed. Therefore, it is worthwhile to put a small delay between requests. And secondly, you need to check whether the request was successful and if not, then wait and repeat the request. - coder675
  • There is no limit in the table structure or in the model. Make sure that the request to add the 41st recipient reaches MySQL (see General Log). Get the answer of the MySQL server to try to add the 41st recipient and quote here. Check if there are any triggers on the recipients table. - Akina
  • from practice it was the filling of the table. 96 lines fills, 97 and ignores further. in fact, it turned out that the size of the POST request was exceeded. all further stupidly cut off. the data on the server went the whole pack at once. - teran
  • although in general probably not max_post_size is to blame, there all the same is 8 MB by default (although I still remember about 2). and in the case of overflow they promise that $_POST will be empty. In any case, look at how many records you have in the $_POST array. - teran
  • judging by the fact that all previous records are deleted from you, all data is also sent to the server in one request. so check that in principle pkhp gets them completely, and if not, then dig in the settings for the size of the request. - teran

1 answer 1

Judging by the code (deleting previous entries) you send all 40 entries at the same time.
in your table there are 27 fields, multiplying by 40 records it will be almost 1200 variables.

In php there is an option max_input_vars , which sets a limit on the number of variables passed. The default value is 1000, and you exceed it. (it can be concluded that you are apparently sending 25 fields out of 27, the id auto- client_id , and client_id logical to fill in the client_id on the server side from the session, and not to transfer).

max_input_vars integer

How many input variables can be taken in one request (the restriction is imposed on each of the global variables $_GET , $_POST and $_COOKIE separately). Using this directive reduces the likelihood of failures in the event of attacks using hash collisions. If there are more input variables than specified by the directive, the E_WARNING warning is thrown out, and all subsequent variables in the query are ignored.

So either increase the limit on the number of variables, or send data to the server in batches. The first option does not require a code change.