PHP - strlen ($ string) не взаимодействует - PullRequest
0 голосов
/ 04 февраля 2012
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="StylesTSL.css" type="text/css" media="screen">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Terraria Server List</title>
</head>
<body>
<div id="page">
<div id="logobase">
<div class="filler"></div>
<center><img src="logo.png" width="400" height="100"/></center>
</div>
<div class="filler"></div>
<div id="form">
<center>
<h1>Add a server!</h1>
<form action="" method="post">
Title: <input type="text" name="title" /><br />
IP & Port: <input type="text" name="ip" />(E.G: 127.0.0.1:7777)<br />
Description:<br />
<textarea name="desc"></textarea><br />
E-Mail: <input type="text" name="email" /><br />
Type:       <select name='type'><option value="Hamachi" selected>Hamachi</option><option value="Non-Hamachi">Non-Hamachi</option></select><br />
<input type="submit" name="submit" value="Submit server!" />
</form>
</center>
</div>
<div class="filler"></div>
<?php
//Our variables
$title = $_POST['title'];
$ip = $_POST['ip'];
$desc = $_POST['desc'];
$type = $_POST['type'];
$email = $_POST['email'];
$submit = $_POST['submit'];
//Connect to our DB
$con = mysql_connect("localhost", "x", "x");   
mysql_select_db("bobrocke_users", $con) or die("Could not select database");
if ($submit) {
    if (strlen($title) == 0) {
        die("Invalid title!");
    }
    else if (strlen($title) >= 51) {
        die("Invalid title!");
    }
    else if (strlen($ip) == 0) {
        die("Invalid IP!");
    }
    else if (strlen($ip) >= 51) {
        die("Invalid IP!");
    }
    else if (strlen($desc) == 0) {
        die("Invalid description!");
    }
    else if (strlen($email) == 0) {
        die("Invalid E-Mail!");
    }
    else if (strlen($email) >= 101) {
        die("Invalid E-Mail!");
    }
    else {
    mysql_query("INSERT INTO `Servers` (`ip`, `desc`, `type`, `title`, `email`) VALUES('".$ip."', '".$desc."', '".$type."', '".$title."', '".$email."')") or die(mysql_error()); 
    }
}
$get_all = mysql_query("SELECT * FROM Servers");
while ($row = mysql_fetch_assoc($get_all)) {
?>
<div class="servbox">
<center>
<h1><?php echo $row['title']?></h1><br /></center>
IP: <span class="ip"><?php echo $row['ip']?></span><br /><hr />
<p><?php echo $row['desc']?></p><br /><br />
<a href="http://bobcraft-games.com/TSL/page.php?id=<?php echo $row['id'] ?>">Server's Page</a><br />
Type: <?php echo $row['type']?><br /><br />
</div>
<div class="filler"></div>
<?php
}
?>
</div>
</body>
</html>

Что я пытаюсь сделать, так это запретить пользователям публиковать недопустимые пустые поля.

По какой-то причине, однако, эти меры if (strlen($submittedValue) == 0) или что-то еще.

Ответы [ 4 ]

2 голосов
/ 04 февраля 2012

Вы можете лучше использовать функцию empty() в PHP, которая проверяет, является ли переменная пустой (например, strlen(...) == 0)

И: не забудьте mysql_real_escape_string() для переменных!

1 голос
/ 04 февраля 2012

Используйте trim (), чтобы убрать все пробелы в начале и конце строки. Используйте пустой (trim ($ var)) для проверки.

Поскольку вы используете utf-8, когда вы хотите считать символы, используйте mb_strlen () http://php.net/manual/en/function.mb-strlen.php

0 голосов
/ 05 февраля 2012

Итак, strlen () не взаимодействует.

Если какой-то код не взаимодействует, я делаю следующее:

  • Устранение проблемы.Избавившись от всего, что не имеет отношения к делу.
  • Попробуйте и уточнить, что следует делать, спросив себя: «Каковы мои утверждения и ожидания?».
  • Напишите специальный сценарий для проверкинекорректно работающий код
  • Изменяйте некорректно работающий код, пока он не будет вести себя как положено (делая его более тестируемым , если требуется).

