JSON.parse

Discussion in 'PHP' started by comeoff, 20 Feb 2017.

  1. comeoff

    comeoff New Member

    Joined:
    10 Mar 2008
    Messages:
    89
    Likes Received:
    3
    Reputations:
    0
    Помогите пожалуйста разобраться.
    Постараюсь кратко описать суть скрипта.

    setInterval каждую секунду выполняет функцию, которая пост запросом отправляет текущее локальное время в формате чч:мм:сс на скрипт, который делает запрос в БД. В БД поля id, name, time, text (1, Alex, 12:13:14, Привет). Скрипт если в базе найдена запись по текущему времени возвращает ответ {"name":[name],"time":[time],"text_message":[text]}

    дальше JSON.parse парсит ответ сервера и на странице в конец контейнера вставляет полученные данные.
    так вот проблема в том, что если в БД есть две записи от одного и того же времени, секунда в секунду, то ответ от сервера будет в 2 строки, и JSON.parse уже не работает.

    Как сделать, чтобы он парсил обе строки, и вставлял в конец контейнера обе и более записи?

    HTML:
    <!doctype html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>VOI</title>
    <style>
    .block {width:300px; height:auto; margin:0 auto;}
    </style>
    <script
      src="https://code.jquery.com/jquery-2.2.4.min.js"
      integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
      crossorigin="anonymous"></script>
    <script>
    function addZero(i) {
        if (i < 10) {
            i = "0" + i;
        }
        return i;
    }
    function cron() {
        var date = new Date();
        var time = addZero(date.getHours()) + ':' + addZero(date.getMinutes()) + ':' + addZero(date.getSeconds());
        $.post("http://testscript.ru/voi/sql.php", {
                time: time
            },
            function(data) {
                if (!data) {
                    console.log("действие");
                } else {
                var user = (data);
                user = JSON.parse(user);
                $('#alert').prepend('<!--insert--><div style="padding:10px 0; border-bottom:1px dashed #bdc3c7; background-color: transparent;"><div style="width:30px; height:30px; float:left;"><div class="ava"></div><div style="clear:both;"></div></div><div style="width:360px; height:auto; float:left;"><div style="padding:0 15px; font-size:14px; color:#626161;"><font style="font-weight:700;">'+user.name+'</font> <font style=" font-size:12px; color:#bdc3c7;">написал в '+user.time+'</font></div><div style="padding:5px 15px; font-size:14px; color:#626161;">'+user.text_message+'</div><div style="color:#bdc3c7; font-size:11px; text-align:right; padding-top:5px;"></div></div><div style="clear:both;"></div></div><!--/insert-->');
              
                }
            });
    }
    setInterval(cron, 1000);
    </script>
    </head>
    
    <body>
    <div class="block">
      <div id="alert"></div>
    
    </div>
    </body>
    </html>
    
    sql.php
    PHP:
    $dat $_POST['time'];
    $dat trim($dat);
    $dat htmlspecialchars($dat);
    $link mysqli_connect("localhost""root""1234""voi");
    if (
    mysqli_connect_errno()) {
        
    printf("Соединение не установлено: %s\n"mysqli_connect_error());
        exit();
    }
    if (!empty(
    $dat)) {
      
        
    mysqli_set_charset($link"utf8");
      
        
    $query  "SELECT * FROM messages WHERE time='$dat'";
        
    $result mysqli_query($link$query);
        while (
    $row mysqli_fetch_assoc($result)) {
      
            echo 
    "{\"name\":\"".$row['name']."\",\"time\":\"".$row['time']."\",\"text_message\":\"".$row['text']."\"}\n";
        }
      
        
    mysqli_close($link);
    }
     
  2. bologer

    bologer Member

    Joined:
    25 Nov 2016
    Messages:
    62
    Likes Received:
    18
    Reputations:
    3
    Ты пытаешься сделать чат?
     
  3. comeoff

    comeoff New Member

    Joined:
    10 Mar 2008
    Messages:
    89
    Likes Received:
    3
    Reputations:
    0
    @bologer у меня есть чат, мне надо чтобы в определённые дни и время туда вставлялись нужные мне сообщения
     
  4. bologer

    bologer Member

    Joined:
    25 Nov 2016
    Messages:
    62
    Likes Received:
    18
    Reputations:
    3
    Ты хочешь чтобы без твоего нахождения на сайте "в определенные дни и время туда вставлялись сообщения"? Если да, то лучше крон сделать, а уже со стороны клиента setInterval который будет обновлять сообщения в чате. А вообще я бы порекомендовал использовать socket.io для чата, с ajax это насилие сайта, тем более если ты делаешь запросы каждую секунду.
     
    comeoff likes this.
  5. comeoff

    comeoff New Member

    Joined:
    10 Mar 2008
    Messages:
    89
    Likes Received:
    3
    Reputations:
    0
    @bologer крон не работает ежесекундно, там же вроде минимум 1 минута интервалы. или я ошибаюсь? да и на нагрузку пофиг, с этим проблем не будет.

    я это-то сделал "на коленке" т.к. в js вообще ничего не понимаю, только синтаксис да интуитивно. поэтому хочется уже решить проблему так, как начал, закончить, и другими делами заняться)) help

    готов к донату на киви или вэбмани))
     
    #5 comeoff, 20 Feb 2017
    Last edited: 20 Feb 2017
  6. sl1k

    sl1k Member

    Joined:
    31 Jul 2009
    Messages:
    106
    Likes Received:
    26
    Reputations:
    5
    Проблема у тебя не в JSON.parse а в этом куске

    Code:
        while ($row = mysqli_fetch_assoc($result)) {
    
            echo "{\"name\":\"".$row['name']."\",\"time\":\"".$row['time']."\",\"text_message\":\"".$row['text']."\"}\n";
        }
     
    comeoff likes this.
  7. bologer

    bologer Member

    Joined:
    25 Nov 2016
    Messages:
    62
    Likes Received:
    18
    Reputations:
    3
    Чтобы тебе вывести больше чем одну запись нужно:
    PHP:
    $result mysqli_query($link$query);
        while (
    $row mysqli_fetch_assoc($result)) {

            echo 
    "{\"name\":\"".$row['name']."\",\"time\":\"".$row['time']."\",\"text_message\":\"".$row['text']."\"}\n";
        }
    заменить на

    PHP:
    $result mysqli_query($link$query);
    echo 
    json_encode($result);
    }
    • в если post будет успешным , тогда выведи все данные в консоль, которые ты вытащил из базы с — console.log(data).
    • парси JSON и верни обратно в data - data = JSON.parse(data)
    • используй forEach() или for() цикл, чтобы append() каждую новую запись из объекта в контейнер (о котором ты говоришь в этом посте)
    HTML:
    function(data) {
        if (!data) {
            console.log("действие");
        } else {
        data = JSON.parse(data);
        console.log(data); // смотри в консоль, что выводится, чтобы понимать формат данных
    
        // и потом уже когда ты понял, что у тебя там - выводи их, например: data.username, data.id
        // for(var i = 0; i <= data.length - 1; i++) {
        //           console.log(data[i].id);
        //           console.log(data[i].username);
        // }
    
        }
    });
    
    Можно тебе JS чуть нужно будет поменять так как я не знаю как у тебя выглядят данные. Посмотри в консоли и уже от этого отталкивайся.

    P.s. При SELECT запросе в базу, выбери только те поля которые тебе действительно нужны, например "SELECT `id`, `username`, `message`", чтобы при ответе с сервера у тебя не показывало лишней информации.

    Я сейчас крайне занят, нашел минутку, чтобы тебе помочь.
     
    #7 bologer, 20 Feb 2017
    Last edited: 20 Feb 2017
    crlf, comeoff and kranx like this.
  8. sl1k

    sl1k Member

    Joined:
    31 Jul 2009
    Messages:
    106
    Likes Received:
    26
    Reputations:
    5
    Сделай так


    Code:
    $arr = [];
    while ($row = mysqli_fetch_assoc($result)) {
        $arr[] = [
            'name': $row['name'],
            ...
            ...
            ...
        ];
    };
    echo json_encode($arr);
     
    comeoff likes this.
  9. comeoff

    comeoff New Member

    Joined:
    10 Mar 2008
    Messages:
    89
    Likes Received:
    3
    Reputations:
    0
    сменил для дебага пост на гет, чтобы прямо с браузера отправлять данные. В общем отправляю гетом 11:18:20, в базе 2 записи под этим временем.
    PHP:
    <?php



    $dat 
    $_GET['time'];
    $dat trim($dat);
    $dat htmlspecialchars($dat);

    $link mysqli_connect("localhost""root""1234""voi");
    /* проверка соединения */
    if (mysqli_connect_errno()) {
        
    printf("Соединение не установлено: %s\n"mysqli_connect_error());
        exit();
    }

    if (!empty(
    $dat)) {

        
    mysqli_set_charset($link"utf8");

        
    $query  "SELECT * FROM messages WHERE time='$dat'";
        
    $result mysqli_query($link$query);
        while (
    $row mysqli_fetch_assoc($result))
            
    $resp[] = $row;
        
    $done json_encode($respJSON_UNESCAPED_UNICODE);
        if (
    $done == "null") {
            
    mysqli_close($link);
            die;
        } else {
            print 
    $done;
       
        }
        
    mysqli_close($link);
    }
    ?>
    ответ
    Code:
    [{"ID":"269","name":"Ваня","time":"11:18:20","text":"Привет Женя"},{"ID":"270","name":"Сергей","time":"11:18:20","text":"Привет Женёк"}]
    дальше пытаюсь в консоль вывести полученные данные, и получаю 2 раза по 4 ответа (undefined). почему?
    HTML:
    function addZero(i) {
        if (i < 10) {
            i = "0" + i;
        }
        return i;
    }
    
    function cron() {
        var date = new Date();
        var time = addZero(date.getHours()) + ':' + addZero(date.getMinutes()) + ':' + addZero(date.getSeconds());
        $.post("http://testscript.ru/voi/script.php", {
                time: time
            },
    
            function(data) {
    
                if (!data) {
                    console.log("действие");
                } else {
    
                    data = JSON.parse(data);
                    for (var i = 0; i <= data.length - 1; i++) {
                    
                  console.log(data.ID);
                  console.log(data.name);
                  console.log(data.time);
                  console.log(data.text);
                    }
    
                    /*
                var user = (data);
                user = JSON.parse(user);
           
                $('#alert').prepend('<!--insert--><div style="padding:10px 0; border-bottom:1px dashed #bdc3c7; background-color: transparent;"><div style="width:30px; height:30px; float:left;"><div class="ava"></div><div style="clear:both;"></div></div><div style="width:360px; height:auto; float:left;"><div style="padding:0 15px; font-size:14px; color:#626161;"><font style="font-weight:700;">'+user.name+'</font> <font style=" font-size:12px; color:#bdc3c7;">написал в '+user.time+'</font></div><div style="padding:5px 15px; font-size:14px; color:#626161;">'+user.text_message+'</div><div style="color:#bdc3c7; font-size:11px; text-align:right; padding-top:5px;"></div></div><div style="clear:both;"></div></div><!--/insert-->');
                */
    
                }
            });
    }
    setInterval(cron, 1000);
    @bologer спасибо что заглядываешь и подсказываешь :)
     
    #9 comeoff, 20 Feb 2017
    Last edited: 20 Feb 2017
  10. kranx

    kranx Member

    Joined:
    19 Feb 2017
    Messages:
    17
    Likes Received:
    7
    Reputations:
    0
    1. Ты сказал что передаешь данные через GET, что и видно в php скрипте, а на клиенте у тебя $.post, смени на $.get
    2. ОБЯЗАТЕЛЬНО перед селектом добавь
    Code:
    $dat = mysqli_real_escape_string($link, $dat);
    иначе будет возможна SQL инъекция
    3. четыре undefined это отсюда:
    Code:
    for (var i = 0; i <= data.length - 1; i++) {
    console.log(data.id);
    console.log(data.name);
    console.log(data.time);
    console.log(data.text_message);
    }
    там у тебя все 4 будут undefined так как ты время через POST передаешь.
     
    crlf and comeoff like this.
  11. comeoff

    comeoff New Member

    Joined:
    10 Mar 2008
    Messages:
    89
    Likes Received:
    3
    Reputations:
    0
    @kranx
    да это я для дебага менял на гет чтобы отправить данные удобнее было
    undefined это уже когда гет на пост заменён
     
  12. kranx

    kranx Member

    Joined:
    19 Feb 2017
    Messages:
    17
    Likes Received:
    7
    Reputations:
    0
    все, понял. вот как надо
    Code:
    for (var i = 0; i <= data.length - 1; i++) {
    console.log(data[i].ID);
    console.log(data[i].name);
    console.log(data[i].time);
    console.log(data[i].text_message);
    }
     
    comeoff and bologer like this.
  13. bologer

    bologer Member

    Joined:
    25 Nov 2016
    Messages:
    62
    Likes Received:
    18
    Reputations:
    3
    напиши "console.log(data)" в JS СНАРУЖИ цикла и отправь сюда результат, чтобы понимать, что тебе вообще возвращается обратно. Скорее всего ты не правильно выводишь данные и из-за этого не могу тебе точный вариант написать.



    Точно, совсем забыл дописать позиции i для каждого ряда :D

    UPD: исправил изначальный ответ, чтобы не путать людей.
     
    comeoff likes this.
  14. comeoff

    comeoff New Member

    Joined:
    10 Mar 2008
    Messages:
    89
    Likes Received:
    3
    Reputations:
    0
    @bologer @kranx СПАСИБИЩЕ, всё сделал :) круто!