neubert neubert - 2 years ago 115
PHP Question

matching a part of a string from the beginning

I have a date (eg. yyyy-mm-dd hh:mm:ss) and I want to be able to return true if we have a string matching that pattern, completely, or that partially matches that pattern, from beginning to end. eg.

would match the pattern because
would match the yy but
would not match because
isn't a valid "y" character.

A few inelegant solutions occur to me. I could do
on something like this:


That just performs a partial match based on the year. It'd need to be expanded out to account for the month, day, hour, minute, etc, but that should show idea # 1.

I could also do something like...

$patterns = [
isset($patterns[strlen($str)] && preg_match('#^' . $patterns[strlen($str)] . '$#', $str)

But that kinda seems convoluted as well.

I could also do this:

switch (strlen($str)) {
case 1: return preg_match('#^\d$#', $str);
case 2: return preg_match('#^\d\d$#', $str);
case 3: return preg_match('#^\d\d\d$#', $str);
case 4: return preg_match('#^\d\d\d\d$#', $str);
case 5: return preg_match('#^\d\d\d\d-$#', $str);

But that seems bloated as well.

In other words, I'm looking for a function for which
will return true, as will
. But
will return false, as will

What I want to be able to do is to pass valid values into an SQL query. eg.
WHERE date_column LIKE '$str%'
. If
is a DATETIME then searching for
is a waste of time because it's not possible for
to have that as a value.

Any ideas?

Answer Source

Something like this should work:

function doesMatch($str) {
    // The date pattern split so that each array entry matches exactly one character
    $pattern_chunks = array(
        '\d', '\d', '\d', '\d', '-',
        '\d', '\d', '-',
        '\d', '\d',
        '\d', '\d', ':',
        '\d', '\d', ':',
        '\d', '\d'

    $chunk_count = count($pattern_chunks);
    $str_len = strlen($str);

    // If the string is empty, it's clearly not a date
    if ( $str_len < 1 ) { return false; }

    // If the string is longer than our pattern chunks, there's no way it matches
    if ( $str_len > $chunk_count ) { return false; }

    // Make a pattern using the first N chunks of our pattern parts
    $pattern = '^' . implode('', array_slice($pattern_chunks, 0, $str_len)) . '$';

    // Return if the string matches
    return (preg_match($pattern, $str) > 0);

For example your input string is 6 characters long, it only uses the first 6 chunks of the date pattern (^\d\d\d\d-\d$).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download