1

Buenas tardes. Hice un sitio web en el que incluí los precios de las clases de inglés usando "Switch" y luego agregando un condicional que verifique que la variable GET está declarada: if(isset($_GET['id'])) { //código } Me aparece el siguiente mensaje de error: Notice: Undefined index: id in C:\xampp\htdocs\Web Development\index.php on line 118

Notice: Undefined variable: number in C:\xampp\htdocs\Web Development\index.php on line 145

Notice: Undefined variable: duration in C:\xampp\htdocs\Web Development\index.php on line 148

Notice: Undefined variable: price in C:\xampp\htdocs\Web Development\index.php on line 151

No puedo identificar el problema. Éste es mi código:

<?php
        if(isset($_GET['id'])) {
        switch ($_GET['id']) {
            case '1l':
                $number = '1 lesson';
                
                $duration = '1 hour';
                
                $price = 'usd 6';
                break;
            case '6l':
                $number = '6 lessons';
                
                $duration = '1 hour each lesson';
                
                $price = 'usd 34';
                break;
            case '12l':
                $number = '12 lessons';
                
                $duration = '1 hour each lesson';
                
                $price = 'usd 68';
                break;
           }}
           ?>
        <div id="cont_pricing">
            <div id="txt_pricing">
            <p>
                <?php echo $number; ?>
                <br/>
                <br/>
                <?php echo $duration; ?>
                <br/>
                <br/>
                <?php echo $price; ?>
            </p>
            </div>
        </div> 

Quisiera saber cómo resolver el problema. Gracias

Cintia T
  • 13
  • 4
  • Cuando no está aignada `$_GET['id']` se salta el bloque if y entonces encuentra las variables sin definir... – Francisco Javier Jan 19 '22 at 17:09
  • ¿Cuál es la linea 118? Por otra parte, como bien señala @FranciscoJavier, no hay coherencia en tu código, no puedes pasar a un bloque sin que haya variables sin definir. Entonces, o das a un valor por defecto a esas variables, o replanteas totalmente la lógica de tu programa. – A. Cedano Jan 19 '22 at 17:11
  • Hola. La línea 118 es: ```switch ($_GET['id'])``` – Cintia T Jan 19 '22 at 17:26
  • @A.Cedano no tenemos una pregunta canonica sobre Undefined variable? es como un NPE en java o en c#... no deberiamos hacer una? – gbianchi Jan 19 '22 at 17:42
  • @gbianchi no sé si [esta](https://es.stackoverflow.com/q/79165/29967) podría ser ¿? Aunque trata de otros primos y hermanos... – A. Cedano Jan 19 '22 at 18:08
  • @A.Cedano podria ser.. pero yo apuntaria mas a algo mas pedagogico sobre causas y posibles soluciones, como tienen las otras.. aca claramente, id, no viene nunca en el get.. por lo cual, no importa como escriba el codigo, si no controla eso, no va a funcionar nada.. el resto, es lo mismo.. nunca se declaran (o porque el codigo falla, o porque declarar dentro de un switch es una pesima idea) – gbianchi Jan 19 '22 at 18:10
  • @gbianchi en ese caso me parece una buena idea lo que propones. – A. Cedano Jan 19 '22 at 18:13

1 Answers1

2

Verificar con isset siempre es recomendable, de lo contrario, tendrás un Undefined index si intentas a acceder a una clave del $_GET que no existe.

Por otra parte, no puedes intentar usar variables sin definirlas previamente, por lo que puedes definir los valores de dichas variables en el default.

Pero, así no queda resuelta la parte del else (porque el código no entraría en el bloque switch), debido a que tienes un if, el cual es innecesario si quieres asignar valores por defecto. El if tendría sentido si quisieras mostrar otra cosa distinta desde el else o dirigir el código por otro camino en ese caso o mostrar un mensaje de error.

En cualquier caso, yo lo resolvería usando un array, es más simple y más fácil de mantener.

Veamos todos los casos:

1. Con array, mostrando valores por defecto

/*
    Esto reemplaza a los case ...
    Si hubiera situaciones nuevas, solamente las agregas aquí
*/

$allData=
    array(
             '1l'=> array(
                'number' => '1 lesson',
                'duration' => '1 hour',
                'price' => 'usd 6'),
             '6l' => array(
                'number' => '6 lessons',
                'duration' => '1 hour each lesson',
                'price' => 'usd 34'),
            '12l' => array (
                'number' => '12 lessons',
                'duration' => '1 hour each lesson',
                'price' => 'usd 68'),
             'default' => array (
                'number' => '',
                'duration' => '',
                'price' => '')
    );

/*
   Obtienes la key desde el GET
   mediante operador de fusion de null
   si tu versión de PHP no lo soporta, usa esto en su lugar
   $key=!empty($_GET['id']) ? $_GET['id'] : 'default';
*/
$key=$_GET['id'] ?? 'default';
$html=sprintf(
'<div id="cont_pricing">
    <div id="txt_pricing">
        <p>
            %s                
            <br/>
            <br/>
            %s
            <br/>
            <br/>
            %s
         </p>
     </div>
</div>',$allData[$key]['number'],$allData[$key]['duration'],$allData[$key]['price']);
echo $html;

2. Con array y else (no hay valores por defecto)

/*
    Esto reemplaza a los case ...
    Si hubiera situaciones nuevas, solamente las agregas aquí
*/

$allData=
    array(
             '1l'=> array(
                'number' => '1 lesson',
                'duration' => '1 hour',
                'price' => 'usd 6'),
             '6l' => array(
                'number' => '6 lessons',
                'duration' => '1 hour each lesson',
                'price' => 'usd 34'),
            '12l' => array (
                'number' => '12 lessons',
                'duration' => '1 hour each lesson',
                'price' => 'usd 68')
    );

/*
   Obtienes la key desde el GET
   mediante operador de fusion de null
   si tu versión de PHP no lo soporta, usa esto en su lugar
   $key=!empty($_GET['id']) ? $_GET['id'] : 'default';
*/

$key=$_GET['id'] ?? null;
if (array_key_exists($key, $allData)) {
    $html=sprintf(
    '<div id="cont_pricing">
        <div id="txt_pricing">
            <p>
                %s                
                <br/>
                <br/>
                %s
                <br/>
                <br/>
                %s
             </p>
         </div>
    </div>',$allData[$key]['number'],$allData[$key]['duration'],$allData[$key]['price']);
} else {
    $html="Error. La clave $key no es válida";
}
echo $html;

3. Con switch (y valores por defecto)

/*
   Obtienes la key desde el GET
   mediante operador de fusion de null
   si tu versión de PHP no lo soporta, usa esto en su lugar
   $key=!empty($_GET['id']) ? $_GET['id'] : 'default';
*/
$key=$_GET['id'] ?? 'default';

      switch ($key) {
            case '1l':
                $number = '1 lesson';
                $duration = '1 hour';
                $price = 'usd 6';
                break;
            case '6l':
                $number = '6 lessons';
                $duration = '1 hour each lesson';
                $price = 'usd 34';
                break;
            case '12l':
                $number = '12 lessons';
                $duration = '1 hour each lesson';
                $price = 'usd 68';
                break;
             default:
                $number = '';
                $duration = '';
                $price = '';
             break;
           }

$html=sprintf(
'<div id="cont_pricing">
    <div id="txt_pricing">
        <p>
            %s                
            <br/>
            <br/>
            %s
            <br/>
            <br/>
            %s
         </p>
     </div>
</div>',$number, $duration, $price);

echo $html;

4. Con switch (y else y valores por defecto)

/*
   Obtienes la key desde el GET
   mediante operador de fusion de null
   si tu versión de PHP no lo soporta, usa esto en su lugar
   $key=!empty($_GET['id']) ? $_GET['id'] : 'default';
*/

$key=$_GET['id'] ?? null;

if ($key) {
    
      switch ($key) {
            case '1l':
                $number = '1 lesson';
                $duration = '1 hour';
                $price = 'usd 6';
                break;
            case '6l':
                $number = '6 lessons';
                $duration = '1 hour each lesson';
                $price = 'usd 34';
                break;
            case '12l':
                $number = '12 lessons';
                $duration = '1 hour each lesson';
                $price = 'usd 68';
                break;
             default:
                $number = '';
                $duration = '';
                $price = '';
             break;
           }
    
    $html=sprintf(
   '<div id="cont_pricing">
        <div id="txt_pricing">
            <p>
                %s                
                <br/>
                <br/>
                %s
                <br/>
                <br/>
                %s
             </p>
         </div>
    </div>',$number, $duration, $price);
} else {
    $html="Error. No se pasaron datos válidos";
}
echo $html;

De cualquiera de estas formas tu código debería funcionar. Lo fundamental es que:

  • Deberías primero capturar el valor del dato que viene en el $_GET, con un ternario o de otro modo.

  • Si usas switch ... case deberías prever la situación del default

  • Si ninguna condición se cumple, debes tener claro qué debe hacer el código en ese caso (por ejemplo, en el caso 4 si el GET tiene una clave id pero que no vale ninguno de los case, el código tomará los valores por defecto, y sólo entrará en el else cuando el GET no tenga una clave id).

A. Cedano
  • 86,578
  • 19
  • 122
  • 221
  • Hola A.Cedano. Probé con el ejemplo 1 "Con array, mostrando valores por defecto" y quedó perfecto. Te agradezco un montón por tu ayuda. Saludos! – Cintia T Jan 21 '22 at 15:01
  • @CintiaT me alegro de que te haya servido. La gran ventaja de esa solución es que si hubiera una situación nueva, solamente la agregas a `$allData` y no tienes que hacer más cambios en el código. – A. Cedano Jan 21 '22 at 17:06
  • Si la respuesta ha servido para solucionar tu problema considera marcarla como aceptada, de modo que la pregunta no aparezca como sin resolver y la respuesta dada pueda servir a futuros usuarios con un problema similar. Saludos. – A. Cedano Jan 21 '22 at 17:07