Изолировать проблему.Избавившись от всего, что не имеет отношения к делу.

Сначала давайте возьмем ваш оригинальный пример кода и избавимся от всего, что не имеет отношения к конкретному рассматриваемому вопросу.Чтобы оставить только код проверки , который использует strlen .Итак, теперь мы можем видеть более четко.

Затем попытайтесь уточнить, что следует делать, спросив «Каковы мои утверждения и ожидания?».

Я предполагаю из вашего кода, что:

  • дано
    • a поле информации (название, имя, ip)
    • и его минимальная длина
    • и ее максимальная длина
  • когда значение передается пользователем, который имеетдлина меньше минимальная длина или больше максимальная длина
    • затем , значение должно быть отклонено
  • иначе все нормально

Напишите специальный скрипт для проверки некорректно работающего кода

Я бы создал скрипт html / php исключительно для тестированияиз PHP, который вызывает горе.Назовите это FormFieldValidatorTest.php например.Тестовый сценарий находится в проекте веб-сайта, но предназначен только для того, чтобы он выполнялся мнойПоэтому я поместил бы его в защищенный паролем каталог или другое недоступное для публики место.

Я хочу UTF-8 html-страницу, которая представляет некоторые строки известной длины.Скажем, буква «а», которую мы знаем, имеет длину один символ, а «пустое поле», которое мы знаем, имеет длину ноль символов.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Test</title>
</head>
<body>

<form action="" method="get">
<input name="singleCharacterString" type="text" value="a" size="1" maxlength="1">
<input name="emptyString" type="text" value="" size="1" >
<input type="submit" name="Submit" value="Run Tests">
</form>
...

Затем в верхней части FormFieldValidatorTest.php я бы написалнекоторый php-код для:

  • получения этих фиксированных, жестко запрограммированных значений формы (данных прибора).
  • передать данные о приборах в некоторые тесты, а затем
  • вернуть мне массив результатов

Чтобы сохранить вещи в чистоте, я бы поставил в тупикпроверьте код в функции, назовите его runTestSuite(), который будет подробно описан ниже.

<?php 
//FormFieldValidatorTest.php

if ( $_REQUEST['Submit'] == 'Run Tests' ) {

    //perform the tests
    $testResultsArray = runTestSuite();

    /**
    * Lets loop through the results and count the failures
    */
    $failureCounter = 0;
    foreach ( $testResultsArray as $result ) {
        if ( $result['hasFailed'] ) {
            $failureCounter++;
        }   
    }
} else {
    //no tests were run set the results to null
    $testResultsArray = null;
}

?>
<html>
...

Я бы добавил немного php в html-часть FormFieldValidatorTest.php.Это должно распечатать результаты, если они были выполнены (то есть, когда $testResultsArray не идентичен null):

<code><?php
//FormFieldValidatorTest.php
...
?>
<html>
...
<body>
<form action="" method="get">
...
</form>

<?php if ( $testResultsArray !== null ) : ?>
    <h1>Results</h1>
    <pre>
    <?php if ( $failureCounter > 0 ) : ?>
        Failed. <?php echo $failureCounter ?> tests failed.
        <?php print_r( $testResultsArray ); ?>
    <?php else : ?>
        Passed
    <?php endif; ?>
    

Затем я заполнил бы все мои функции runTestSuite().По сути, это два вызова функции assertTrue(), которые я конкретизирую позже.

  • Во-первых, утверждается, что это правда, что strlen возвращает 1, когда ему дано singleCharacterString.
  • Затем он утверждает, что это правда, что strlen возвращает 0, когда ему дано emptyString.

В то же время он передает сообщение, описывающее каждый тест.Они сохраняются в массиве результатов, чтобы облегчить отладку в случае неудачи тестов.


