Odeslání dat z PHP do JS a naopak

ForestCZE
Člen | 209
+
0
-

Ahoj, mám následující kód:

Presenter:

public function handleSnakeScore(): void
{
	$lastScore = $this->character->getSnakeScore($this->char->phone_number);
    $this->sendJson($lastScore);
}

JS:

function snake()
{
	var somePlayedScore = 50;

	var url = new URL(location.href);
    fetch(url + "&do=snakeScore")
    	.then(response => response.json())
    	.then(data => data = lastScore);

	console.log(lastScore); //zde se mi vypíše score z databáze, které je podle očekávání

	// A nyní potřebuji nějak aktualizovat hodnotu v databázi

	if(somePlayedScore > lastScore)
	{
		// vrať se z JS do Presentru a aktualizuj hodnotu v databázi
	}
}

Jak to z JS poslat zase zpět? Jsem z toho nějak mimo. Díky předem za pomoc.

Editoval ForestCZE (8. 7. 2021 5:21)

Kamil Valenta
Člen | 822
+
+2
-

Poslat XHR (ajax) request?

ForestCZE
Člen | 209
+
0
-

Kamil Valenta napsal(a):

Poslat XHR (ajax) request?

Byla by možná nějaká ukázka, prosím? Už to posílání z handle metody do JS je ajax, takže moc nevím, jak to myslíš.

dakur
Člen | 493
+
+1
-

@ForestCZE Pošleš druhý, kdy v query stringu či v body toho požadavku budeš mít data, která potřebuješ updatovat.

David Matějka
Moderator | 6445
+
0
-

Je zbytečný posílat druhý request. Prostě do toho prvního (třeba do query parametrů) přípoj to skóre. A ten if budeš mít v tom handle.

dakur
Člen | 493
+
0
-

@ForestCZE Ono totiž nic jako „vrať se z JS do presenteru“ není. Je browser a server, kteří mezi sebou komunikují. Browser posílá requesty, server odpovídá s response. To je celé. „Vrať se z JS do presenteru“ tedy ve skutečnosti znamená „pošli nový request“. Jestli je ten request synchronní (normální) nebo asynchronní (XHR/ajax), to už je jen detail.

Editoval dakur (8. 7. 2021 9:33)

dakur
Člen | 493
+
0
-

Je zbytečný posílat druhý request. Prostě do toho prvního (třeba do query parametrů) přípoj to skóre. A ten if budeš mít v tom handle.

@DavidMatějka To dost záleží na tom, čeho chce docílit. Jestli to chce updatnout v reakci na interakci uživatele, tak potřebuje druhý request.

Editoval dakur (8. 7. 2021 9:33)

David Matějka
Moderator | 6445
+
0
-

@dakur Dle kódu to nevypadá, že by mezi requestem a updatem byla nějaká interakce.

@ForestCZE Jo a ten js handler vlastne vůbec fungovat nemůže. V tom druhém then přepíšeš vrácena data nějakou hodnotou lastScore a výsledek serveru zahodis. A za druhé, ten console.log a if se provede okamžitě po vyvolání requestu, nikoliv po jeho dokončení. Ten obsluzny kód tak musíš mít v tom then

ForestCZE
Člen | 209
+
0
-

David Matějka napsal(a):

@dakur Dle kódu to nevypadá, že by mezi requestem a updatem byla nějaká interakce.

@ForestCZE Jo a ten js handler vlastne vůbec fungovat nemůže. V tom druhém then přepíšeš vrácena data nějakou hodnotou lastScore a výsledek serveru zahodis. A za druhé, ten console.log a if se provede okamžitě po vyvolání requestu, nikoliv po jeho dokončení. Ten obsluzny kód tak musíš mít v tom then

@dakur Žádná interakce tam není. Já pouze potřebuji vytáhnout poslední score hráče z DB, pak ho provnat s tím, co má v JS na klientovi (co nahrál) a pokud je to nahrané větší než to z DB, tak mu ho aktualizovat v DB.

@DavidMatějka Chápu, jak to myslíš, že se ta data ztratí, ale zbytek nedávám. Jsem z toho ještě víc zmatený než předtím…

Marek Znojil
Člen | 90
+
0
-

Pokud zjišťuješ skóre klienta až pomocí JS, tak to proveď pomocí dalšího requestu na endpoint tomu určený (V tvém případě třeba jiný handle.).

David Matějka
Moderator | 6445
+
+5
-

zadnej dalsi request neni potreba.

var somePlayedScore = 50;

