Testing the results returned from a function

Here is my function that I am working with:

// Hightlight the words of their recent keyword search

function highlightWords($text, $words) {

// Loop through the array of words
foreach ($words as $word) {

// Quote the text for regex
$word = preg_quote($word);
$text = preg_replace(“/\b($word)\b/i”, ‘\1’, $text);
}

return $text;

}

Here is the code the calls it:

if ($_SESSION[‘originalSearch’]) {

  $words = explode(" ", $_SESSION['originalSearch']);
  
  $testimonialBody = "<p>Note: Any matching search keywords will be in <b>bold</b>.</p>\n\n" . $testimonialBody;
  
  $testimonialBody = highlightWords($testimonialBody, $words);

}

$pageTestimonialContent .= text2paragraph($testimonialBody);

Right now, when $text is returned I have no way of knowing if any stop words were bolded. Since a function can only return one value, what is the best way to test to see if $testimonialBody had any changes made to it?

Thank you!

That one value the function returns can be an object with as many properties as you like.

1 Like

Can you point me in the right direction? I’m not very good with functions.

Thank you.

If you’re talking about testing for the purpose of verifying that your function is working correctly, compare the output of the function to a string with the expected output:

$text = 'This string should have some words in bold.';
$expected = 'This string <b>should</b> have <b>some</b> words in bold.';

$words = [ 'should', 'some' ];

$output = highlightWords($text, $words);

echo ($output === $expected) ? 'Test Passed' : 'Test Failed';

Would you suggest an object over an array? An array could also do the job.

Scott

An array implies that the content are multiple occurrences of the same thing. An object allows each variable to be returned to be a completely different type and for each to be given a meaningful name so they can be independently referenced even if the object returned is later modified to add extra values for use by some but not all calls.

Um, but you can also have an array with different types and you can give the indexes meaningful names too.

Yes, arrays are often used for multiple occurrences of the same thing, but arrays can also hold multiple occurrences of the same thing and in those “things”, there are different types, which is also often the case.

In this case, the array wouldn’t be holding multiple occurrences of the same thing. It would just be holding only one occurrence of different things, which is ok to do.

Objects, on the other hand, are usually a mix between data AND behavior, so just giving an object data and no behavior, is sort of overkill for the simple purpose of passing values out of a function.

In general though, it would probably be a better idea to have a HighlightWords class and do the work that way, but I think busboy isn’t doing OOP at all here, so introducing an object wouldn’t be quite right either, when sticking to the functional paradigm.

I also found this interesting SE question and pretty good answer. From that answer, an array will do fine here. :smile:

Scott

Thanks for your tip fretburner. Here is what I came up with. It seems to work, I just hope it’s not an inefficient way of accomplishing it.

// Highlight search words if they conducted a search

if ($_SESSION['originalSearch'] && $_SESSION['subscription'] != "Free") {

	$words = explode(" ", $_SESSION['originalSearch']);
	
	$originalText = $testimonialBody;
	$modifiedText = highlightWords($originalText, $words);
	
	
	if ($originalText === $modifiedText) {
		
		// No words were bolded
		
		$pageTestimonialContent .= text2paragraph($originalText);
		
	} else {
		
		// At least one word was bolded
		
		$modifiedText = "<p>Note: Any keywords from your search will be in <b>bold</b>.</p>\n\n" . $modifiedText;
		
		$pageTestimonialContent .= text2paragraph($modifiedText);
	}

} 

Thanks!

The correct name for an array like that is an object. Just because you define it using array syntax rather than object syntax doesn’t change the fact that when you use named keys with an array you are basically creating an object.

Sorry, but I can’t accept that. At least not in PHP. In PHP arrays and objects are two completely different compound types.

Scott

So please explain in what way an array with named entries behaves differently from an object in PHP.

It sounds like you’re mixing up terminology between JavaScript and PHP. In JavaScript, an associative array is called an object. But in PHP, an associate array is called an array. And that’s not my or anyone else’s opinion either. That’s straight from the official documentation. PHP array keys can be either an integer or a string, and the values can be of any type.

I am not talking about the terminology - I am asking in what way an associative array in PHP differs from an object other than in what it is called. I fully realise that the PHP terminology is different but is it just a different name for what is effectively the same thing or is there an actual difference in PHP between an associative array and an object?

The most obvious difference that comes to mind is how we access values.

$o = new stdClass();
$o->foo = 'foo'; // ok
$o['bar'] = 'bar'; // error

$a = [];
$a['foo'] = 'foo'; // ok
$a->bar = 'bar'; // warning

Not to mention the plethora of array functions.

array_keys($a); // ok
array_keys($o); // warning

In other words just two different ways to do the same thing that are not interchangeable as they are in some other languages.

The two lines you left out of your example for getting the keys

get_object_vars($a); // warning
get_object_vars($o); // ok

Conceptually? Sure. But the “not interchangeable” part is a big deal. You can’t just pretend that an array with different types is actually an object. Nor is it right to say that “the correct name for an array like that is an object.” Nor is it right to imply that an array doesn’t allow different types or meaningful names.

2 Likes

Not considering that there are different functions involved, or that arrays have “keys” while objects have “properties”, an important consideration is “reference”- “pointer”

For demonstration, try this hackish example

<?php
error_reporting(E_ALL);
ini_set('display_errors', true);

$some_array = array("aa" => "1", "ab" => "2", "ac" => "3");
$some_object = new stdClass;
$some_object->oa = "uno";
$some_object->ob = "dos";
$some_object->oc = "tres"; 

function change_value($some_param, $return = false) {
 if (is_array($some_param)) {
  $some_param["aa"] = "new 1";
 }
 if (is_object($some_param)) {
  $some_param->oa = "new uno"; 
 }
 if ($return) {
  return ($some_param);
 }
}

$some_array_copy = $some_array; 
$some_object_copy = $some_object; 

echo "Before function calls<pre>";
var_dump($some_array);
var_dump($some_array_copy);
var_dump($some_object);
var_dump($some_object_copy);
echo "</pre>"; 

change_value($some_array_copy);
change_value($some_object_copy);
$returned_changed_array = change_value($some_array_copy, true);
$returned_changed_object = change_value($some_object_copy, true);

echo "After function calls<pre>";
var_dump($some_array);
var_dump($some_array_copy);
var_dump($returned_changed_array);
var_dump($some_object);
var_dump($some_object_copy);
var_dump($returned_changed_object);
echo "</pre>";
?>
1 Like

You can include a parameter to preg_replace that will tell you whether any replacements were done.

function highlightWords ($text, $words) {
    $bolded = false;
    foreach ($words as $word) {
        $word = preg_quote($word);
        $text = preg_replace("/\b($word)\b/i", '\1', $text, -1, $count);
        if ($count) $bolded = true;
    }
    return ['text' => $text, 'bolded' => $bolded];
}

However, it probably won’t be enough to be worth your while unless you are dealing with 50 MB strings and you’re really squeezed for memory. I would just go with what you’ve got, where you test for equality. Or you can store the length of the string beforehand and then test the length of the string after the replacements.

In addition to the great replies already offered, I’d say the biggest behavioral difference is, all the functions available for arrays in PHP don’t work on objects properties or methods and all features available with objects in PHP don’t work on array keys or values. The fact an array can “act” like an object simply doesn’t make it one.

Scott

Bringing this back to the original question - in what way do they behave differently with respect to returning information from a function?