PHP создание многомерного массива потоков сообщений из многомерного массива (IMAP)


Мой вопрос заключается в следующем:

Если вы посмотрите ниже, вы увидите структуру данных с идентификаторами сообщений, а затем окончательную структуру данных, содержащую сведения о сообщении, которые должны быть объединены из imap_fetch_overview. Идентификаторы сообщений взяты из imap_thread. Проблема в том, что он не помещает данные электронной почты в положение, в котором находится идентификатор сообщения.

Вот моя структура данных:

[5] => Array
    (
        [0] => 5
        [1] => 9
    )

[10] => Array
    (
        [0] => 10
        [1] => 11
    )

То, что я хотел бы иметь, это:

[5] => Array
    (
        [0] => messageDetails for id 5
        [1] => messageDetails for id 9
    )

[10] => Array
    (
        [0] => messageDetails for id 10
        [1] => messageDetails for id 11
    )

Вот код, который у меня есть таким образом далеко:

$emails = imap_fetch_overview($imap, implode(',',$ids));

// root is the array index position of the threads message, such as 5 or 10
foreach($threads as $root => $messages){

    // id is the id being given to us from `imap_thread`
    foreach($message as $key => $id){

      foreach($emails as $index => $email){

         if($id === $email->msgno){
             $threads[$root][$key] = $email;
             break;
          }
      }
    }
 }

Вот распечатка одного из электронных писем $:

    [0] => stdClass Object
    (
        [subject] => Cloud Storage Dump
        [from] => Josh Doe
        [to] => [email protected]
        [date] => Mon, 21 Jan 2013 23:18:00 -0500
        [message_id] => <[email protected]>
        [size] => 2559
        [uid] => 5
        [msgno] => 5
        [recent] => 0
        [flagged] => 0
        [answered] => 1
        [deleted] => 0
        [seen] => 0
        [draft] => 0
        [udate] => 1358828308
    )

Если вы заметили, msgno равно 5, что соответствует $id, поэтому технически данные должны заполняться в окончательной структуре данных.

Кроме того, это кажется неэффективным способом справиться с этим.

Пожалуйста, дайте мне знать, если вам понадобятся какие-либо дополнительные разъяснения.

КОД ОБНОВЛЕНИЯ

Этот код представляет собой комбинацию кода, который я нашел в php api, и некоторых исправлений, сделанных мной. Что я считаю проблематичным, так это то, что $root.

$addedEmails = array();
$thread = imap_thread($imap);
foreach ($thread as $i => $messageId) { 
    list($sequence, $type) = explode('.', $i); 
    //if type is not num or messageId is 0 or (start of a new thread and no next) or is already set 
   if($type != 'num' || $messageId == 0 || ($root == 0 && $thread[$sequence.'.next'] == 0) || isset($rootValues[$messageId])) { 
    //ignore it 
    continue; 
} 

if(in_array($messageId, $addedEmails)){
    continue;
}
array_push($addedEmails,$messageId);

//if this is the start of a new thread 
if($root == 0) { 
    //set root 
    $root = $messageId; 
} 

//at this point this will be part of a thread 
//let's remember the root for this email 
$rootValues[$messageId] = $root; 

//if there is no next 
if($thread[$sequence.'.next'] == 0) { 
    //reset root 
    $root = 0; 
    } 
  }
$ids=array();
$threads = array();
foreach($rootValues as $id => $root){
    if(!array_key_exists($root,$threads)){
        $threads[$root] = array();
    }
    if(!in_array($id,$threads[$root])){
        $threads[$root][] = $id;
       $ids[]=$id;
    }
 }
 $emails = imap_fetch_overview($imap, implode(',', array_keys($rootValues)));

 $keys = array();
 foreach($emails as $k => $email)
 {
$keys[$email->msgno] = $k;
 }

 $threads = array_map(function($thread) use($emails, $keys)
{
// Iterate emails in these threads
return array_map(function($msgno) use($emails, $keys)
{
    // Swap the msgno with the email details
    return $emails[$keys[$msgno]];

}, $thread);
}, $threads);
Author: jkushner, 2013-04-27

4 answers

Помните, что в php любая функция, которую вы используете, будет окончательно преобразована в какой-то цикл. Однако есть некоторые шаги, которые вы могли бы предпринять, чтобы сделать его более эффективным, и они отличаются в PHP 5.5 и в 5.3/5.4.

PHP 5.3/5.4 способ

