• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Prüfen ob ein Teil eines Strings in einem Arraywert vorkommt

Tobi44

Mitglied
Hallo,

ich möchte hiermit prüfen, ob der Teil eines Wertes in einem Arraywert vorkommt:

PHP:
$gethost = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$german_hosts = array("t-ipconnect.de", "t-dialin.net"); 

$check_host_in_array = strpos($gethost, $german_hosts);
if ($check_host_in_array === TRUE) { echo "true"; }
Bedeutet für mich, dass er den Hostname des Users nehmen und feststellen soll, ob dieser einen der Werte im Array $german_hosts enthält. Nur leider wird mir nie true ausgegeben. Wieso klappt denn das nicht?
 
Ja, aber er vergleicht mit === - das passt schon.

Das Problem ist eher, dass Du versuchst einen String in einem Array zu finden. Das geht mit strpos nicht. Verwende eher in_array().
 
Hallo,

also da komme ich auf keine Lösung. Ich muss aber doch irgendwie mit strpos arbeiten, denn im Array stehen ja nur Teile eines Hostnames. Irgendwie muss doch überprüft werden, ob ein Teil es tatsächlichen Hostname im Array vorkommt oder nicht.

Kann mir nicht vorstellen, dass das nicht gehen soll. Alternativ kann ich ja wieder auf meine bisherige Methode zurückgreifen, die dann so aussieht:
PHP:
$gethost = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$eintrag1 = 't-ipconnect.de'; 
$check1 = strpos($gethost, $eintrag1); 
$eintrag2 = 't-dialin.net'; 
$check2 = strpos($gethost, $eintrag2);
if ($check1 !== FALSE OR $check2 !== FALSE) { echo "true"; }
 
strpos() kann aber nicht mit Arrays umgehen.

Daher mein alternativer Vorschlag:
PHP:
$gethost = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$german_hosts = array("t-ipconnect.de", "t-dialin.net"); 

foreach( $german_hosts as $host ) {
 if( strpos($gethost, $hosts) === true ) {
  echo $true;
 }
}
 
Ja, aber er vergleicht mit === - das passt schon.
strops() gibt bei Erfolg einen Interger zurück, ansonsten einen Boolean (false!).
Wie soll so eine Bedingung jemals zutreffen? -> integer === boolean(true)
Das sind zwei unterschiedliche Datentypen - beim ===-Vergleichsoperator wird geprüft, ob die beiden verglichenen Daten den selben Datentyp haben, daher muss das wenn schon so lauten:

PHP:
$gethost = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$german_hosts = array("t-ipconnect.de", "t-dialin.net"); 

foreach( $german_hosts as $host ) {
 if( strpos($gethost, $hosts) !== false ) {
  echo $true;
 }
}

bzw.

PHP:
$gethost = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$german_hosts = array("t-ipconnect.de", "t-dialin.net"); 

foreach( $german_hosts as $host ) {
 if(is_int($gethost, $hosts)) {
  echo $true;
 }
}
 
Am Rande: Da sind noch ein paar „Flüchtigkeitsfehler“ drin. Im ersten Beispiel etwa einmal $hosts, wo $host gemeint ist. Die Schleife sollte im Erfolgsfall zudem vermutlich nicht weiterlaufen. Das hängt aber letztlich von der konkreten Anwendung ab.

Hier eine etwas ausgereiftere Testfunktion:

PHP:
/**
 *
 * @param  string $needle
 * @param  string $haystack
 * @return bool
 * @throws Exception
 */
function domainIsWithinDomain($needle, $haystack)
{
    if (!is_string($needle)) {
        throw new Exception('$needle must be of type string');
    }

    if (!is_string($haystack)) {
        throw new Exception('$haystack must be of type string');
    }

    $result = preg_match(
            '/(?<=\.|^)' . preg_quote($haystack, '/') . '$/',
            $needle);

    return (1 === $result);
}