var url = new URL(location.href);
url.searchParams.append('do', 'snakeScore')
url.searchParams.append('newScore', somePlayedScore )
fetch(url.toString())
	.then(it => it.json())
	.then(it => {
		// zpracovani response
	})

a handler

public function handleSnakeScore(int $newScore): void
{
	$lastScore = $this->character->getSnakeScore($this->char->phone_number);
	if ($newScore > $lastScore) {
		// update
	}
    $this->sendJson($lastScore);
}
ForestCZE
Člen | 209
+
0
-

David Matějka napsal(a):

zadnej dalsi request neni potreba.

var somePlayedScore = 50;

var url = new URL(location.href);
url.searchParams.append('do', 'snakeScore')
url.searchParams.append('newScore', somePlayedScore )
fetch(url.toString())
	.then(it => it.json())
	.then(it => {
		// zpracovani response
	})

a handler

public function handleSnakeScore(int $newScore): void
{
	$lastScore = $this->character->getSnakeScore($this->char->phone_number);
	if ($newScore > $lastScore) {
		// update
	}
    $this->sendJson($lastScore);
}

@DavidMatějka funguje to parádně. Akorát jsem zjistil, že mi ten JS funguje i takto:

var url = new URL(location.href);
url.searchParams.append('do', 'snakeScore');
url.searchParams.append('newScore', score);
fetch(url.toString());

jakože asi ani není potřeba zpracovávat ten response

bdump mi v Presenteru vrátí správné nové i poslední score.

Je to možné, že to funguje i bez toho? Měl jsem za to, že se ten response nějak zpracovat musí.
EDIT: dokonce ani $this->sendJson($lastScore); nepotřebuju. Nějak to moc nechápu :D

Editoval ForestCZE (8. 7. 2021 21:26)

David Matějka
Moderator | 6445
+
+1
-

Response zpracovávat ani odesílat nemusíš.

Šaman
Člen | 2667
+
+1
-

Jestli to chápu, jediný vstup od uživatele je jeho skóre. Zbytek server zná. Imho by stačil jeden formulář a jeho odeslání. JS jen zařídí to odeslání ajaxově, ale v principu je to stále jen poslat data na server, nechat ho ta data zpracovat a pak překreslit stránku tím, co server vrátí.

ForestCZE
Člen | 209
+
0
-

Šaman napsal(a):

Jestli to chápu, jediný vstup od uživatele je jeho skóre. Zbytek server zná. Imho by stačil jeden formulář a jeho odeslání. JS jen zařídí to odeslání ajaxově, ale v principu je to stále jen poslat data na server, nechat ho ta data zpracovat a pak překreslit stránku tím, co server vrátí.

No on to není vstup. To score se přičítá samo na pozadí v JS klientovi. Takže formulář je asi k ničemu.

ForestCZE
Člen | 209
+
0
-

David Matějka napsal(a):

Response zpracovávat ani odesílat nemusíš.

@DavidMatějka už ten příspěvek píšu po třetí. Vždycky vidím, jak to funguje, tak si řeknu ok, můj dotaz je zbytečný a pak zase nic. Snažím se překreslit tabulku se score. Jednou se to překreslí, 2× ne a prostě dělá si to, co chce.

Šablona:

{snippet snakesb}
    <table class="records records_h">
        <tr>
            <th>#</th>
            <th>Hráč</th>
            <th>Body</th>
        </tr>

        {var $order = 0}
        {foreach $scoreBoard as $player}
            {var $order += 1}
            <tr>
                <td>{$order}</td>
                <td>{$player->name}</td>
                <td>{$player->score}</td>
            </tr>
        {/foreach}
    </table>
{/snippet}

Handler:

public function handleSnakeScore(int $newScore): void
    {
        if(!$this->character->snakePlayerExists($this->char->phone_number))
            $this->character->createSnakePlayer($this->char->phone_number, $this->char->lastname . " " . $this->char->firstname);

        $lastScore = $this->character->getSnakePlayerScore($this->char->phone_number);
        if($newScore > $lastScore)
            $this->character->updateSnakePlayerScore($this->char->phone_number, $newScore);

        if($this->isAjax())
            $this->redrawControl('snakesb');
    }

JS:

var url = new URL(location.href);
            url.searchParams.append('do', 'snakeScore');
            url.searchParams.append('newScore', score);
            fetch(url.toString());

            $.ajax({
                type: 'POST',
                url: url.toString(),
                success: function(data){
                    $("#snippet--snakesb").html(data.snippets['snippet--snakesb']);
                }
            });

Nevím, co je špatně, ale prostě to funguje úplně na randoma. Někdy to překreslí a někdy ne…