PHP - 如何让一个函数等待并且 return 另一个函数值

PHP - How do I make a function wait and return another functions value

所以我有一些 XML 我需要遍历 children 来找到 childs 值。问题是实际的循环。我知道的方法是制作一个函数,如果有 child,使用相同的函数并循环遍历 children - 如此循环第四次。

我的问题是函数似乎没有在等待 "child function" 完成后返回我的值。

有更好的方法吗?我知道有回调,但我不确定如何在这里实现它

例子XML

<?xml version="1.0" standalone="yes"?>
<pages>
    <page>
        <title>Parent Page1</title>
        <id>0</id>
        <children>
            <page>
                <title>Child Page1</title>
                <id>1</id>
                <children/>
            </page>
        </children>
    </page>
    <page>
        <title>Parent Page2</title>
        <id>2</id>
        <children>
            <page>
                <title>Child Page2</title>
                <id>3</id>
                <children/>
            </page>
        </children>
    </page>
</pages>

例子PHP

$page = "Child Page2";
echo "The ID of " . $page . " is " . a($page);

function a ($title) {
    $xml = simplexml_load_file("pages.xml") or die("Failed.");
    return b ($xml[0], $title);
}

function b ($pages, $title) {
    $val;
    foreach ($pages as $page) {
        if($page->title == $title) {
            $val = $page->id;
            break;
        } else if ($page->children->children() > 0){
            $val = b($page->children->children(), $title);
        }
    }
    return $val;
}

正在输出:The ID of Child Page2 is

现在我知道 XML 在这个例子中并不完美,但它只是一个占位符,所以你明白我想做什么。我在 XML 上使用 SimpleXML 如果有任何帮助的话

解决方案

问题是,如果 b(); 在第一个分支返回,但仍需要检查 children 的其他分支,则整个返回 null 或者根本没有返回.

我下面的解决方案可行,但采用了 Swayze 的答案,因为它更短且更有效(保存保存变量)

试试这个:

<?php

$page = "Child Page";
echo "The ID of " . $page . " is " . a($page);

function a($title) {
    $pages = [
        [
            'title'    => 'Parent Page',
            'id'       => 0,
            'children' => [
                [
                    'title'    => 'Child Page',
                    'id'       => 1,
                    'children' => []
                ]
            ]
        ]
    ];
    return b($pages, $title);
}

function b($pages, $title) {
    foreach ($pages as $page) {
        if ($page['title'] == $title) {
            $val = $page['id'];
        } else if (count($page['children']) > 0) {
            $val = b($page['children'], $title);
        }
    }
    return $val;
}

如果不需要,我不会在这里使用 XML。这是一个使用数组的粗略示例,但它适用于您要执行的操作。如果这对你有用,请告诉我。如果你喜欢对象表示法,你可以把数组变成一个对象,或者使用 类 (首选)。

我认为您可以仅使用 xPath 来简化工作:

function b( $xml, $title )
{
    $val = Null;
    $pattern = '//page/title[text()="'.$title.'"]/..';
    if( $found = $xml->xpath( $pattern ) ) $val = $found[0]->id;
    return $val;
}

你也可以修改它最终有多个相同的标题:

function b( $xml, $title )
{
    $val = array();
    $pattern = '//page/title[text()="'.$title.'"]/..';
    foreach( $xml->xpath( $pattern ) as $node )
    {
        $val[] = $found[0]->id;
    }
    return $val;
}

xPath 模式说明:

//                      Search following pattern no matter where it is
page/title              <page> with child <title> with
[text()="'.$title.'"]   node value = $text
/..                     select parent node

终于找到问题了。问题是因为我有很多分支(许多 parents 和 children),一旦我的循环通过第一个分支但什么也没找到,它 returned null 到也 returned null 回到开始的函数。

我可以通过添加一个简单的 if ($received != null) 来解决这个问题

function b ($pages, $title) {
    $val;
    foreach ($pages as $page) {
        if($page->title == $title) {
            $val = $page->id;
            break;
        } else if ($page->children->children() > 0){
            $received = b($page->children->children(), $title);
            if ($received != null) { // Important
                $val = $received;
            }
        }
    }
    return $val;
}

在我发表评论的地方,你可以看到最后的 return 被迫等待 foreach 的其余部分,而不是只使用它收到的第一个 null

function b ($pages, $title){
    foreach ($pages as $page){
        if($page->title == $title){
            // returns id regardless of how many loops in you are 
            return $page->id;}
        else if ($page->children->children() > 0){
            // call function if it has children
            return b ($page->children->children(), $title);}}
    // if nothing is found
    return 'no results';}

如果每个标题只能有一个实例,这是最简单的方法..

如果我误解了你,并且每次搜索可能会有多个结果,那么此方法只会 return 它找到的第一个匹配项的 ID。