Hintergrund: t-ipconnect.example soll nicht als zu foo-t-ipconnect.example gehörig erkannt werden.

Zum regulären Ausdruck siehe vor allem: http://www.php.net/manual/en/regexp.reference.assertions.php

Einige Tests:

PHP:
$tests = array();

// Empty input
$tests[] = array(
    'needle'   => '',
    'haystack' => '',
    'expected' => true
);

// Same domain
$tests[] = array(
    'needle'   => 'example.org',
    'haystack' => 'example.org',
    'expected' => true
);

// Different TLD
$tests[] = array(
    'needle'   => 'example.org',
    'haystack' => 'example.com',
    'expected' => false
);

// Additional subdomain in needle
$tests[] = array(
    'needle'   => 'de.example.org',
    'haystack' => 'example.org',
    'expected' => true
);

// Needle lacks needed subdomain
$tests[] = array(
    'needle'   => 'example.org',
    'haystack' => 'de.example.org',
    'expected' => false
);

// Subdomain of needle matches only in last part
$tests[] = array(
    'needle'   => 'xfoo.example',
    'haystack' => 'foo.example',
    'expected' => false
);

// Subdomain of haystack matches only in last past
$tests[] = array(
    'needle'   => 'foo.example',
    'haystack' => 'xfoo.example',
    'expected' => false
);

$failureCounter = 0;

foreach ($tests as $test) {
    $result = domainIsWithinDomain($test['needle'], $test['haystack']);

    if ($result === $test['expected']) {
        echo '.';
    } else {
        echo "\n" . 'FAILURE.' . print_r($test, true) . "\n";
        $failureCounter++;
    }
}

echo "\n";
echo 'Tests complete. ' . $failureCounter . ' failures.' . "\n";

Beispiel mit Liste und Schleife:

PHP:
$needle = 'x.provider1.example';

$domainList = array(
    'provider1.example',
    'provider2.example',
    'provider3.example.com',
);

$found = false;
$i = 0;
$size = count($domainList);

while (!$found && $i < $size) {
    $found = domainIsWithinDomain($needle, $domainList[$i]);
    $i++;
}

if ($found) {
    echo $needle . ' lies within a domain from the list.' . "\n";
}

(Alternativ eben foreach mit break. Aber da wir die Variante schon hatten…)
 
Zuletzt bearbeitet:
Hi,

@mermshaus
Also das ist mir nun doch zu kompliziert. "t-ipconnect.example soll nicht als zu foo-t-ipconnect.example gehörig erkannt werden." -> Das ist mir noch zu hoch - kann da nicht folgen.

Habe nun den ersten von T!P-TOP geposteten Schnipsel getestet und damit funktioniert es. Mit foreach habe ich es auch schon probiert, ging aber vermutlich wegen dem fehlerhaften === true nicht.

Danke & Gruß
 
Tobi44 schrieb:
kann da nicht folgen

Beispiel:

PHP:
<?php

#$gethost = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$gethost = '233x1s.fast-dialin.network.hungary-superprovider.example';
$german_hosts = array("t-ipconnect.de", "t-dialin.net");

foreach( $german_hosts as $host ) {
 if( strpos($gethost, $host) !== false ) {
  echo 'User is connected through ' . $host;
 }
}
 
Ah okay, ich verstehe. Angenommen ich setze einen Punkt davor (.t-ipconnect.de) dann sollte es klar sein. Außerdem habe ich ein .de dahinter.
So wichtig ist das Script übrigens nicht, da ich nur Usern aus Deutschland beim Seitenaufruf einen entsprechenden Hinweis einblenden will. Wirklich zuverlässig ist es nicht, da auch IPs (wie bspw. mobile Internetverbindungen) die gar keinen Hostnamen haben (sondern IP = Host) nicht mit einbezogen werden.

Für meine Ansprüche reicht es aber völlig und funktioniert nun auch.

Vielen Dank :-)
 
Zurück
Oben