Наиболее эффективным способом сделать это было бы разделить функцию на 2 отдельных шага. На первом этапе вы должны сгенерировать карту ключей для списка электронных писем.

$keys = array();
foreach($emails as $k => $email)
{
    $keys[$email->msgno] = $k;
}

На 2-м шаге вы повторяете все значения в многомерные потоки $ и замените их данными электронной почты:

// Iterate threads
$threads = array_map(function($thread) use($emails, $keys)
{
    // Iterate emails in these threads
    return array_map(function($msgno) use($emails, $keys)
    {
        // Swap the msgno with the email details
        return $emails[$keys[$msgno]];

    }, $thread);

}, $threads);

Доказательство концепции: http://pastebin.com/rp5QFN4J

Объяснение ключевого слова использование в анонимных функциях:

Чтобы использовать переменные, определенные в родительской области, можно импортировать переменные из родительской области в область замыкания с помощью ключевого слова use (). Хотя он был представлен в PHP 5.3, он не был задокументирован в официальном PHP руководства пока нет. Здесь есть только черновик документа на вики php https://wiki.php.net/rfc/closures#userland_perspective

PHP 5.5

Одна из новых функций в этой версии позволяет использовать генераторы, которые имеют значительно меньший объем памяти, поэтому являются более эффективными.

Объяснение ключевого слова выход в генераторах:

Сердцем функции генератора является ключевое слово yield. В своей простейшей форме заявление о доходности выглядит очень похоже на оператор return, за исключением того, что вместо остановки выполнения функции и возврата, yield вместо этого предоставляет значение коду, зацикливающемуся на генераторе, и приостанавливает выполнение функции генератора.

1-й шаг:

function genetateKeyMap($emails)
{
    foreach($emails as $k => $email)
    {
        // Yielding key => value pair to result set
        yield $email->msgno => $k;
    }
};
$keys = iterator_to_array(genetateKeyMap($emails));

2-й шаг:

function updateThreads($emails, $threads, $keys)
{
    foreach($threads as $thread)
    {
        $array = array();

        // Create a set of detailed emails
        foreach($thread as $msgno)
        {
            $array[] = $emails[$keys[$msgno]];
        }

        // Yielding array to result set
        yield $array;
    }
};
$threads = iterator_to_array(updateThreads($emails, $threads, $keys));

Несколько слов о значениях, возвращаемых генераторами:

Генераторы возвращают объект, который является экземпляром итератора SPL, поэтому ему необходимо использовать iterator_to_array(), чтобы преобразовать его в точно такая же структура массива, которую ожидает ваш код. Вам не нужно этого делать, но для этого потребуется обновить ваш код, следуя функции генератора, что может быть еще более эффективным.

Доказательство концепции: http://pastebin.com/9Z4pftBH

Производительность тестирования:

Я сгенерировал список из 7000 потоков по 5 сообщений в каждом и проверил производительность каждого метода (в среднем из 5 тестов):

                   Takes:       Memory used:
                   ----------------------------
3x foreach():      2.8s              5.2 MB
PHP 5.3/5.4 way    0.061s            2.7 MB
PHP 5.5 way        0.036s            2.7 MB

Хотя результаты на вашем компьютере/сервере могут быть другим, но обзор показывает, что 2-шаговый метод примерно в 45-77 раз быстрее, чем при использовании 3 циклов foreach

Тестовый сценарий: http://pastebin.com/M40hf0x7

 4
Author: WooDzu, 2013-07-10 21:21:44

Когда вы печатаете массив $email, какую структуру вы получаете? Может быть, это должно быть сделано ниже?

 $threads[$root][$key] = $emails[$key];
 2
Author: georgec20001, 2013-07-09 21:03:54

У меня сейчас нет доступа к PHP для тестирования, но я верю, что вы пытаетесь сделать что-то вроде

foreach($emails as $email) {
    foreach($threads as $root => $messages) {
        foreach($messages as $index =>$message_id){
            if($message_id == $email->msgno){
                 $threads[$root][$index] = $email;
            }
        }
    }
}

При этом, даже если это сработает, вероятно, есть более эффективный способ подойти к этому, чем с тремя вложенными циклами. По какой причине вам необходимо хранить выходные данные в этом формате?

 0
Author: aelfric5578, 2013-07-09 21:28:56

Реализация с ветвями (более сложная, чем один поток array('5' => array(5,7,8)), но если я не разговаривал только с 1 человеком, потоки всегда имеют тенденцию ветвиться лично для меня, поэтому мне придется справиться с дополнительной сложностью)

