英文:
How to fix my PHP Code which return me "Invalid input" when I modify "input" variable value?
问题
这里是我的USSD个人代码:
<?php
class UssdNode {
// ...(略)
}
class MyTree {
// ...(略)
}
class MyUssdUserSession {
// ...(略)
}
// 开始USSD会话
session_start();
// 创建USSD树
$ussdTree = new MyTree();
// 获取用户的地址(手机号码)
$address = $_POST['address'] ?? '';
// 创建或检索用户会话
$userSessions = $_SESSION['userSessions'] ?? [];
$userSession = $userSessions[$address] ?? null;
if ($userSession === null) {
$userSession = new MyUssdUserSession($address, $ussdTree);
$userSessions[$address] = $userSession;
$_SESSION['userSessions'] = $userSessions;
}
// 获取来自请求的USSD输入
$input = $_POST['ussdInput'] ?? '';
// 处理USSD输入并获取响应
$response = $userSession->processUssdInput($input);
// 将响应发送回USSD网关
header('Content-type: text/plain');
echo $response;
英文:
Here my USSD Personnal Code:
<?php
class UssdNode {
private $name = '';
private $parent = '';
private $title = '';
private $address = '';
private $children = array();
private $index = 0;
function __construct($title, $name, $parent) {
$this->name = $name;
$this->parent = $parent;
$this->title = $title;
}
function addChildNode(UssdNode $childNode) {
$this->children[] = $childNode;
}
function setIndex($index) {
$this->index = $index;
}
function hasChildren() {
return count($this->children) > 0;
}
function setAddress($address) {
$this->address = $address;
}
function getName() {
return $this->name;
}
function getParent() {
return $this->parent;
}
function getAddress() {
return $this->address;
}
function getTitle() {
return $this->title;
}
function getChildren() {
return $this->children;
}
function getNameFromIndex($index) {
return $this->children[$index - 1]->getName();
}
function toString() {
$objectString = '';
$items = $this->children;
$bufferLimit = (count($items) == 0) ? 1 : $this->getBufferLimit() + 1;
do {
$bufferLimit -= 1;
$objectString = $this->recurseMenu($items, $bufferLimit);
} while (strlen($objectString) > 160);
$this->index = $bufferLimit;
return $objectString;
}
function getBufferLimit() {
$len = count($this->children);
$margin = $len - $this->index;
if ($margin < 5)
return $this->index + $margin;
else
return $this->index + 5;
}
function recurseMenu($items, $bufferLimit) {
$objectString = $this->getTitle() . PHP_EOL;
$lastMenu = false;
if (count($items) > 0) {
for ($i = $this->index; $i < $bufferLimit; $i++) {
$item = $items[$i];
$num = $i + 1;
// get node by name
$userSessions = $_SESSION['userSessions'];
$currUserSession = $userSessions[$this->address];
$node = $currUserSession->getNode($item->getName());
$title = $node->getTitle();
$objectString = $objectString . PHP_EOL . $num . '. ' . $title;
}
} else {
$objectString = $objectString . PHP_EOL . 'NO DATA AVAILABLE, TRY AGAIN LATER';
}
$lastMenu = $bufferLimit == count($items);
$objectString = $objectString . PHP_EOL . PHP_EOL . '0. Exit';
if ($this->getParent() != '0') {
$objectString = $objectString . PHP_EOL . '#. Back';
}
if ($lastMenu === false) {
$rem = count($items) - $this->index;
$objectString = $objectString . PHP_EOL . '77. Next (' . $rem . ')';
}
return $objectString;
}
}
class MyTree {
private $rootNode;
function __construct() {
$this->initTree();
}
function initTree() {
$rootNode = new UssdNode('Welcome to Cheggen USSD Menu', 'root', '0');
$childNode1 = new UssdNode('Option 1', 'option1', 'root');
$childNode1->addChildNode(new UssdNode('Sub-option 1', 'suboption1', 'option1'));
$childNode1->addChildNode(new UssdNode('Sub-option 2', 'suboption2', 'option1'));
$childNode2 = new UssdNode('Option 2', 'option2', 'root');
$childNode2->addChildNode(new UssdNode('Sub-option 3', 'suboption3', 'option2'));
$childNode2->addChildNode(new UssdNode('Sub-option 4', 'suboption4', 'option2'));
$rootNode->addChildNode($childNode1);
$rootNode->addChildNode($childNode2);
$this->rootNode = $rootNode;
}
function getRootNode() {
return $this->rootNode;
}
}
class MyUssdUserSession {
private $ussdTree;
private $currentNode;
private $address;
function __construct($address, $ussdTree) {
$this->address = $address;
$this->ussdTree = $ussdTree;
$this->currentNode = $ussdTree->getRootNode();
}
function getNode($name) {
$children = $this->currentNode->getChildren();
foreach ($children as $child) {
if ($child->getName() === $name) {
return $child;
}
}
return null;
}
function processUssdInput($input) {
if ($input === '') {
// Initial menu
return $this->currentNode->toString();
} elseif ($input === '0') {
// Exit
return 'Thanks, end of session';
} elseif ($input === '#') {
// Back
$parentName = $this->currentNode->getParent();
$parentNode = $this->getNode($parentName);
if ($parentNode !== null) {
$this->currentNode = $parentNode;
return $this->currentNode->toString();
} else {
return 'Invalid input';
}
} elseif ($input === '77') {
// Next
$index = $this->currentNode->getIndex() + 5;
$this->currentNode->setIndex($index);
return $this->currentNode->toString();
} else {
// Check if the input matches any child node
$childNode = $this->getNode($input);
if ($childNode !== null) {
$this->currentNode = $childNode;
return $this->currentNode->toString();
} else {
return 'Invalid input';
}
}
}
}
// Start the USSD session
session_start();
// Create the USSD tree
$ussdTree = new MyTree();
// Get the user's address (phone number)
$address = $_POST['address'] ?? '';
// Create or retrieve the user session
$userSessions = $_SESSION['userSessions'] ?? [];
$userSession = $userSessions[$address] ?? null;
if ($userSession === null) {
$userSession = new MyUssdUserSession($address, $ussdTree);
$userSessions[$address] = $userSession;
$_SESSION['userSessions'] = $userSessions;
}
// Get the USSD input from the request
$input = $_POST['ussdInput'] ?? '';
// Process the USSD input and get the response
$response = $userSession->processUssdInput($input);
// Send the response back to the USSD gateway
header('Content-type: text/plain');
echo $response;
The problem is when I try to start the first session (notice session_start
at Line 194), USSD App is running well. But when I try to change in Line 212, $input = $_POST['ussdInput'] ?? '';
to $input = '1';
or to $input = 1;
to access Sub-Menu of Option 1, I get This foolowing error: Invalid input.
Note that this $input
variable is used to retrieve the value entered in the simulator by the user. And If, I put or give it 1
as value, normally it should return me the Sub-option 1
of the Option 1
as defined on my initTree()
function from Line 115 to 130.
So How to fix my Code to browse (navigate) through Menus (Options) and their Sub-Menus (Sub-option) without getting Invalid input error ???
Thanks.
答案1
得分: 0
错误在于您将索引传递给一个按名称搜索节点的函数,而不是名称。如果我在您的代码中添加一些调试信息,例如
function getNode($name) {
$children = $this->currentNode->getChildren();
foreach ($children as $child) {
echo var_dump([$child->getName(), $name]);
if ($child->getName() === $name) {
return $child;
}
}
return null;
}
然后我可以看到循环正在检查匹配项:
如果您尝试将 'option1'
分配给 $input
,那么它将起作用。如果您希望通过索引来搜索节点,那么您需要实现一个能够执行此操作的方法。
编辑
您可以更改 getNode
以检查输入的类型并根据情况返回索引或名称:
function getNode($input) {
$children = $this->currentNode->getChildren();
foreach ($children as $index => $child) {
if ((is_int($input) ? $index : $child->getName()) == $input) {
return $child;
}
}
return null;
}
我已经删除了测试文件,所以上面的编辑未经测试,让我知道是否有效。
英文:
The mistake is that you pass the index rather than the name to a function that searches the nodes by name. If I add some debugging to your code, such as
function getNode($name) {
$children = $this->currentNode->getChildren();
foreach ($children as $child) {
echo var_dump([$child->getName(), $name]);
if ($child->getName() === $name) {
return $child;
}
}
return null;
}
then I see what the loop was checking for a match:
If you try assigning 'option1'
to $input
, then it works. If you want your node to be searched for by index, then you will need to implement a method that does that.
EDIT
You can change getNode
to check for the type of the input and return the index if it's integer and name otherwise:
function getNode($input) {
$children = $this->currentNode->getChildren();
foreach ($children as $index => $child) {
if ((is_int($input) ? $index : $child->getName()) == $input) {
return $child;
}
}
return null;
}
I already removed the test file, so the edit above is untested, let me know whether it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论