8.4.2 wrong block ID in block controller

Permalink
Following this:
https://documentation.concrete5.org/developers/working-with-blocks/c...

I pass a block ID to JS which I then use to compare the received bID with the controller's block ID value. And that value is wrong.

Here's the action function:
public function action_rate($token = false, $bID = false) 
    {
        $data = $this->request->request->all();
        \Log::addInfo($this->bID . ', ' . $bID); // $this->bID is 550 while $bID is 551
        if ($this->bID != $bID) {
            array_push($this->form_errors, $this->error_token);
            echo $this->app->make('helper/json')->encode(['status' => 'error', 'errors' => $this->form_errors, 'bid'=>$this->bID, 'buid'=>$bID], JSON_UNESCAPED_UNICODE);
        }

I have 3 same block on the page with IDs 550, 551 and 552. And both the JS and Log confirm that $this->bID always equals the ID of the first block, it's always 550 even when the other blocks process.

Why does the controller take other block's ID and not its own?

linuxoid
 
ramonleenders replied on at Permalink Reply
ramonleenders
You mention you pass stuff with JS, but you have no JS code posted here. Did you try and look what happens without posting using JS? I'm assuming that's the issue here. If you just plain submit it and check for the ID's, concrete5 will loop the blocks and all will be OK. I'm guessing your JS/Ajax call will mess things up, so you can't use the $this->bID most likely (just implement it in another way I guess).
linuxoid replied on at Permalink Reply
linuxoid
$.ajax({
            dataType: "json",
            type: "post",
            data: {
                'buid': buid,
                'n': n,
            },
            url: url,
        })
        .done(function(response) {console.log(response['bid']+', '+response['buid']);

The JS returns incorrect code too. But regardless of JS, why would the controller have a wrong block ID? How is it even possible? It's not what goes though JS, it's its own variable.
ramonleenders replied on at Permalink Reply
ramonleenders
The answer is rather simple, you do a request to a URL. Normally, concrete5 will loop all the Blocks with that given Block Type. Afterwards, stuff will render. NOW, you do 1 (one, singular) JavaScript/Ajax request. That will mean the first of all the to be looped Blocks. Hence why I said "Did you try and look what happens without posting using JS?". So you can't check against $this->bID if you just call that URL once. You'd have to do it multiple times (which also doesn't make sense because you flood your site with unneeded requests). So the solution should be a little different then what you have right now. Just pass the bID and search the block data based upon that. Or perhaps others have ideas or perhaps you can come up with another solution yourself too maybe? Multiple roads lead to Rome :)
linuxoid replied on at Permalink Reply
linuxoid
The request is send on click from each block, the url is unique:
<?php $form_action = $view->action('rate', $app->make('token')->generate('rate_form_'.$bUID)); ?>
<form id="rate_form_<?php echo $bUID; ?>" action="<?php echo $form_action?>" method="post" accept-charset="utf-8">

and I echoed the bID in view - it's the same everywhere in the view, in JS, in returned response. But the controller's variable $this->bID is different. And I just can't understand why.

I haven't tried without ajax, the addon only works with it.
linuxoid replied on at Permalink Reply
linuxoid
Aha, I found what the problem is.

I had this code before:
if ($this->bID != $bID) {
            return false;
        }

which actually loops through the blocks as you said. But then someone at PRB told me I had to return an error message instead of just returning false. So I did. And that broke it. I went back to the original and now it all works fine.
mnakalay replied on at Permalink Reply
mnakalay
the reason I told you to return an error message instead of false is that your JS expects a JSON object back and throws an error when you return false. Either change your JS code or properly return a JSON object the same way you do later in the code or send it back to the PRB for more review.

If it broke it's because you didn't return the data you needed in your JSON object maybe.
mnakalay replied on at Permalink Reply
mnakalay
Something that maybe you didn't understand is the purpose of that first "if" comparing $bID and $this->bID.

$this->bID is the actual bID of the current block.

$bID, on the other hand, is the $bID you sent to your function.

Any time one of your blocks calls that function and sends data to it, all blocks of the same type on the page receive that call.

That is why you compare. You are telling the block "check the $bID and if it's not for you just ignore"

So all three blocks will send you back the same value for $bID when you trigger the function call on one block. It's the $bID sent to all by the call itself
linuxoid replied on at Permalink Reply
linuxoid
To be honest I didn't know it worked that way. Thanks for the details. It makes sense now.

But why should I return the error message? If I have 10 blocks on the same page, it will return 10 error messages?