<?php 
$threads = imap_thread($imap, SE_UID);
/*
 * threads returns entries as follows:
 * <id>.num = <messageid>
 * <id>.next = <messageid of first reply to <id>>,  0 = no replies
 * <id>.branch = <messageid of nth. reply to <parent of id>>, 0 = no more branches
 * Keep in mind: _every_ message 'starts' a branch, but that may be empty.
 */
$nodes = array( 0 => array( 'children' => array()));
$ids = array();
foreach ($threads as $key => $val) {
    list($treeid,$type) = explode('.',$key);
    switch($type){
        case 'num':
            //the actual message number of this tree node
            //store id for retrieval later:
            $ids[$val] = null;
            if($val==0){
                //return to root
                $nodes[$treeid] = &$nodes[0];
            } else {
                if(!isset($nodes[$treeid])) $nodes[$treeid] = array();
                $nodes[$treeid] = array_merge($nodes[$treeid],array(
                    'id' => $val,
                    'message' => &$ids[$val],
                    'treeid' => $treeid));
            }
            break;
        case 'next':
            // 0 means no next message, anything else is a reply
            if (0!=$val) {
                if(!isset($nodes[$val])) $nodes[$val] = array('parent' => $treeid);
                $nodes[$treeid][] = &$nodes[$val];
            }
            break;
        case 'branch':
            //0 means end of branch, a number means continue as sibling \
            //so we need to know the parent
            if (0!=$val) {
                if(!isset($nodes[$val])) $nodes[$val] = array('parent' => $nodes[$treeid]['parent']?:0);
                $nodes[$nodes[$val]['parent']][] = &$nodes[$val];
            }
            break;
        default:
            trigger_error("Unknown tree traverse-type: $type", E_USER_WARNING);
    }
}
//the great thing is we can get all our ID's at once:
$keystofetch = implode(',',array_filter(array_keys($nodes)));
$messages = imap_fetch_overview($imap,$keystofetch, FT_UID);
foreach($messages as $message){
    // you can of course store the _whole_ message in this thread like:
    // $nodes[$message->uid]['message'] = get_object_vars($message);
    // and do what you like with $tree[0]['children'] (be it a resursive array iterator,
    // or a  resursive function, your pick.
    // However, for this example we are going to only set message to a string of p.o.c 
    // (which is also nicer for our treeiterator)
    $ids[$message->uid] = $message->from.':'.$message->subject;
}
//let's show the result:
$it = new RecursiveTreeIterator(new RecursiveArrayIterator($nodes[0]),
    RecursiveTreeIterator::BYPASS_CURRENT,
    CachingIterator::TOSTRING_USE_KEY);
foreach($it as $key => $item){
    echo "$key".(is_scalar($item)?': '.$item:'').PHP_EOL;
}

Которые дают нам:

