PHP: class function works in one file but not another - php

I am making a Telegram Bot using PHP. I have bot.php, filter.php and test.php.
I want my bot to send a message to the user that includes an ID.
I have a Filter class and I have a function in my filter.php with a regex pattern to detect this id and I'm using preg_match to obtain the match.
public function getID($string) {
$pattern = "/e0(\d){6}\b/i";
preg_match($pattern, $string, $matches);
return $matches[0];
}
In my test.php, I use that function and it was able to echo the match to me.
<?php
include __DIR__ . './filter.php';
$check = new Filter();
$pattern = "/e0(\d){6}\b/i";
$text = "hi e0000000";
echo "id: ".$check->getID($text);
?>
In my bot.php, I try to use the same function to send a message, but it doesn't work. (the sendMsg function is just a simple curl http request to the Telegram Bot API)
include __DIR__ . './filter.php';
$filter = new Filter();
function handleGoodMessage($chatId, $text) {
$report = "Message '".$text."' passed the filters.\nID: ".$filter->getID($text);
sendMsg($chatId, $report);
}
Instead, whenever the function is called the bot returns a 500 Internal Server Error.
Please help.

$filter is not accessible inside the function.
$filter = new Filter(); //<--- filter is here, in the outer scope
function handleGoodMessage($chatId, $text) {
$report = "Message '".$text."' passed the filters.\nID: ".$filter->getID($text);
//this scope is inside the function, $filter does not exist here
sendMsg($chatId, $report);
}
This works in test as you do not change the scope. You need to pass $filter in
------UPDATE----
personally I would always rely on injection rather than using globals so my preference would be to redefine the function like this:
function handleGoodMessage($chatId, $text, $filter) {
$report = "Message '".$text."' passed the filters.\nID: ".$filter->getID($text);
sendMsg($chatId, $report);
}
I would probably (at the risk of upsetting some people) have getID defined as a static function because it's not really interacting anything, not using any member variables and is just processing a string and returning it. So then instead of injecting it, or using global you could say
function handleGoodMessage($chatId, $text) {
$report = "Message '".$text."' passed the filters.\nID: ".Filter::getID($text);
sendMsg($chatId, $report);
}

Related

Remove parameters from Symfony 4.4 HttpFoundation\Request and re-generate URL

I need to re-generate the URL of my page, removing the additional parameters. For example: when I receive:
/bao1/bao2/?removeMe1=anything&keepMe1=anything&removeMe2=&keepMe2=anything
I want to generate the URL with removeMe query var removed, but with everything else intact. Like this:
/bao1/bao2/?keepMe1=anything&keepMe2=anything
I autowired the request:
public function __construct(RequestStack $httpRequest)
{
$this->httpRequest = $httpRequest;
}
Then I'm playing around like this:
public function getCleanUrl()
{
// HttpFoundation\Request
$currentHttpRequest = $this->httpRequest->getCurrentRequest();
// Trying to remove the parameters
$currentHttpRequest->query->remove("removeMe1");
return $currentHttpRequest->getUri()
}
The query->remove("removeMe1") works, but when I invoke getUri() I still get the full input url, as if remove() was never invoked. I think I'm probably missing to call some kind of $currentHttpRequest->regenerate()->getUri() but I cannot find anything.
To get the modified URL after calling mutator methods on a Request object, you need to call overrideGlobals().
If not, Request methods will give you results accordin to the original superglobals ($_GET, $_POST, $_SERVER). By calling Request::overrideGlobals() you tell the object not to.
E.g.:
if ($request->query->has('amp') && Request::METHOD_GET === $request->getMethod()) {
$request->query->remove('amp');
$request->overrideGlobals();
return new RedirectResponse($request->getUri(), Response::HTTP_MOVED_PERMANENTLY));
}
Or maybe, something more adjusted to your use case (untested, but the general idea should hold):
$queryParams = array_keys($request->query->all());
$goodParams = ['foo', 'bar', 'baz'];
$badParams = array_diff($queryParams, $goodParams);
foreach ($badParams as $badParam) {
$request->query->remove($badParam);
}
$request->overrideGlobals();
// get modified URL
echo $request->getUri();
I had to make this work, so I devised a non-Symfony solution:
$currentHttpRequest = $this->httpRequest->getCurrentRequest();
$arrParams = $currentHttpRequest->query->all();
$arrParams = array_intersect_key($arrParams, array_flip([
"keepMe1", "keepMe2"
]));
$currentUrlNoQs = strtok($currentHttpRequest->getUri(), '?');
if( empty($arrParams) ) {
$canonical = $currentUrlNoQs;
} else {
$queryString = http_build_query($arrParams);
$canonical = $currentUrlNoQs . '?' . $queryString;
}
return $canonical;
I'm not too fond of it, but it got the job done.

Upgrading from create_function to closures