/**
* @desc A suite of tests to excercise that troublesome code
* @return array of results for each test done
*/
function runTestSuite() {

    /**
    * Lets Run some tests
    */

    /**
    * Create the results array
    */
    $testResultsArray = array();

    /**
    * Test some known data submitted via a form parameter 
    */
    assertTrue( 
        ( strlen( $_REQUEST['singleCharacterString'] ) == 1 ), 
        'Expect it to be TRUE that singleCharacterString http parameter
        has a stringlength of 1', 
        $testResultsArray );

    /**
    * @todo Add more tests here. 
    */
    assertTrue( 
        ( strlen( $_REQUEST['emptyString'] ) == 0 ), 
        'Expect it to be TRUE that emptyString http parameter
        has a stringlength of 0', 
        $testResultsArray );

    return $testResultsArray;
}

Наконец, я расшифровал функцию assertTrue().Это в основном проверяет, имеет ли первый аргумент Failed проверку утверждения.Затем он добавляет этот результат и message как запись в $testResultsArray.

/**
* @desc A TRUE assertion
* @param mixed - a value that we expect to be true
* @param string - a message to help understand what we are testing
* @param array - a collection of results so far passed by reference
* @return void
*/
function assertTrue( $value, $message, &$testResultsArray ) {   

    if ( $value ) {
        //value is as asserted
        $currentResult = array(         
            'message' => $message,
            'hasFailed' => FALSE
            );
    } else {
        //value is not as asserted
        $currentResult = array(
            'message' => $message,
            'hasFailed' => TRUE
            );
    }   

    $testResultsArray[] = $currentResult;   

}

Теперь тестовый скрипт завершен. См. Здесь .

Если я запустлю его и увижу, что оно прошло, я могу быть уверен, что strlen сотрудничает.Если он не работает, я могу перейти к:

Изменить код неправильного поведения до тех пор, пока он не будет вести себя как положено.

Чтобы сделать это, вам, вероятно, понадобится разделить бит неправильного поведения наотдельная функция или класс, который находится в своем собственном файле.Это делает его повторно используемым , поэтому его можно вызывать как из тестового кода, так и из действующего производственного кода.

То, что мы действительно должны проверять, это правило длины , которое указывает, что разрешены только строки определенной длины.

Итак, давайте выделим это, чтобы мы могли его проверить.Может быть, функция в библиотеке rules с именем isCorrectLength () в файле с именем ServerValidationRules.php

<?php 
//ServerValidationRules.php

/**
* @desc boolean function to test string length 
* @param string to test
* @param integer defining minimum length required
* @param integer defining maximum length required
* @return TRUE if its the correct length, FALSE otherwise.
*/
function isCorrectLength( $string, $minLength, $maxLength ) {

    if ( strlen( $string ) < $minLength ) {
        //its too short
        return FALSE;
    }

    if ( strlen( $string ) > $maxLength ) {
        //its too long
        return FALSE;
    }
    return TRUE;
}

Затем мы можем заменить код в нашем тесте, чтобы использовать его вместо собственного strlen() function.

<?php
//FormFieldValidatorTest.php

require_once('ServerValidationRules.php');

...

/**
* @desc A suite of tests to excercise that troublesome code
* @return array of results for each test done
*/
function runTestSuite() {


    $testResultsArray = array();

    /**
    * Test some known data submitted via a form parameter 
    */
    assertTrue( 
        //( strlen( $_REQUEST['singleCharacterString'] ) == 1 ), 
        isCorrectLength( $_REQUEST['singleCharacterString'], 0, 1 ),
        'Expect it to be TRUE that singleCharacterString http parameter
        has a stringlength of 1', 
        $testResultsArray );

    /**
    * @todo Add more tests here. 
    */
    assertTrue( 
        //( strlen( $_REQUEST['emptyString'] ) == 0 ), 
        isCorrectLength( $_REQUEST['emptyString'], 0, 0 ),
        'Expect it to be TRUE that emptyString http parameter
        has a stringlength of 0', 
        $testResultsArray );

    return $testResultsArray;
}
...

Итак, теперь мы можем заменить код в производственном скрипте на:

<title>Terraria Server List</title>
...
<?php
...
if ( $submit ) {    
    if (!( isCorrectLength( $title, 0, 50 ) )) {
        die("Invalid title!");
    }    
    elseif (!( isCorrectLength($ip, 0, 50) )) {
        die("Invalid IP!");
    }
    elseif (!( isCorrectLength( $desc, 0, 10000 ) )) {
        die("Invalid description!");
    }    
    elseif (!( isCorrectLength( $email, 0, 100 ) )) {
        die("Invalid E-Mail!");
    }
    else {
        //do the insert
    }
}
...

Или, что еще лучше, переместить length правила в одну функцию, так что логика может быть повторно использована другим кодом (например, некоторый код в наборе тестов).

Мы могли бы свернуть все это в функцию с именем isServerFieldsValid и поместить ее в нашServerValidationRules.php file.

<?php
//ServerValidationRules.php
...
/**
* @desc tests user-submitted fields appending feedback to an array of messages upon failure.
* @param associative array of Posted values keyed by field name
* @param array of messages passed by reference
* @return boolean True if all fields are valid. False otherwise.
*/
function isServerFieldsValid( $values, &$messages ) {   

    $hasFailed = FALSE;

    if (!( isCorrectLength( $values['title'], 1, 50 ) )) {
        $hasFailed = TRUE;
        $messages[] = "Invalid title!";
    }    

    if (!( isCorrectLength($values['ip'], 1, 50) )) {
        $hasFailed = TRUE;
        $messages[] = "Invalid IP!";    
    }

    if (!( isCorrectLength( $values['desc'], 1, 1000 ) )) {
        $hasFailed = TRUE;
        $messages[] = "Invalid description!";
    }    

    if (!( isCorrectLength( $values['email'], 1, 100 ) )) {
        $hasFailed = TRUE;
        $messages[] = "Invalid E-Mail!";
    }

    if ( $hasFailed ) {
        return FALSE;
    } 
    //else
    return TRUE;
}

, а затем добавьте еще несколько утверждений к функции набора тестов в нашем тестовом скрипте.

...

/**
* @desc A suite of tests to excercise that troublesome code
* @return array of results for each test done
*/
function runTestSuite() {

    /**
    * Initialize the results array
    */
    $testResultsArray = array();

    ...

    /**
    * Test some variants of possible user submitted data
    * 
    * @todo We ought to invoke an assertFalse() function.
    *  In meantime, hack it by passing a negated value to assertTrue().
    */

    /**
    * When given values that are too long, 
    * expect a validation failure.
    */
    $validationMessages = array();
    $result = isServerFieldsValid(
            array(
                'title' => str_repeat( 'a' , 51 ),
                'ip' => str_repeat( 'a' , 51 ),
                'desc' => str_repeat( 'a' , 1001 ),
                //?'type' => str_repeat( 'a' , 1001 ),
                'email' => str_repeat( 'a' , 101 ),
                ),
            $validationMessages
            );

    assertTrue(                 
        (!( $result )), 
        'Expect it to be TRUE that result is False when given long values',
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid title!', $validationMessages ), 
        'Expect messages to say "Invalid title!"', 
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid IP!', $validationMessages ), 
        'Expect messages to say "Invalid IP!"', 
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid description!', $validationMessages ), 
        'Expect messages to say "Invalid description!"', 
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid E-Mail!', $validationMessages ), 
        'Expect messages to say "Invalid E-Mail!"', 
        $testResultsArray );

    /**
    * When given values that are too short,
    *  expect a validation failure.
    */
    $validationMessages = array();
    $result = isServerFieldsValid(
            array(
                'title' => null,
                'ip' => null,
                'desc' => null,             
                'email' => null,
                ),
            $validationMessages
            );

    assertTrue(                 
        (!( $result )), 
        'Expect it to be TRUE that result is False when given short values',
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid title!', $validationMessages ), 
        'Expect messages to say "Invalid title!"', 
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid IP!', $validationMessages ), 
        'Expect messages to say "Invalid IP!"', 
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid description!', $validationMessages ), 
        'Expect messages to say "Invalid description!"', 
        $testResultsArray );

    assertTrue(                 
        in_array( 'Invalid E-Mail!', $validationMessages ), 
        'Expect messages to say "Invalid E-Mail!"', 
        $testResultsArray );

    /**
    * When given values that are the correct length,
    *  expect a validation success.
    */
    $validationMessages = array();
    $result = isServerFieldsValid(
            array(
                'title' => 'a title',
                'ip' => 'an ip',
                'desc' => 'a desc',             
                'email' => 'an email',
                ),
            $validationMessages
            );

    assertTrue(                 
        ( $result ), 
        'Expect it to be TRUE that result is True when given correct values',
        $testResultsArray );

    assertTrue(                 
        (!( in_array( 'Invalid title!', $validationMessages ) )), 
        'Expect messages NOT to say "Invalid title!"', 
        $testResultsArray );

    assertTrue(                 
        (!( in_array( 'Invalid IP!', $validationMessages ) )), 
        'Expect messages NOT to say "Invalid IP!"', 
        $testResultsArray );

    assertTrue(                 
        (!( in_array( 'Invalid description!', $validationMessages ) )), 
        'Expect messages NOT to say "Invalid description!"', 
        $testResultsArray );

    assertTrue(                 
        (!( in_array( 'Invalid E-Mail!', $validationMessages ) )), 
        'Expect messages NOT to say "Invalid E-Mail!"', 
        $testResultsArray );


    return $testResultsArray;
}

...

Итак, полный сценарий тестирования теперь выглядит следующим образом .

Итак, если это пройдет, мы можем изменить производственный код, заменив все эти if (strlen ) { die } заявления с вызовом этой новой, хорошо протестированной, isServerFieldsValid() функции:

<title>Terraria Server List</title>

...

if ( $submit ) {
    $messages = array();
    if (!( isServerFieldsValid( $_POST, $messages ) )) {
        echo 'Invalid data was submitted:' . PHP_EOL;

        foreach( $messages as $message ) {
            echo $message . PHP_EOL;
        }

        exit;
    } else {
        //do the insert
} 
...

Ну, вот как бы я справился с кодом, который все равно не взаимодействует.

Код:

Примечание:

Мне понадобилось несколько часов, чтобы написать этот ответ, но очень мало времени, чтобы написать реальный тест.Когда вы начинаете привыкать, часто требуется всего несколько минут, чтобы набросать тест и выяснить, почему какой-то код не взаимодействует.

Совет: вам не нужно писать свои собственные функции утверждений.,Смотри: http://www.simpletest.org/en/start-testing.html

0 голосов
/ 04 февраля 2012

Почему бы просто не использовать if (!$somestring) ...? Пустая строка будет проверяться как false, так же как и null - до тех пор, пока для $somestring не может быть установлено нестроковое значение (кроме null), которое должно работать нормально. Например:

...
    if (!$title) {
        die("Invalid title!");
    }
    else if (strlen($title) >= 51) {
        die("Invalid title!");
    }
...

Также будут обнаружены случаи, когда в данных формы не было отправлено $title.

Вы должны также избегать ваших строк, когда используете их в своем запросе. Итак:

mysql_query("INSERT INTO `Servers` (`ip`, `desc`, `type`, `title`, `email`) VALUES('".$ip."', '".$desc."', '".$type."', '".$title."', '".$email."')") or die(mysql_error()); 

.. должно стать:

mysql_query("INSERT INTO `Servers` (`ip`, `desc`, `type`, `title`, `email`) VALUES('".
  mysql_real_escape_string($ip)."', '".
  mysql_real_escape_string($desc)."', '".
  mysql_real_escape_string($type)."', '".
  mysql_real_escape_string($title)."', '".
  mysql_real_escape_string($email)."')")
or die(mysql_error()); 

В противном случае люди могут связываться с вашим запросом, помещая значимые в SQL символы и код в данные формы.

...