IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Récupérer variable php dans Javascript


Sujet :

JavaScript

  1. #21
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Je vois que l'on a pu ainsi récupérer le contenu du echo pour le placer dans le div.


    J'ai également essayé de modifié dynamiquement en passant un paramètre à la page et cela semble également modifier l'affichage.

    Merci beaucoup pour cet exemple !!

    Le getValue renvoie donc bien la chaine de caractère de la variable, il ne m'en fallait pas plus que ça

    Vraiment merci !


    Maintenant, il ne me reste plus qu'à essayer de comprendre comment cette ligne là arrive à me renvoyer la valeur en question =)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return(xhr.readyState==4&& xhr.status==200)?xhr.responseText:null;
    Je dois avouer que je n'ai jamais vu ce genre de syntaxe return a?b

  2. #22
    Membre émérite
    Avatar de Eric2a
    Homme Profil pro
    Technicien
    Inscrit en
    Septembre 2005
    Messages
    1 225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Corse (Corse)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 225
    Points : 2 411
    Points
    2 411
    Par défaut
    Il s'agit de L'opérateur (ternaire) conditionnel.

    Le code ci-dessous
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (condition)
    	return 'vrai';
    else
    	return 'faux';
    peut-être remplacer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return (condition) ? 'vrai' : 'faux';

  3. #23
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Ah d'accord, je le connaissais pas celui là =)

    Il est vrai que l'écriture va plus vite une fois que l'on a compris d'où ça vient


    Bon, ayant vu que cela fonctionnait sur des exemples simples, j'ai voulu essayer d'appliquer ça sur l'une de mes pages.

    Sauf que, je n'ai même pas pu y accéder, j'obtiens une erreur serveur 500.

    C'est la première fois que j'ai quelque chose comme ça, en général si le code est mauvais il est juste pas interprété par le serveur.


    Enfin bref, voyez vous dans le code suivant quelque chose pouvant provoquer un tel problème ?


    (Il est tout à fait possible que mes requêtes soit remplies d'erreurs, mais de là à provoquer une erreur du serveur ? Peut-être y a-il une façon de voir si une requete plante ou non ?)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    <?php 
      session_start();
    ?>
    <html>
        <head>
            <title>AttendMatch</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <script type="text/javascript" src="./wait.js"> </script>
        </head>
    
    <?php
      require_once("./../BDD/connect.php");
       $connexion = mysqli_connect(SERVEUR,NOM,PASSE,BASE);
        if(!$connexion) //si erreur
        {
                echo "Désolé, connexion à ".SERVEUR." temporairement impossible !";
                echo "Essayez plus tard !"; 
        }
        //CONNEXION OK
        $requete="select COUNT(idAtt) from WaitMatch"; 
        $resultat=mysqli_query($connexion,$requete);
        $value=mysqli_fetch_row($resultat);/*Valeur unique ==> [0]*/
        if($value==0){
            /*Personne n'attend un match, on est inséré dans la table
            On commence par récupérer notre id*/
            if(isset($_SESSION['pseudo'])){
                $pseudo=$_SESSION['pseudo'];
            }else{
                 header('Location: ./notFound.html');
            }
            $reqId="select idU from Utilisateur where (pseudo='$pseudo')";
            $resId=mysqli_query($connexion,$reqId);
            //Un seul résultat possible
            $emp=mysqli_fetch_assoc($resId));
            $myId=$emp['idU'];
            //Requete d'insertion le champ waiting est à false par defaut
            $insert="insert into WaitMatch(idU1) values ('$myId')";
            $resInsert=mysqli_query($connexion,$insert);
            //On est en attente de match
            ?>
            <body>
                <p onclick='alert(getValue())'>Toujours en attente ?</p>
            </body>
            <?php
        }else{
            if($value==1){
                /*Une personne attend, on lance le match après récupération de son id*/
                $reqIdAdv="select idU1 from WaitMatch";
                $resIdAdv=mysqli_query($connexion,$reqIdAdv);
                $idAdv=mysqli_fetch_assoc($resIdAdv));
                $id=$idAdv['idU1'];
                //On alter pour signifier qu'il n'y a plus besoin d'attendre à l'adversaire
                $alterWait="update WaitMatch set waiting = 'false' where waiting = 'true'
                                                                    and idU1='$id'";
                $resAlterWait= mysqli_query($connexion,$alterWait);    
                //a partir de l'id le pseudo de l'adv
                $reqPseudoAdv="select pseudo into Utilisateur where idU='$id'";
                $resPseudoAdv=mysqli_query($connexion,$reqPseudoAdv);
                $emp=mysqli_fetch_assoc($resPseudoAdv));
                $pseudoAdv=$emp['pseudo'];
                $_SESSION['pseudoAdv']=$pseudoAdv;
                /*On a le pseudo de l'adv, on peut supprimer dans la table
                $delWait="delete * from WaitMatch";
                $reqDel=mysqli_query($connexion,$reqDel);*/
    
                //On part en match
                header('Location: ./combat.php');
            }else{
                header('Location: ./notFound.html');
            }
        }
        
    ?>
    
    </html>
    La partie en rouge est celle qui devrait s'exécuter lorsque je fais mon test étant donné que la table WaitMatch est vide.

  4. #24
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    En phase de développement il faut faire afficher les erreurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    ou plus simplement configurer le serveur d'évaluation pour ne pas avoir à mettre ce code en haut de chaque page.

  5. #25
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Je l'ai rajouté en tête de mon fichier php et, aucun affichage, rien à part l'erreur 500.

  6. #26
    Membre émérite
    Avatar de Eric2a
    Homme Profil pro
    Technicien
    Inscrit en
    Septembre 2005
    Messages
    1 225
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Corse (Corse)

    Informations professionnelles :
    Activité : Technicien

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 225
    Points : 2 411
    Points
    2 411
    Par défaut
    Tu as modifié le fichier .htaccess entre temps ?

    Sinon, essaie ceci.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    <?php
    ini_set('display_errors', 1);
    error_reporting(E_ALL);
     
    session_start();
     
    function redirect($page){
    	if($page!=='')header('Location: ./'.$page);
    	exit();
    }
     
    require_once('./../BDD/connect.php');
    $connexion = mysqli_connect(SERVEUR,NOM,PASSE,BASE);
    if(!$connexion){ //si erreur
    	echo 'Désolé, connexion à '.SERVEUR.' temporairement impossible !';
    	echo 'Essayez plus tard !';
    	exit();
    }
     
    //CONNEXION OK
    $requete='select COUNT(idAtt) from WaitMatch'; 
    $resultat=mysqli_query($connexion,$requete);
    $value=mysqli_fetch_row($resultat);/*Valeur unique ==> [0]*/
    if($value==0){
    	/*Personne n'attend un match, on est inséré dans la table
    	On commence par récupérer notre id*/
    	$pseudo=isset($_SESSION['pseudo'])?$_SESSION['pseudo']:'';
    	if($pseudo=='')redirect('notFound.html');
     
    	$reqId='select idU from Utilisateur where pseudo="'.mysqli_real_escape_string($connexion,$pseudo).'"';
    	$resId=mysqli_query($connexion,$reqId);
    	//Un seul résultat possible
    	$emp=mysqli_fetch_assoc($resId));
    	$myId=$emp['idU'];
    	//Requete d'insertion le champ waiting est à false par defaut
    	$insert="insert into WaitMatch(idU1) values ('$myId')";
    	$resInsert=mysqli_query($connexion,$insert);
    	//On est en attente de match
    }elseif($value==1){
    	/*Une personne attend, on lance le match après récupération de son id*/
    	$reqIdAdv="select idU1 from WaitMatch";
    	$resIdAdv=mysqli_query($connexion,$reqIdAdv);
    	$idAdv=mysqli_fetch_assoc($resIdAdv));
    	$id=$idAdv['idU1'];
    	//On alter pour signifier qu'il n'y a plus besoin d'attendre à l'adversaire
    	$alterWait="update WaitMatch set waiting = 'false' where waiting = 'true' and idU1='$id'";
    	$resAlterWait= mysqli_query($connexion,$alterWait);    
    	//a partir de l'id le pseudo de l'adv
    	$reqPseudoAdv="select pseudo into Utilisateur where idU='$id'";
    	$resPseudoAdv=mysqli_query($connexion,$reqPseudoAdv);
    	$emp=mysqli_fetch_assoc($resPseudoAdv));
    	$pseudoAdv=$emp['pseudo'];
    	$_SESSION['pseudoAdv']=$pseudoAdv;
    	/*On a le pseudo de l'adv, on peut supprimer dans la table
    	$delWait="delete * from WaitMatch";
    	$reqDel=mysqli_query($connexion,$reqDel);*/
     
    	//On part en match
    	redirect('combat.php');
    }else{
    	redirect('notFound.html');
    }
    ?>
    <!DOCTYPE>
    <html>
    	<head>
    		<title>AttendMatch</title>
    		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    		<script type="text/javascript" src="./wait.js"></script>
    	</head>
    	<body>
    		<p onclick='alert(getValue())'>Toujours en attente ?</p>
    	</body>
    </html>
    Le but est d'éviter les appel à la fonction header() après avoir affiché le moindre caractère.

  7. #27
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Je n'ai pas ce fichier là. Je me suis pas renseigné sur Olympe plus que ça, mais je sais que certains fichiers comme php.ini sont inaccessible pour les utilisateurs.

    Je débuggue mon code petit à petit. Pas grand chose d'autre à faire de toute façon =)

    Et il semblerait que l'erreur vienne bien de mes requêtes.


    La première erreur que j'ai trouvé; mon $value était un array, il me fallait donc récupérer $value[0].

    La seconde semble être sur la forme de ma requête, vu que sans la requete je n'ai pas d'erreur 500.

    Le code suivant ne me semble pourtant pas faux...c'est étrange...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $reqId="select idU from Utilisateur where (pseudo='$pseudo')";
            $resId=mysqli_query($connexion,$reqId);
            //Un seul résultat possible
            $emp=mysqli_fetch_assoc($resId));
            $myId=$emp['idU'];
    Je finirais par trouver, en y allant pas à pas =)

    C'est quand même une belle merde à debug le php =)

    En tout cas

    Là j'ai une erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
       if($value[0]==0){
            /*Personne n'attend un match, on est inséré dans la table
            On commence par récupérer notre id*/
            if(isset($_SESSION['pseudo'])){
                $pseudo=$_SESSION['pseudo'];
            }else{
                 header('Location: ./notFound.html');
            }
            $reqId="select idU from Utilisateur where (pseudo='$pseudo')";
            $resId=mysqli_query($connexion,$reqId);
            //Un seul résultat possible
            $emp=mysqli_fetch_assoc($resId));
            $myId=$emp['idU'];
            echo $myId;
     
        }else{
            if($value[0]==1){
                echo "1";
            }else{
                echo "2";
            }
        }
     
    ?>
    Là je n'ai pas d'erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
       if($value[0]==0){
            /*Personne n'attend un match, on est inséré dans la table
            On commence par récupérer notre id*/
            if(isset($_SESSION['pseudo'])){
                $pseudo=$_SESSION['pseudo'];
            }else{
                 header('Location: ./notFound.html');
            }
        }else{
            if($value[0]==1){
                echo "1";
            }else{
                echo "2";
            }
        }
     
    ?>

  8. #28
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Faut débuger en local sur un serveur d'évaluation pour ne pas être dépendant de la configuration du serveur distant.

    Côté serveur distant les erreurs ne sont pas affichées car elles pourraient donner éventuellement des informations pour pirater le code.

    Et contrairement à ce que tu dis php est très facile à débugguer sauf que tu ne te mets pas dans les bonnes conditions pour le débuggage.

    Enfin bon maintenant que tu as trouvé le bloc qui buggue, la marche à suivre quand on a des difficultés pour voir le bug est d'extraire ce bloc de son contexte pour essayer ce fragment de code séparément dans un page vierge et mieux comprendre l'erreur.

  9. #29
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    J'aime pas bosser avec EasyPhp à cause de son interface de phpMyAdmin que je trouve vraiment lent, en tout cas en local sur mon ordi. Du coup c'est pour ça que je teste directement comme ceci.


    Par contre, j'ai pas essayé de lancer le php en local en gardant mes logs de BDD distant, si ça peut fonctionner de cette façon, c'est vrai que j'aurais tout intérêt à procéder ainsi

  10. #30
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Tu peux essayer wampserver plutôt qu'Easyphp. Cela dit le phpMyadmin risque d'être le même, mais si tu le trouve vraiment lent c'est sans doute que tu as eu un problème à l'installation. Donc tu devrais tenter de réinstaller Easyphp ou wampserver (après avoir désinstaller la version déjà existante).

    Ou tu peux aussi monter ta config toi-même mais cela demande plus de connaissances. En tous cas faut trouver une solution pour pouvoir faire des tests en local. Quand on crée du code c'est indispensable pour un débuggage facile, mais aussi plus rapide, et indépendant d'une connexion internet. Alors bon comme dirait l'autre, "faut te donner les moyens de ton ambition", sinon en testant uniquement sur un serveur distant sur lequel tu n'as pas la main pour la configuration, évidemment le débuggage risque d'être beaucoup plus compliqué et tu risque de perdre beaucoup de temps

  11. #31
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Pour la petite histoire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     $emp=mysqli_fetch_assoc($resId));
    J'avais une parenthèse de trop

    C'est vrai qu'en passant sous easyPhp, j'ai pu repérer l'erreur directement (enfin, après que la page ait chargé une bonne minute ).

    Je pense que je vais continuer à faire mon dev et mes tests avec l'hébergeur et mon ftp. Mais je testerais avec easyPhp si je rencontre un problème.



    Merci en tout cas pour votre aide à tous tout au long de ce sujet, j'ai de quoi avancer à présent. J'espère que ma solution de passer par la BD pour simuler une connexion fonctionnera

  12. #32
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Clairement avec une minute d'attente en local tu as un problème. Faudrait réinstaller ou changer pour voir.

    Sinon au passage si tu fais de nouveaux projets, ne traine pas trop avec mysqli qui est clairement destiné à mettre à jour d'anciens scripts faits avec mysql. Aujourd'hui c'est PDO, beaucoup plus rapide et agréable à écrire et plus puissant, notamment on peut mettre un tableau dans la fonction execute() et ça ça vaut des points. A+

  13. #33
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Pour tout te dire, j'ai eu tous mes cours à la fac sous my_sql.

    Ils les ont pas encore mis à jour d'ailleurs =)


    Donc, c'est vrai que j'ai choisi de passer sous my_sqli parce que c'était bien plus simple de migrer de l'un à l'autre.

    Je pense que j'essaierais un jour de m'autoformer sur pdo, ça doit pas être bien sorcier une fois qu'on a fait de la POO.
    Mais pour l'instant je préfère garder une forme que je connais pour mes requêtes, sachant que je veux surtout me forcer à travailler sur le Js.

    C'est con, mais arrivé en L3 à la fac, on a sorti aucun projet web réellement conséquent, mis à part de banales requêtes sql 'affichage et d'insertion.

    Donc j'essaie de faire un truc un peu plus costaud et perso; quitte à le mettre à jour après coup


    Pour en revenir à PDO, je n'ai jamais ressenti le besoin de m'en servir pour le moment, un jour ce sera le cas et je m'y mettrais =) Tout comme j'ai eu besoin de comprendre AJAX^^

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. variable php dans javascript
    Par thilde dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 24/01/2008, 11h32
  2. [PHP-JS] [Débutant]Variables php dans javascript
    Par Nibor dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 17/07/2007, 21h58
  3. [PHP-JS] Variables PHP dans JavaScript
    Par m3n2o dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 29/01/2007, 14h09
  4. [PHP-JS] Soucis variable php dans javascript.
    Par cisse18 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 13/07/2006, 11h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo