xhr.response会在我的PHP代码出现警告时设置为null吗?

huangapple go评论60阅读模式
英文:

Why is xhr.response set to null if a warning arises in my PHP code?

问题

The issue you are experiencing with xhr.response being set to null in your JavaScript code is likely due to the warning message generated in your PHP code. When a warning or error occurs in PHP, it can affect the response being sent back to the JavaScript code.

In your PHP code, you have this line that generates a warning when the $VALORES variable is not defined:

$RESPUESTA = $db->select($mysql, $VALORES);

If $VALORES is not defined, PHP will generate a warning message. Even though the warning doesn't halt the execution of your PHP script, it can still interfere with the response being sent back to the client (Postman in this case). The warning message might cause unexpected behavior in your JavaScript code when trying to process the response.

To resolve this issue, you have already removed the use of $VALORES, which is a valid solution. By removing it, you prevent the warning from being generated, and your PHP script should respond without any issues.

In summary, the warning in your PHP code could indirectly affect the response sent to your JavaScript code, causing xhr.response to be set to null. Removing the problematic code or handling the warning differently are both valid approaches to resolve this issue.

英文:

For clarification: the .php files are my professor's and are intended NOT to be changed. The problem arises because $VALORES in line 186 is uninitialized, and I already issued it to my professor.

This is the code:

  • nueva.html:
<form onsubmit="crearPublicacion(event);">
    <div>
        <label>Título:</label>
        <input type="text" name="titulo">
    </div>
    <div>
        <label>Texto:</label>
        <textarea name="texto"></textarea>
    </div>
    <div>
        <label>Zona:</label>
        <input type="text" name="zona">
    </div>
    <div id="fotos">
        <div>
            <input type="file" name="fotos[]" accept="image/*">
            <textarea name="descripciones[]"></textarea>
        </div>
        <div>
            <input type="file" name="fotos[]" accept="image/*">
            <textarea name="descripciones[]"></textarea>
        </div>
        <div>
            <input type="file" name="fotos[]" accept="image/*">
            <textarea name="descripciones[]"></textarea>
        </div>
        <div>
            <input type="submit">
        </div>
    </div>
</form>
  • nueva.js:
function crearPublicacion(evt) {
    evt.preventDefault();   // Cancela el comportamiento por defecto

    let xhr = new XMLHttpRequest(),
        url = 'api/publicaciones',
        fd  = new FormData(evt.currentTarget),
        usu = JSON.parse(sessionStorage['_datos_']),
        auth = `${usu.LOGIN}:${usu.TOKEN}`;
    
    xhr.open('POST', url, true);
    xhr.responseType = 'json';
    xhr.onload = (evt) => {
        let r = xhr.response;

        console.log(r);
    };
    xhr.setRequestHeader('Authorization', auth);
    xhr.send(fd);
}
  • publicaciones.php:
<?php
require_once('../inc/config.php'); // Constantes, etc ...
require_once('../inc/database.php');

$db    = new Database();
$dbCon = $db->getConnection();
$dbCon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

header("Access-Control-Allow-Orgin: *");
header("Access-Control-Allow-Methods: POST");
header("Content-Type: application/json; charset=UTF-8");

$RECURSO = explode("/", substr($_GET['prm'],1));
$headers = apache_request_headers();
if(isset($headers['Authorization']))
    $AUTORIZACION = $headers['Authorization'];
elseif (isset($headers['authorization']))
    $AUTORIZACION = $headers['authorization'];

if(!isset($AUTORIZACION))
{ // Acceso no autorizado
  $RESPONSE_CODE    = 403;
  $R['RESULTADO']   = 'ERROR';
  $R['CODIGO']      = $RESPONSE_CODE;
  $R['DESCRIPCION'] = 'Falta autorización';
}
else
{
  $R             = [];  // Almacenará el resultado.
  $RESPONSE_CODE = 200; // código de respuesta por defecto: 200 - OK
  $PARAMS = $_POST;
  list($login,$token) = explode(':', $AUTORIZACION);

  if( !$db->comprobarSesion($login,$token) )
  {
    $RESPONSE_CODE    = 401;
    $R['RESULTADO']   = 'ERROR';
    $R['CODIGO']      = $RESPONSE_CODE;
    $R['DESCRIPCION'] = 'Error de autenticación.';
  }
  else
  {
    $ID = array_shift($RECURSO);
    try{
      $dbCon->beginTransaction();
      if(!is_numeric($ID)) // NUEVO REGISTRO
      { // Si no es numérico $ID es porque se está creando un nuevo registro
        $titulo        = $PARAMS['titulo'];
        $texto         = nl2br($PARAMS['texto'],false);
        $zona          = $PARAMS['zona'];
        $descripciones = $PARAMS['descripciones'];

        $mysql = 'select * from zona where nombre=:ZONA';
        $RESPUESTA = $db->select($mysql, [':ZONA'=>$zona]);
        if( $RESPUESTA['CORRECTO'] ) // execute query OK
        {
          if(count($RESPUESTA['RESULT']) > 0)
          { // encontrado
            $idZona = $RESPUESTA['RESULT'][0]['id'];
          }
          else
          { // No existe la zona. Hay que crearla.
            $mysql = 'insert into zona(nombre) values(:NOMBRE)';
            if( $db->executeStatement($mysql, [':NOMBRE'=>$zona]) )
            {
              $mysql = 'select max(id) as idZona from zona';
              $RESPUESTA = $db->select($mysql, $VALORES);
              if( $RESPUESTA['CORRECTO'] ) // execute query OK
              {
                if(count($RESPUESTA['RESULT']) > 0)
                { // encontrado
                  $idZona = $RESPUESTA['RESULT'][0]['idZona'];
                }
              }
            }
          }
        }

        $mysql  = 'insert into publicacion(titulo,texto,idZona,autor) ';
        $mysql .= 'values(:TITULO,:TEXTO,:ID_ZONA,:AUTOR)';
        $VALORES             = [];
        $VALORES[':TITULO']  = $titulo;
        $VALORES[':TEXTO']   = $texto;
        $VALORES[':ID_ZONA'] = $idZona;
        $VALORES[':AUTOR']   = $login;

        if( $db->executeStatement($mysql, $VALORES) )
        {
          $mysql = "select MAX(id) as id_pub from publicacion";
          $RESPUESTA = $db->select($mysql);
          if($RESPUESTA['CORRECTO'])
          {
            $ID = $RESPUESTA['RESULT'][0]['id_pub'];

            $RESPONSE_CODE    = 201;
            $R['RESULTADO']   = 'OK';
            $R['CODIGO']      = $RESPONSE_CODE;
            $R['DESCRIPCION'] = 'Registro creado correctamente';
            $R['ID']          = $ID;
            $R['TITULO']      = $titulo;
            $R['FOTOS']       = $fotos;
          }
          else
            $ID = -1;
        }
        else
        {
          $RESPONSE_CODE    = 500; // INTERNAL SERVER ERROR
          $R['RESULTADO']   = 'ERROR';
          $R['CODIGO']      = $RESPONSE_CODE;
          $R['DESCRIPCION'] = 'Error indefinido al crear el nuevo registro';
        }
      }
      $dbCon->commit();
    }catch(Exception $e){
      echo $e;
      $dbCon->rollBack();
    }
  }
}
$dbCon = null;
http_response_code($RESPONSE_CODE);
echo json_encode($R);
?>
  • database.php:
