Last Updated: April 20, 2022
·
2.041K
· 2upmedia

Like array_search, but searches a full string

<?php
function array_searchstring( $needle, $haystack, $valueAsNeedle = FALSE ){
    foreach( $haystack as $key => $value ){
        $needleValue = $needle;

        if($valueAsNeedle){
            list( $value, $needleValue ) = array( $needleValue, $value ); // swap values
    }

    if( stripos( $value, $needleValue ) !== FALSE ) {
            return $key;
        }
    }

    return FALSE;
}

I needed array_search() to do a search using the values of my haystack as needles against the needle parameter so I created array_searchstring(). This behavior set by the $valueAsNeedle parameter. By default the array_searchstring() function does a complete string search instead of an exact match which is what array_search() does.

I had a list of school names and for each school name I wanted to say we're servicing grades A to B. Here it is in practice:

<?php
function array_searchstring( $needle, $haystack, $valueAsNeedle = FALSE ){
    foreach( $haystack as $key => $value ){
        $needleValue = $needle;

        if($valueAsNeedle){
            list( $value, $needleValue ) = array( $needleValue, $value ); // swap values
    }

    if( stripos( $value, $needleValue ) !== FALSE ) {
            return $key;
        }
    }

    return FALSE;
}

$schools = array( "Cougar Elementary School", "Eagle Middle School", "Owl High School");

$gradeMapping = array(
    '4-5' => 'elementary',
    '6-8' => 'middle',
    '9-12' => 'high',
);

$buffer = array();

$key = array_search( "elementary", $gradeMapping );

var_dump( 'key', $key );

foreach( $schools as $school ){
    $buffer[] = array( 'title' => $school, 'gradesServiced' => array_searchstring( $school, $gradeMapping, TRUE ) );
}

print_r( $buffer );
/*
Array
(
    [0] => Array
        (
            [title] => Cougar Elementary School
            [gradesServiced] => 4-5
        )

    [1] => Array
        (
            [title] => Eagle Middle School
            [gradesServiced] => 6-8
        )

    [2] => Array
        (
            [title] => Owl High School
            [gradesServiced] => 9-12
        )

)
 */

Because Unit Test

<?php

function array_searchstring( $needle, $haystack, $valueAsNeedle = FALSE ){
    foreach( $haystack as $key => $value ){
        $needleValue = $needle;

        if($valueAsNeedle){
            list( $value, $needleValue ) = array( $needleValue, $value ); // swap values
        }

        if( stripos( $value, $needleValue ) !== FALSE ) {
            return $key;
        }
    }

    return FALSE;
}

class ArraySearchStringTest extends PHPUnit_Framework_TestCase {
    protected $needleAsValueHaystack;
    protected $haystack;

    public function setUp( ){
        $this->needleAsValueHaystack = array(
            '4-5' => 'elementary',
            '6-8' => 'middle',
            '9-12' => 'high',
        );
        $this->haystack = array(
            '4-5' => 'Orange Elementary School',
            '6-8' => 'Waterside Middle School',
            '9-12' => 'Waterloo High School',
        );
    }

    /**
     * @dataProvider assertFalseProvider
     */
    public function test_search_returnsFalse( $needle )
    {
        $this->assertFalse( array_searchstring( $needle, $this->needleAsValueHaystack, TRUE ));
        $this->assertFalse( array_searchstring( $needle, $this->haystack ));
    }

    /**
     * @dataProvider assertEqualsProvider
     */
    public function test_search_returnsCorrectKeys($key, $value)
    {
        $this->assertEquals( $key, array_searchstring( $value, $this->needleAsValueHaystack, TRUE ));
        $this->assertEquals( $key, array_searchstring( $value, $this->haystack ));
    }

    public function test_searchExactMatch_returnsCorrectKeys()
    {
        $text = 'Waterloo High School';
        $this->assertEquals( '9-12', array_searchstring( $text, $this->haystack ));
    }

    public function assertFalseProvider()
    {
        return array(
            array( 'Technical School' )
        );
    }

    public function assertEqualsProvider()
    {
        return array(
            array( '4-5', 'elementary school' ),
            array( '6-8', 'middle school' ),
            array( '9-12', 'high school' ),
        );
    }
}

2 Responses
Add your response

I think your stripos( $needle, $value ) variables are reversed.

over 1 year ago ·

@rob%20malon I programmed it for a specific use case which worked, but I refactored it to separate my particular use case from the default behavior. It should work now the way you would expect it to work. Have a look at the latest version.

Seems like I can't mention your name since it has a space in it. :/

over 1 year ago ·