Struggling to understand closures for a couple of days. Can anybody point me in the right direction? Need to re-write this "create_function" as a lambda.
$section = preg_replace_callback('/{listing_field_([^{}]*?)_caption}/', create_function('$matches', 'global $config,$or_replace_listing_id,$lang;require_once($config[\'basepath\'].\'/include/listing.inc.php\'); return listing_pages::renderSingleListingItem($or_replace_listing_id, $matches[1],\'caption\');'), $section);
You define a closure like so:
$myClosure = function ($args) {
// do something;
};
create_function takes two arguments - the first is an eval'd string of the callable's arguments, the second is the code to execute - so you'd do something like this:
$section = preg_replace_callback(
// Your regex search pattern
'/{listing_field_([^{}]*?)_caption}/',
// Your callback
function ($matches) use ($config, $or_replace_listing_id) {
require_once $config['basepath'] . '/include/listing.inc.php';
return listing_pages::renderSingleListingItem(
$or_replace_listing_id,
$matches[1],
'caption'
);
},
// Your subject
$section
);
Note that I've replaced your global variable calls with importing them via use into the callback instead, and removed $lang because you aren't using it.

PHP Functions returning an array

I am having some issues with my function which returns an array, I decided to try and use an OO approach to my php code and try to make a class with a few static functions since I decided I don't want to access it using an object. In my code, within the same class, I decided to make the following function:
public static function decideCategory($tweets) {
$tweet = $tweets;
if(in_array($tweet, self::$food)) {
echo "\nOur " . $tweet . " is under food\n";
} //if statements of the same nature below as well.
}
Now, this function works in the sense that it does not throw an error where $food is definded as an array at the top. However, originally I simply had $food defined at the top as just a private static variable, and then I had the following function which I passed into the in_array.
public static function getFood()
{
self::$food = array("Wendys", "McDonalds", "Wendy's", "Chic Fil A", "Chic-Fil-a", "Burger", "TGI", "BBQ", "Grilling", "Wine", "Tasty", "Yum", "IHOP", "Pancakes", "Pizza", "Cake"
,"Baking");
return self::$food;
}
However, it would return an error saying that in_array expects an array value for its second argument, but that instead it sees that a null was passed instead. Why is that and how can I use methods to do my comparison rather than the variables themselvs. If this were Java this would be how I would do it, and as such I cannot see why php would have these issues as it appears to follow a similar logic with returns.
Yes it would error because until you call self::getFood() Self::$food is null if you have declared it as
static $food;
update your method as below
public static function decideCategory($tweets)
{
$tweet = $tweets;
$food = self::getFood();
if(in_array($tweet, $food)) {
echo "\nOur " . $tweet . " is under food\n";
} //if statements of the same nature below as well.
}

Create a require() alias function

I have a class with this function:
public function loadTemplate($template)
{
return require "templates/$template.php";
}
It's fine, but I have a problem with it.
Let's say I have this code:
require('class.php');
$class = new ClassName; // ClassName is the class which contains the function loadTemplate()
$name = 'Jerry';
$class->loadTemplate('myname');
And "myname.php" is:
<?php
echo "My name is $name.";
In this case I get an error because "myname.php" is actually included in the file of the class and so $name is undefined.
How do I overcome this problem?
Not discussing whether that's the best design, here's how you can do it.
public function loadTemplate($template, $vars)
{
extract($vars);
ob_start();
require "templates/$template.php";
$viewContent = ob_get_contents();
ob_get_clean();
return $viewContent;
}
Pass your variables as an associative array:
$vars = ['name' => 'Jerry']
And then output it:
echo $class->loadTemplate('myname', $vars);
What this does is, it creates variables from the array and loads the view, but with the "ob_" functions we are capturing the output buffer and then echoing it if we want.
You could probably get away without using ob_ just by echoing the require method as you were trying. I'd say give it a go and use what you prefer.

Symfony: using getPartial() in a third party library (in $SFROOT/lib folder)

I am using the events system in Symfony 1.3.8.
I am writing logic for the event handlers. As part of my logic, I may need to send email. I therefore need to get the appropriate partial for the email to be sent.
What is the best way to do this?
I have this so far:
class MyEventHandler
{
public static function handleFooEvent(sfEvent $event)
{
// I need to get partial here
// $body = $this->getPartial('somemodule', 'foo', $params);
}
}
I notice that getPartial() is implemented in sfAction like this:
public function getPartial($templateName, $vars = null)
{
$this->getContext()->getConfiguration()->loadHelpers('Partial');
$vars = null !== $vars ? $vars : $this->varHolder->getAll();
return get_partial($templateName, $vars);
}
To load an helper from anywhere in your application, you can use the following:
sfProjectConfiguration::getActive()->loadHelpers("Partial", "Url", "MyHelper");
Then you can get the needed partial just with:
get_partial('somemodule/somepartial', $params)

Categories