|-children
|-0
| |-parent: 0
| |-id: 35
| |-message: Friend Purple Acc2 <[email protected]>:A bigger message thread
| |-treeid: 1
| \-0
|   |-parent: 1
|   |-id: 7
|   |-message: Friend White <[email protected]>:Re: A bigger message thread
|   |-treeid: 2
|   \-0
|     |-parent: 2
|     |-id: 11
|     |-message: Friend Grey <[email protected]>Re: A bigger message thread
|     |-treeid: 3
|     \-0
|       |-parent: 3
|       |-id: 39
|       |-message: Friend Purple Acc2 <[email protected]>:Re: A bigger message thread
|       |-treeid: 4
|       \-0
|         |-parent: 4
|         |-id: 40
|         |-message: Friend Pink <[email protected]>:Re: A bigger message thread
|         |-treeid: 5
|         \-0
|           |-parent: 5
|           |-id: 38
|           |-message: Friend Yellow <[email protected]>:Re: A bigger message thread
|           |-treeid: 6
|           \-0
|             |-parent: 6
|             |-id: 12
|             |-message: Friend Pink <[email protected]>:Re: A bigger message thread
|             |-treeid: 7
|             \-0
|               |-parent: 7
|               |-id: 25
|               |-message: Friend White <[email protected]>:Re: A bigger message thread
|               |-treeid: 8
|               \-0
|                 |-parent: 8
|                 |-id: 19
|                 |-message: Friend Black <[email protected]>:Re: A bigger message thread
|                 |-treeid: 9
|                 \-0
|                   |-parent: 9
|                   |-id: 23
|                   |-message: Friend Black <[email protected]>:Re: A bigger message thread
|                   |-treeid: 10
|                   \-0
|                     |-parent: 10
|                     |-id: 30
|                     |-message: Friend Yellow <[email protected]>:Re: A bigger message thread
|                     |-treeid: 11
|                     \-0
|                       |-parent: 11
|                       |-id: 2
|                       |-message: Friend Yellow <[email protected]>:Re: A bigger message thread
|                       |-treeid: 12
|                       |-0
|                       | |-parent: 12
|                       | |-id: 20
|                       | |-message: Me <[email protected]>:Re: A bigger message thread
|                       | |-treeid: 13
|                       | \-0
|                       |   |-parent: 13
|                       |   |-id: 1
|                       |   |-message: Fiend Silver <[email protected]>:Re: A bigger message thread
|                       |   |-treeid: 14
|                       |   \-0
|                       |     |-parent: 14
|                       |     |-id: 41
|                       |     |-message: Fiend Silver <[email protected]>:Re: A bigger message thread
|                       |     |-treeid: 15
|                       |     \-0
|                       |       |-parent: 15
|                       |       |-id: 27
|                       |       |-message: Friend Grey <[email protected]>Re: A bigger message thread
|                       |       |-treeid: 16
|                       |       \-0
|                       |         |-parent: 16
|                       |         |-id: 17
|                       |         |-message: Friend Magenta <[email protected]>:Re: A bigger message thread
|                       |         |-treeid: 17
|                       |         |-0
|                       |         | |-parent: 17
|                       |         | |-id: 31
|                       |         | |-message: Friend Purple <[email protected]>:Re: A bigger message thread
|                       |         | |-treeid: 18
|                       |         | \-0
|                       |         |   |-parent: 18
|                       |         |   |-id: 4
|                       |         |   |-message: Friend Black <[email protected]>:Re: A bigger message thread
|                       |         |   |-treeid: 19
|                       |         |   \-0
|                       |         |     |-parent: 19
|                       |         |     |-id: 37
|                       |         |     |-message: Friend Black <[email protected]>:Re: A bigger message thread
|                       |         |     |-treeid: 20
|                       |         |     \-0
|                       |         |       |-parent: 20
|                       |         |       |-id: 24
|                       |         |       |-message: Friend Purple Acc2 <[email protected]>:Re: A bigger message thread
|                       |         |       |-treeid: 21
|                       |         |       \-0
|                       |         |         |-parent: 21
|                       |         |         |-id: 13
|                       |         |         |-message: Friend White <[email protected]>:Re: A bigger message thread
|                       |         |         \-treeid: 22
|                       |         \-1
|                       |           |-parent: 17
|                       |           |-id: 15
|                       |           |-message: Friend Grey <[email protected]>Re: A bigger message thread
|                       |           |-treeid: 23
|                       |           \-0
|                       |             |-parent: 23
|                       |             |-id: 18
|                       |             |-message: Friend Magenta <[email protected]>:Re: A bigger message thread
|                       |             |-treeid: 24
|                       |             \-0
|                       |               |-parent: 24
|                       |               |-id: 45
|                       |               |-message: Friend Black <[email protected]>:Re: A bigger message thread
|                       |               \-treeid: 25
|                       \-1
|                         |-parent: 12
|                         |-id: 46
|                         |-message: Friend Yellow <[email protected]>:Re: A bigger message thread
|                         |-treeid: 26
|                         \-0
|                           |-parent: 26
|                           |-id: 29
|                           |-message: Fiend Silver <[email protected]>:Re: A bigger message thread
|                           |-treeid: 27
|                           \-0
|                             |-parent: 27
|                             |-id: 26
|                             |-message: Friend Magenta <[email protected]>:Re: A bigger message thread
|                             |-treeid: 28
|                             |-0
|                             | |-parent: 28
|                             | |-id: 34
|                             | |-message: Friend Grey <[email protected]>Re: A bigger message thread
|                             | \-treeid: 29
|                             |-1
|                             | |-parent: 28
|                             | |-id: 33
|                             | |-message: Friend Yellow <[email protected]>:Re: A bigger message thread
|                             | |-treeid: 30
|                             | \-0
|                             |   |-parent: 30
|                             |   |-id: 36
|                             |   |-message: Friend White <[email protected]>:Re: A bigger message thread
|                             |   |-treeid: 31
|                             |   |-0
|                             |   | |-parent: 31
|                             |   | |-id: 10
|                             |   | |-message: Friend White <[email protected]>:Re: A bigger message thread
|                             |   | \-treeid: 32
|                             |   \-1
|                             |     |-parent: 31
|                             |     |-id: 48
|                             |     |-message: Friend Pink <[email protected]>:Re: A bigger message thread
|                             |     \-treeid: 33
|                             \-2
|                               |-parent: 28
|                               |-id: 47
|                               |-message: Friend Purple <[email protected]>:Re: A bigger message thread
|                               |-treeid: 34
|                               \-0
|                                 |-parent: 34
|                                 |-id: 5
|                                 |-message: Friend White <[email protected]>:Re: A bigger message thread
|                                 |-treeid: 35
|                                 \-0
|                                   |-parent: 35
|                                   |-id: 3
|                                   |-message: Friend Purple <[email protected]>:Re: A bigger message thread
|                                   |-treeid: 36
|                                   \-0
|                                     |-parent: 36
|                                     |-id: 21
|                                     |-message: Friend Yellow <[email protected]>:Re: A bigger message thread
|                                     |-treeid: 37
|                                     \-0
|                                       |-parent: 37
|                                       |-id: 8
|                                       |-message: Friend Purple <[email protected]>:Re: A bigger message thread
|                                       |-treeid: 38
|                                       \-0
|                                         |-parent: 38
|                                         |-id: 43
|                                         |-message: Friend White <[email protected]>:Re: A bigger message thread
|                                         |-treeid: 39
|                                         \-0
|                                           |-parent: 39
|                                           |-id: 28
|                                           |-message: Friend Purple <[email protected]>:Re: A bigger message thread
|                                           |-treeid: 40
|                                           \-0
|                                             |-parent: 40
|                                             |-id: 42
|                                             |-message: Friend Brown <[email protected]>:Re: A bigger message thread
|                                             |-treeid: 41
|                                             \-0
|                                               |-parent: 41
|                                               |-id: 22
|                                               |-message: Friend Purple <[email protected]>:Re: A bigger message thread
|                                               \-treeid: 42
|-1
| |-parent: 0
| |-id: 9
| |-message: Friend Blue <[email protected]>:RE: A bigger message thread
| \-treeid: 43
|-2
| \-parent: 0
|-3
| |-parent: 44
| |-id: 49
| |-message: Some Subcription <[email protected]>:Newsletter #1
| \-treeid: 45
|-4
| |-parent: 44
| |-id: 50
| |-message: Some Subcription <[email protected]>:Newsletter #2
| \-treeid: 46
\-5
  |-parent: 0
  |-id: 32
  |-message: Friend Red <[email protected]>:A second mainthread
  |-treeid: 47
  \-0
    |-parent: 47
    |-id: 16
    |-message: Friend Black <[email protected]>:Re: A second mainthread
    |-treeid: 48
    \-0
      |-parent: 48
      |-id: 14
      |-message: Friend Red <[email protected]>:Re: A second mainthread
      |-treeid: 49
      \-0
        |-parent: 49
        |-id: 6
        |-message: Friend White <[email protected]>:Re: A second mainthread
        |-treeid: 50
        \-0
          |-parent: 50
          |-id: 44
          |-message: Fiend Silver <[email protected]>:Re: A second mainthread
          \-treeid: 51

