This question already has answers here:
Run php script as daemon process
(15 answers)
Closed last month.
Am writing a simple telegram bot in php using getUpdates method for receiving messages from bot.
So after executing php bot.php in terminal, it works and reply only once then the script auto exit.
bot.php
<?php
for ($i= 0; $i >0; $i++) {
/**
* Telegram Bot whitout WebHook.
* It uses getUpdates Telegram's API
*/
include 'Telegram.php'; //am using a php telegram bot Library
$bot_token = 'xyz';
$telegram = new Telegram($bot_token);
// Get all the new updates and set the new correct update_id
$req = $telegram->getUpdates();
for ($i = 0; $i < $telegram->UpdateCount(); $i++) {
// You NEED to call serveUpdate before accessing the values of message in Telegram Class
$telegram->serveUpdate($i);
$text = $telegram->Text();
$chat_id = $telegram->ChatID();
if ($text == '/start') {
$reply = 'Working';
$content = ['chat_id' => $chat_id, 'text' => $reply];
$telegram->sendMessage($content);
}
if ($text == '/test') {
if ($telegram->messageFromGroup()) {
$reply = 'Chat Group';
} else {
$reply = 'Private Chat';
}
if ($text == '/git') {
$reply = 'Check me on GitHub: https://github.com/Eleirbag89/TelegramBotPHP';
// Build the reply array
$content = ['chat_id' => $chat_id, 'text' => $reply];
$telegram->sendMessage($content);
}
}
}
I tried setting set_time_limit(0) but it doesn't works, then I wrapped the entire code in a for loop. But it still exit after running once.
I want the script to remain running and reply all incoming messages, untill I exit script myself or exit terminal)
You have a few issues here.
First, this outer loop will never do anything, because you set $i to zero and then run the loop only while $i is greater than zero... which it never is:
for ($i= 0; $i >0; $i++) {
Then you use the same variable for another loop inside that outer loop:
for ($i= 0; $i >0; $i++) {
for ($i = 0; $i < $telegram->UpdateCount(); $i++) {
So you've got $i trying to do two different things at once. If you're using nested loops, you want to use a different variable for each loop:
for ($i = 0; $i < 100; $i++) {
for ($j = 0; $j < 100; $j++) {
If you want to wrap your whole script in a never-ending loop, you can do that most simply with:
while (true) {
// your code here
}
There's no need to run the import each time, so I would put this wrapper just before the getUpdates() call:
while (true) {
$req = $telegram->getUpdates();
for ($i = 0; $i < $telegram->UpdateCount(); $i++) {
// ...
}
}
Note this means your script will never exit. You'll have to hit control-c or kill its process. If you want the script to exit on some trigger, you can just break at the end of the loop:
while (true) {
$req = $telegram->getUpdates();
for ($i = 0; $i < $telegram->UpdateCount(); $i++) {
// ...
}
if ($someCondition) {
break;
}
}
Related
Below is the code i tried, where count is showing improper.
Please help me to get where i am missing the logic.
I am attaching the code which i have tried so far.
PS Note:- I am not intended to use more built in function of php and so I created function for string length.
error_reporting(E_ALL);
$string = "ssddk";
function checkString($addinString, &$stringBK) {
if (empty(count($stringBK))) {
$stringBK[] = $addinString;
return false;
}
foreach ($stringBK as $key => $val) {
if ($addinString == $val) {
return true;
}
}
$stringBK[] = $addinString;
return false;
}
for ($i = 0; $i < checkstrlength($string); $i++) {
$count = 0;
for ($j = 0; $j < checkstrlength($string); $j++) {
if ($string[$i] == $string[$j]) {
if (checkString($string[$i], $stringBK)) {
continue 2;
}
$count++;
echo "Column => " . $string[$j] . " for count" .$count . "<br>";
}
}
}
function checkstrlength($string) {
$count = 0;
for ($i = 0; $string[$i] != ""; $i++) {
$count++;
}
return $count;
}
It gives below output ,
Column => s for count1
Column => d for count1
Column => k for count1
I am expecting it as ,
Column => s for count 2
Column => d for count 2
Column => k for count 1
Ok, there a couple of things to look at here.
The checkstrlength() has the below loop.
for ($i = 0; $string[$i] != ""; $i++) {
Formally speaking, we usually look at \0 terminating character in the string to terminate our loop. But in PHP, everything is a string. So, \0 is now a string to match on rather than a character match. Better, we do an isset check to stop our loop. So, code would look like:
for ($i = 0; isset($string[$i]); $i++) {
Second is your not caching the result which you got from checkstrlength(). Do it. Also, you can start the inner loop from $i itself. There is no need to go from start again. So, for loop would look like:
$length = checkstrlength($string);
for ($i = 0; $i < $length; $i++) {
for ($j = $i; $j < $length; $j++) {
Third is that there is no need of empty and count checks in checkString. This also reduces inbuilt function calls. You can simply loop over and return true if found. If not found, we are adding it anyway. So it would look like:
function checkString($addinString, &$stringBK) {
foreach ($stringBK as $key => $val) {
if ($addinString == $val) {
return true;
}
}
$stringBK[] = $addinString;
return false;
}
Now, in your nested loop, you add it to $stringBK outside of the inner loop, because there is no point in checking with the inner loop when chars match. This is because if some character was visited, why initialize the inner loop at all. Just have a check above and continue the search and count. Also note that you are having echo statements inside the inner loop which doesn't make sense because we haven't finished the count yet. Let's do and print it outside of the inner loop at the end. Snippet as follows:
for ($i = 0; $i < $length; $i++) {
$count = 0;
if (checkString($string[$i], $stringBK)) {
continue;
}
for ($j = $i; $j < $length; $j++) {
if ($string[$i] == $string[$j]) {
$count++;
}
}
echo "Column => " . $string[$i] . " for count : " .$count,PHP_EOL;
}
Final Code Demo: https://3v4l.org/4dpST
I want to update my MySQL table. When I type the ID as a number works, but when using a variable instead, it does not work.
What I am trying to do is order elements of an html table by column.
I have e.g. 4 Columns:
$colname = array("Column1", "Column2", "Column3", "Column4");
I get the IDs of the elements already sorted from the URL variable:
$strTaskIds = $_GET["taskIds"];
// for example: $strTaskIds = "3;1;32_4;5_6;36_34;7"
Now I split the string into a 2D-Array and update the MySQL table:
$arrTaskIds = explode("_", $strTaskIds);
for($i = 0; $i < count($arrTaskIds); $i++) {
$arrIdsPerCol = explode(";", $arrTaskIds[$i]);
for($j = 0; $j < count($arrIdsPerCol); $j++) {
$sql = "UPDATE tasks SET col='$colname[$i]', rank=$j WHERE id=$arrIdsPerCol[$j]";
}
if($conW->query($sql) === TRUE) {
$error = 0;
} else {
$error = 1;
}
}
When I write a number E.G 7 instead of the variable $arrIdsPerCol[$j] it works.
Writing (int)$arrIdsPerCol[$j] does not work either.
The reason i gave you no error message is that there was none. It just looked like the MySQL table is not updating.
After starring at my code for quite a long time a found the problem.
I placed the query() code in the outer loop. But i needed it in the inner loop.
Problem solved:
$arrTaskIds = explode("_", $strTaskIds);
$error = 0;
for($i = 0; $i < count($arrTaskIds); $i++) {
$arrIdsPerCol = explode(";", $arrTaskIds[$i]);
for($j = 0; $j < count($arrIdsPerCol); $j++) {
$sql = "UPDATE tasks SET col='$colname[$i]', rank=$j WHERE id=$arrIdsPerCol[$j]";
if($conW->query($sql) === TRUE) {
} else {
$error = 1;
}
}
}
I need to add * in an array. This is how i do it in javaScript.
function makeStarString(grade) {
var starArray = [];
var starString = "";
for (var i = 0; i < grade; i++){
starArray[i] = "*";
starString = starString.concat(starArray[i]);
}
return starString;
}
The javascript version works fine but I cant make it work with php.
This is as far as i got with php.
function makeStarString($varGrade) {
$starArray = array ();
$starString = "";
for ($i = 0; $i < strlen($varGrade); $i++){
$starArray($i) = $star;
$starString = $starString.(starArray(i));
}
return $starString;
}
I get this error "Fatal error: Can't use function return value in write context" because of line $starArray($i) = $star;
The argument I send to the function is an Integer.
So the purpose of the function is that if i send a 5 to the function it will return *****
How can i fix my php function?
Use $starArray[$i] instead of $starArray($i) and starArray(i).
If you really need stars in an array, you don't need to use a loop:
$starArray = array_fill(0, $varGrade, '*');
and if you need to turn the array into a string:
$starString = implode('', $starArray);
But if you don't really ever need to use the array of stars, it would be easier to just use str_repeat:
str_repeat('*', $varGrade);
It would generally be a great idea to use strlen($varGrade) in a variable, because the foreach loop will have to count the length every iteration. This might bring performance issues.
Your $star variable is not defined, so I have no idea what you're trying to put there. Revise your own code.
Finally, you may use the .= operator to add something to existing string.
function makeStarString($varGrade) {
$starArray = array ();
$starString = "";
$length = strlen($varGrade);
for ($i = 0; $i < $length; $i++){
$starArray[$i] = $star;
$starString .= $starArray[$i];
// equivalent to $starString = $starString . $starArray[$];
}
return $starString;
}
UPDATE
If you send an int to the function, you don't need strlen:
function makeStarString($varGrade) {
$starArray = array ();
$starString = "";
for ($i = 0; $i < $varGrade; $i++){
$starArray[$i] = $star;
$starString .= $starArray[$i];
// equivalent to $starString = $starString . $starArray[$];
}
return $starString;
}
This code should work
function makeStarString($varGrade) {
$star = "*"; // star variable wasn't defined to.
$starArray = array ();
$starString = "";
for ($i = 0; $i < $varGrade; $i++){
$starArray[$i] = $star; // [ ] instead of ( )
$starString .= ($starArray[$i]); // $a.=$b instead of $a=$a+$b, added the $ at the i and [ ] instead of ( )
}
return $starString;
}
Is this what you need?
function makeStarString($varGrade) {
$starString = '';
for ($i = 0; $i < $varGrade; $i++) {
$starString .= '*';
}
return $starString;
}
A few notes on my modifications.
I don't see why you need that $starArray array in the first place. So I skipped it.
I revised your indentation. Strange indentation can make very simple code seem much more complicated than it really is. :)
You should ask if $i < $varGrade, not if $i < strlen($varGrade). If you ask by strlen(), then you get the width of the number you enter. For example, strlen(55) is 2, strlen(555) is 3, strlen(5555) is 4 etc. - ignoring the fact that it's a number. You just want the for-loop to give you $varGrade many stars so there is no need for strlen().
As a detail, I've put used single-quotes instead of double-quotes for strings because they're lighter (PHP doesn't parse variables inside them).
I hope it helps.
I have the following code:
for ($i = 1; $i <= $j; $i++)
{
$goods_{$i} = array(
$_POST["'goods'.$i'_title'"],
$_POST["'goods'.$i.'_package'"],
$_POST["'goods'.$i.'_nmr'"]
);
}
I hoped that it could make this in first step of the cycle:
$i =1;
$goods_1 = array(
$_POST['goods1_title'],
$_POST['goods1_package'],
$_POST['goods1_nmr']
);
and so on in other steps.
I follow AbraCadaver's sentiments:
Why in the world are you doing this? You are using arrays, keep using them.
As such, I would write the code simply using an Array:
$goods = array();
for ($i = 1; $i <= $j; $i++)
{
// Assign to an index in the already created array,
// but DO NOT create a new variable.
$goods[$i] = array(
// Also make sure these are correct ..
$_POST["goods{$i}_title"],
);
}
If you really want to create dynamic variables - ick! - see variable variables.
Should be
$_POST["goods{$i}_title"],
$_POST["goods{$i}_package"],
$_POST["goods{$i}_nmr"]
It can be done like this:
for ($i = 1; $i <= $j; $i++)
{
${"goods_$i"} = array(
$_POST["'goods'.$i'_title'"],
$_POST["'goods'.$i.'_package'"],
$_POST["'goods'.$i.'_nmr'"]
);
}
You can read more about this topic in related PHP documentation.
The result of "'goods'.$i'_title'" will be 'goods'.1'_title', in case that you want it to be goods1_title then use following code instead:
for ($i = 1; $i <= $j; $i++)
{
${"goods_$i"} = array(
$_POST["goods{$i}_title"],
$_POST["goods{$i}_package"],
$_POST["goods{$i}_nmr"]
);
}
Another bug might be that in 1 case you use .$i. and in other 2 cases you use .$i without the last ..
what I want to do is run this for loop and within there is a foreach searching the positions. what I want to do is once there it returns false I want it to break and save the position of $i in a variable. I'm using simple_html_dom.php but I don't think that matters since this is more of a basic programming problem.
for($i = $0; $i < $20; $i++){
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
break;
}
}
//this is not valid, but essentialy this is what I want to do.
$stop = $i;
}
To break multiple levels in a loop you simply specify the levels, eg, break 2 - see the manual on break - http://www.php.net/manual/en/control-structures.break.php.
As such your code might work as
for($i = $0; $i < $20; $i++){
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
$stop = $i; // Set variable
break 2; // break both loops
// or alternatively force the outer loop condition to expire
//$i = 21; // Force the outer loop to exit
//break;
}
}
}
I have expanded to question to set $i = 21 to break the outer loop with a single break.
Untested code but syntax checked...
<?php
// Untested code...
// Assume that you WILL break out of the loops...
$currentForIdx = -1; // so we can test that 'for' loop actually ran
$quitLoops = false;
for($i = 0; $i < $20 && !quitLoops; $i++) {
$currentForIdx = $i; // in case we break out of the loops
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false) {
$quitLoops = true;
break;
}
}
}
// test $quitLoops and $currentForIdx to work out what happened...
?>
I havent tested this, but I would try something like this:
for($i = $0; $i < $20; $i++){
$stop = false;
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
$stop = $i;
}
}
if ($stop !== false) {break;}
}