<?php
class Database{
    private $HOST              = "127.0.0.1";
    private $DB_DATABASE_NAME  = "websocial";
    private $DB_USERNAME       = "pcw";
    private $DB_PASSWORD       = "pcw";
    public  $conn;

    public function __construct() {...}

    public function select($query = "" , $params = [])
    {
        $result = false;
        $RESPUESTA = [];

        try {
            $stmt = $this->conn->prepare( $query );
            if($stmt === false) {
                throw New Exception("Unable to do prepared statement: " . $query);
            }

            $stmt->execute($params);

            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
            $stmt->closeCursor();
            $RESPUESTA['CORRECTO'] = true;
        } catch(Exception $e) {
            // throw New Exception( $e->getMessage() );
            $RESPUESTA['CORRECTO'] = false;
            $RESPUESTA['ERROR'] = $e->getMessage();
        }

        $RESPUESTA['RESULT'] = $result;

        return $RESPUESTA;
    }

    public function executeStatement($query = "", $params = [])
    {
        $retVal = false;
        try {
            $stmt = $this->conn->prepare( $query );
 
            if($stmt === false) {
                throw New Exception("Unable to do prepared statement: " . $query);
            }
 
            if( $params )
                $retVal = $stmt->execute($params);
            else
                $retVal = $stmt->execute();

        } catch(Exception $e) {
            throw New Exception( $e->getMessage() );
        }   

        return $retVal;
    }

}
?>

As you can see, $VALORES (publicacion.php) has not been initialized when calling select in line 186 (that is the warning it gives me whenever I try to do a POST in Postman). The solution is as easy as to remove $VALORES altogether.

To give you an idea, this is the expected result:

{
    "RESULTADO": "OK",
    "CODIGO": 201,
    "DESCRIPCION": "Registro creado correctamente",
    "ID": 109,
    "TITULO": "",
    "FOTOS": []
}

But this is what happens only when the value for "zona" does not exist yet in the database (if it already exists, then the response is always the above):

  • Postman:

>Warning: Undefined variable $VALORES in C:\xampp\htdocs\pcw\practica2\api\post\publicaciones.php on line 186

{
    "RESULTADO": "OK",
    "CODIGO": 201,
    "DESCRIPCION": "Registro creado correctamente",
    "ID": 109,
    "TITULO": "",
    "FOTOS": []
}
  • JS console in VSCode debugger / Web DevTools:
null

As I stated before, I already solved the problem, but my question is about why does it happen and where exactly.

What moment my xhr.response sets to null? The only explanation I could find is that rising a warning somehow nullifies the response even if the code is running alright (i.e., without falling into catch and throw statements and without exiting at all).

答案1

得分: 0

"When setting responseType to a particular value, the author should make sure that the server is actually sending a response compatible with that format. If the server returns data that is not compatible with the responseType that was set, the value of response will be null.

With xhr.responseType = 'json'; you told the browser that the response would be JSON, and that it should automatically parse it as such for you.

But "random PHP warning message followed by some JSON" is not valid JSON. And so it set the value of your response to null."

英文:

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType#value:

> When setting responseType to a particular value, the author should make sure that the server is actually sending a response compatible with that format. If the server returns data that is not compatible with the responseType that was set, the value of response will be null.

With xhr.responseType = 'json'; you told the browser, that the response would be JSON, and that it should automatically parse it as such for you.

But "random PHP warning message followed by some JSON" is not valid JSON. And so it set the value of your response to null.

huangapple
  • 本文由 发表于 2023年4月13日 18:19:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76004298.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定