Несколько примечательных моментов:

  • Первое воплощение этого скрипта неправильно добавило ветви к первому дочернему узлу вместо самого фактического узла, который теперь исправлен, также сохранив его родитель.
  • imap_thread не идеален: мы видим id=9 как сироту, хотя, кажется, это должно быть где-то в первом потоке. Однако из-за того, что в заголовках об этом не упоминается, Google Apps здесь решили сделать его своим собственным узлом.
  • 3-я запись (ключ=2) - это метод "возврата к корню", поскольку у метода N.num.N.branch,N.next, по-видимому, нет другого способа вернуться к корню. Это бит /return to root $nodes[$treeid] = &$nodes[0]; . Вы можете/должны отфильтровать это после определения всех остальных узлов, но вам это нужно для построения массива на первый.

Чтобы получить только узлы, запускающие новые потоки (N-й ответ на сообщение, N>1):

$threads = imap_thread($imap, SE_UID);
$branchestarts = array();
foreach($threads as $key => $value){
    list($num,$type) = explode('.',$key);
    if (
        $type=='num'                     // an id
        && $value == 0                   // which is actually root
        && isset($threads[$num.'.next']) // then check for next
        && isset($threads[$threads[$num.'.next'].'.num'])
    ){
        $branchestarts[] = $threads[$threads[$num.'.next'].'.num'];
    } else if(
        $type=='branch'                   // branch movement
        && $value != 0                    // not back
        && isset($threads[$value.'.num']) // sanity: target exists
        && $threads[$value.'.num'] != 0   // and is not a return to root
    ){
        $branchestarts[] = $threads[$value.'.num'];
    }
}
echo json_encode($branchestarts);

