Set priority for received requests

Hello,
It comes to my controller for a request. First Ajax, second POST.
Ajax sent from js-file.
Come in the sequence:
Ajax after POST.
I need the other way around. First POST, second Ajax.

This is very important because in POST request contains data for Ajax.

This is my code in controller :

public function cart()
{
    $cart = 'Shopping list';
    $token = $this->request->getParam('_csrfToken');
    $client = $this->Clients->newEntity();

    if ($this->request->is('post')) { 
        $client = $this->Clients->patchEntity($client, $this->request->getData());

        if ($this->Clients->save($client)) {
            $this->Id = $client['id'];
            $this->Flash->success(__('Your client has been saved.'));
        }
        $this->Flash->error(__('Unable to add your client.'));
    }

    if ($this->request->is('ajax')) { 
        $jsonData = $this->request->input('json_decode');
        
        for($i=0; $i<=count($jsonData); $i++){
            $order = $this->Clients_products->newEntity();

            $order->client_id = $this->Id; 
            $order->product_id = $jsonData[$i]->id;

            if ($this->Clients_products->save($order)) {
                $this->Flash->success(__('{0} is bought', $jsonData[$i]->name));
            }else{
                $this->Flash->success(__('{0} is not bought', $jsonData[$i]->name)); 
            }
        } 
    }

    $this->set(compact('cart', 'token', 'client'));
}

Your code certainly appears to be doing the Ajax processing after the POST processing. What, exactly, is not working about this setup?

When I buy, a modal window appears in which it is proposed to enter the buyer’s data (name and address).Further in POST request user is created with this data. Then to be processed Ajax request in which all purchases will be assigned to this user.

This is my all code in controller :

<?php // src/Controller/ProductsController.php namespace App\Controller; class CartController extends AppController { private $Id; public function initialize() { parent::initialize(); $this->loadComponent('Paginator'); $this->loadComponent('Flash'); // Include the FlashComponent $this->loadComponent('RequestHandler'); $this->loadModel('Clients'); $this->loadModel('Clients_products'); } public function cart() { $cart = 'Shopping list'; $token = $this->request->getParam('_csrfToken'); $client = $this->Clients->newEntity(); if ($this->request->is('post')) { $client = $this->Clients->patchEntity($client, $this->request->getData()); // $userId = $this->request->data['id']; // получение данных одного поля if ($this->Clients->save($client)) { $this->Id = $client['id']; $this->Flash->success(__('Your client has been saved.')); // return $this->redirect(['action' => 'cart']); } $this->Flash->error(__('Unable to add your client.')); } if ($this->request->is('ajax')) { $jsonData = $this->request->input('json_decode'); for($i=0; $i<=count($jsonData); $i++){ $order = $this->Clients_products->newEntity(); $order->client_id = $this->Id; $order->product_id = $jsonData[$i]->id; if ($this->Clients_products->save($order)) { $this->Flash->success(__('{0} is bought', $jsonData[$i]->name)); }else{ $this->Flash->success(__('{0} is not bought', $jsonData[$i]->name)); } } } $this->set(compact('cart', 'token', 'client')); } } This is all code in view :

<?= $cart ?>

</section>
<section>
    <table class="table">
    	<thead>
    		<tr>
    			<th  scope="col">Id</th>
    			<th  scope="col">Name</th>
    			<th  scope="col">Category</th>
    			<th  scope="col">Price</th>
    			<th  scope="col">Delete</th>
    		</tr>
    	</thead>
    	<tbody id="cart">

    	</tbody>
    	<tfoot>
    		<tr>
    			<th scope="col" colspan="3">Total price :</th>
    			<th scope="col"><span class='totalPrice'></span><span>p</span></th>
    			<?php 
				    $request = $this->Url->build(['controller' => 'cart', 'action' => 'add_order']);
				?>
    			<!-- <th><button class="btn btn-primary" onclick="checkout()">BUY!</button></th> -->
                <th><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#RegistrationWindow">BUY!</button></th>
    		</tr>
    	</tfoot>
    </table>
</section>
<div id="target" style="display: none;"><?= $token ?></div>
<!-- <div id="result"></div> -->

<!-- Modal -->
<div class="modal fade" id="RegistrationWindow" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Registration</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <?php
            echo $this->Form->create($client);
            echo $this->Form->control('id', ['type' => 'hidden']); ?>
                <?php echo $this->Form->control('name'); ?>
                <?php echo $this->Form->control('address'); ?>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <!-- <button type="button" class="btn btn-primary">Save changes</button> -->
                <?php echo $this->Form->button(__('To register'), ['class' => 'btn btn-primary', 'onclick' => 'checkout()']); ?>
            <?php echo $this->Form->end();
        ?>
      </div>
    </div>
  </div>
</div>

This is code in js :

function checkout(){
let order = [];
var csrfToken = $(’#target’).text();

for (var i = 0; i < count; i++) {
	var one_product = JSON.parse(localStorage.getItem(localStorage.key(i)));
	order.push(one_product);
}

order = JSON.stringify(order);

$.ajax({
	type: 'post',
	url: 'http://thc:81/cart/cart',
	data: order,
    beforeSend: function(xhr){
        xhr.setRequestHeader('X-CSRF-Token', csrfToken);
    },
    success: function(){
    	ord = JSON.parse(order);
    	console.log(ord);
		localStorage.clear();
    },
    error: function(e){
        alert("An error occurred: " + e.statusText);
        console.log(e);
    }
});

}

This is my log :

Unable to add your client.
tomato is bought
tomato is bought
tomato is bought
tomato is bought
tomato is bought
Your client has been saved.
Unable to add your client.

You have this code:

        if ($this->Clients->save($client)) {
            $this->Id = $client['id'];
            $this->Flash->success(__('Your client has been saved.'));
        }
        $this->Flash->error(__('Unable to add your client.'));

That is always going to generate the “Unable to add your client” message. You need to wrap that in an else block. And consider whether it’s possible to reasonably continue on to the Ajax portion if this save fails, or if you should return at that time.

Since you’re not getting the “Your client has been saved” message, there’s presumably something wrong with your entity. Check $client->errors() when it fails to see that problem, it’s likely a validation issue.

That! I didn’t notice that I missed ELSE. It baffled me. But all the same, the user is not saved at the first call. Then the purchase operation occurs and the user is saved …

This is terrible.

Logs :

Unable to add your client.
Banana is bought
plum is bought
Orange is bought
Orange is bought
potatoes is bought
Banana is bought
potatoes is bought
plum is bought
Banana is bought
Orange is bought
Banana is bought
Orange is bought
Banana added to customer base

Tell me what is this post request that comes first? It is empty and spoils the whole order. Or how to remove it?

What do you mean? How to remove your code? Just remove it. It’s your code, do what you want with it.

Are you saying that there are two separate requests being sent to your controller?

Three separate requests.

Post - I don’t know what it is. He is empty.
Ajax - orders
Post - save user.

I need to do the latter first than Ajax

Your user clicks one button and your controller receives three requests?

Yes. This is the whole problem. And I do not understand where the first request comes from ( POST )

It sound like you have lost control of the javascript on your page. You must be triggering a submit action by accident.

I think having a single click both a form post and make an ajax call is probably a bad idea.

I would use javascript to gather all the needed data together into one form or one json object, then do one post or one ajax call.

The controller can split the data and use the proper values in the order you require.

1 Like

Thanks for the advice, I will do just that.