Что дает нам:

[35,15,46,33,48,47,9,49,50,32]

И действительно, 35,49,50 и 32 являются запусками потоков, 9 также распознаются как таковые сервером imap, а остальные являются 2-м или более ответами, начинающими свои собственные ветви.

Теперь вы могли бы действительно разделить ветви как отдельный разговор, но, как вы можете видеть, это часто всего на 1 или 2 ответа больше, более длинные потоки, как правило, развиваются немного реже. Чтобы увидеть, как идут эти "ветви":

$branches = array();
$currenttree = null;
foreach($threads as $key => $value){
    list($num,$type) = explode('.',$key);
    switch($type){
        case 'num':
            //nothing
            break;
        case 'next':
            if(is_null($currenttree)) $currenttree = &$branches[$threads[$value.'.num']];
            if($value && isset($threads[$value.'.num'])) $currenttree[] = $threads[$value.'.num'];
            break;
        case 'branch':
            unset($currenttree);
            if($value && $threads[$value.'.num']){
                $branches[$threads[$value.'.num']] = array($threads[$value.'.num']);
                $currenttree =& $branches[$threads[$value.'.num']];
            }
    }
}
echo json_encode($branches, JSON_PRETTY_PRINT);

Который дает вам корни и ветви и их ответы:

{
    "35": [
        35,
        7,
        11,
        39,
        40,
        38,
        12,
        25,
        19,
        23,
        30,
        2,
        20,
        1,
        41,
        27,
        17,
        31,
        4,
        37,
        24,
        13
    ],
    "15": [
        15,
        18,
        45
    ],
    "46": [
        46,
        29,
        26,
        34
    ],
    "33": [
        33,
        36,
        10
    ],
    "48": [
        48
    ],
    "47": [
        47,
        5,
        3,
        21,
        8,
        43,
        28,
        42,
        22
    ],
    "9": [
        9
    ],
    "49": [
        49
    ],
    "50": [
        50
    ],
    "32": [
        32,
        16,
        14,
        6,
        44
    ]
}

С некоторыми небольшими изменениями мы можем получить сообщения там:

$branches = array();
$currenttree = null;
$messages = array();
foreach($threads as $key => $value){
    list($num,$type) = explode('.',$key);
    switch($type){
        case 'num':
            //nothing
            break;
        case 'next':
            if(is_null($currenttree)) $currenttree = &$branches[$threads[$value.'.num']];
            if($value && isset($threads[$value.'.num'])) $currenttree[] = &$messages[$threads[$value.'.num']];
            break;
        case 'branch':
            unset($currenttree);
            if($value && $threads[$value.'.num']){
                $branches[$threads[$value.'.num']] = array(&$messages[$threads[$value.'.num']]);
                $currenttree =& $branches[$threads[$value.'.num']];
            } else {
                $currenttree = null;
            }
    }
}
$keystofetch = implode(',',array_filter(array_keys($messages)));
foreach(imap_fetch_overview($imap,$keystofetch,FT_UID) as $message){
        $messages[$message->uid] = $message;
}
echo json_encode($branches);//won't show it's output, this answer is to large as it is ;)

Другой вариант - просто отсортировать их по значению даты и времени, что было бы хорошо для разговоров с небольшим/незначительным ветвлением, вероятно, заставляя большую часть кода, который вы планируете, просто работать.

Сочетание этих двух будет "движущимися ветвями", следуйте потоки последовательно, так что это:

 1       2013-06-01
   2     2013-06-02
     3   2013-06-03
   4     2013-06-03
     5   2013-06-04

Становится последовательностью 1,2,3,4,5, но ответ на 3 будет использовать его:

 1       2013-06-01
   4     2013-06-03
     5   2013-06-04
   2     2013-06-02
     3   2013-06-03
       6 2013-06-05

Превращая его в последовательность 1,4,5,2,3,6, которая сохраняла бы логически протекающий разговор, всегда с потоком/ветвью с последним ответом в качестве последнего.

 0
Author: Wrikken, 2013-07-15 20:50:30