找回密碼
 立即註冊
搜索
熱搜: 活動 交友 discuz
查看: 542|回復: 1

PHP 驗證

[複製鏈接]

257

主題

38

回帖

1138

積分

管理員

積分
1138
發表於 2023-5-25 11:07:50 | 顯示全部樓層 |閱讀模式

Validation

Validation of data is a fundamentally important aspect of a CRUD application. You need to be sure that the data that the client is sending you is what you expect. This is not just for security reasons, protecting your data from misuse and intentional corruption, but also simply from unintentional mistakes in submitting data. Strings limited to a certain length, dates in a particular format and required fields are all common uses of data validation.

The Editor PHP libraries provide two different validation methods:

  • Field based, where each individual value submitted is independently validated: Field->validator().
  • Global validation, where the data submitted by the client-side can be validated as a whole: Editor->validator().

Field validation is the one you will most commonly work with - for example checking that an e-mail address field actually contains an e-mail address, and Editor provides a number of ready to use validators for the most common data types as well as the ability to specify your own. Global validation can be useful when checking dependencies between fields and conflicts in the existing data set.

Field validation

The Editor PHP libraries provide a validator() method for the Field class and a number of pre-built validation methods in the Validate class. Each of these validation methods returns a function which is executed when required to validate submitted data.

Consider the following example - the Validate::minNum() function is configured with a number and returns a function that can be used for the field validator.

1
2
Field::inst("age")
    ->validator(Validate::minNum( 16 ));

Please see below for more detailed examples.

Validation options

Each validation method provided by the Validation class can optionally accept parameters to tell it how to validate data (for example the minLen method will accept an integer to indicate the minimum length of an acceptable string), but all optionally accept a ValidateOptions class instance. This class defines a number of options that are shared between all validation methods.

The ValidateOptions class is constructed with ValidateOptions::inst() (or new ValidateOptions() in PHP 5.4+) similar to the other Editor classes. It has three methods that can be used to alter the validation behaviour:

  • ->allowEmpty( boolean ): How to handle empty data (i.e. a zero length string):
    • true (default) - Allow the input for the field to be zero length
    • false - Disallow zero length inputs
  • ->message( string ): the error message to show if the validation fails. This is simply "Input not valid" by default, so you will likely want to customise this to suit your needs.
  • ->optional( boolean ): Require the field to be submitted or not. This option can be particularly useful in Editor as Editor will not set a value for fields which have not been submitted - giving the ability to submit just a partial list of options.
    • true (default) - The field does not need to be be in the list of parameters sent by the client.
    • false - The field must be included in the data submitted by the client.

Example - setting a custom error message

1
2
3
4
5
6
Field::inst( "stock_name" )
    ->validator( Validate::minNum(
        10,
        new ValidateOptions::inst()
            ->message( 'Stock name must be at least 10 characters long' )
    ) );

Multiple validators

It can often be useful to use multiple validators together, for example to confirm that an input string is less than a certain number of characters and also that it is unique in the database. Multiple validators can be added to a field simply by calling the Field->validator() method multiple times. Rather than overwriting the previous validator it will in fact add them together. They are run in the sequence they were added, and all validators must pass for the data to be accepted as valid.

As an example consider the following code which will check the min and max length of the data, and also that it is unique:

1
2
3
4
Field::inst( 'stock_name' )
    ->validator( Validate::minLen( 10 ) )
    ->validator( Validate::maxLen( 12 ) )
    ->validator( Validate::unique() );

Ready to use field validators

The Validate class in the Editor PHP libraries has a number of methods which can be used to perform validation very quickly and easily. These are:

Basic

  • none( ValidateOptions $cfg=null ) - No validation is performed
  • basic( ValidateOptions $cfg=null) - Basic validation - only the validation provided by ValidateOptions is performed
  • required( ValidateOptions $cfg=null) - The field must be submitted and the data must not be zero length. Note that Editor has the option of not submitting all fields (for example when inline editing), so the notEmpty() validator is recommended over this one.
  • notEmpty( ValidateOptions $cfg=null) - The field need not be submitted, but if it is, it cannot contain zero length data
  • boolean( ValidateOptions $cfg=null) - Check that boolean data was submitted (including 1, true on, yes, 0, false, off and no)

Numbers

  • numeric( string $decimalChar=".", ValidateOptions $cfg=null) - Check that any input is numeric.
  • minNum( integer $min, string $decimalChar=".", ValidateOptions $cfg=null) - Numeric input is greater than or equal to the given number
  • maxNum( integer $max, string $decimalChar=".", ValidateOptions $cfg=null) - Numeric input is less than or equal to the given number
  • minMaxNum( integer $min, integer $max, string $decimalChar=".", ValidateOptions $cfg=null) - Numeric input is within the given range (inclusive)

Strings

  • email( ValidateOptions $cfg=null) - Validate an input as an e-mail address.
  • ip( ValidateOptions $cfg=null) - Validate as an IP address.
  • minLen( integer $min, ValidateOptions $cfg=null) - Validate a string has a minimum length.
  • maxLen( integer $max, ValidateOptions $cfg=null) - Validate a string does not exceed a maximum length.
  • minMaxLen( integer $min, integer $max, ValidateOptions $cfg=null) - Validate a string has a given length in a range
  • noTags( ValidateOptions $cfg=null) - Don't allow HTML tags
  • url( ValidateOptions $cfg=null) - Validate as an URL address.
  • values(array $values, ValidateOptions $cfg=null) - Allow only values which have been specified in an array of options (the first parameter). This could be useful if you wish to have free-form input or event a select list, and want to confirm that the value submitted is within a given data set (see also the dbValues() method if valid values are stored in a database). Note that the values given in the values array are checked against the submitted data as case-sensitive data (i.e. `"A" != "a").
  • xss( ValidateOptions $cfg=null) - Check to see if the input could contain an XSS attack. This used the Field's XSS formatting function to determine if the input string needs to be formatted or not.

Date / time

  • dateFormat( string $format, ValidateOptions $cfg=null) - Check that a valid date input is given. The format is defined by PHP's date() method which is used for the parsing of date and time string.

Database

  • dbValues( ValidateOptions $cfg=null, string $column=null, string $table=null, Database $db=null, array $valid=null) - Allow only a value that is present in a database column. This is specifically designed for use with joined tables (i.e. ensure that the reference row is present before using it), but it could potentially also be used in other situations where referential integrity is required.
  • unique( ValidateOptions $cfg=null, string $column=null, string $table=null, array $db=null) - Ensure that the data submitted is unique in the table's column.

Custom field validators

If the provided methods above don't suit the kind of validation you are looking for, it is absolutely possible to provide custom validation methods. The validator() Field method will accept a function that returns either true or a string and accepts the following input parameters:

  1. value - The value to be validated
  2. data - The collection of data for the row in question
  3. field -The host Field instance
  4. host - Information about the host Editor instance

The return value should be true to indicate that the validate passed, or a string that contains an error message if the validation failed.

The following simple example shows how a maxLen string check could be implemented with a custom validation method:

1
2
3
4
5
6
Field::inst( 'last_name' )
    ->validator( function $val$data$field$host ) {
        return strlen$val ) > 50 ?
            'Name length must be 50 characters or less' :
            true;
    } );

Field validation examples

Use the Validation.minNum() method to validate an input as numeric and greater or equal to a given number (no validation options specified, so the defaults are used):

1
2
3
// Simple non-empty field
Field::inst( 'age' )
    ->validator( Validate::minNum( 16 ) )

As above, but with ValidateOptions used to set the error message:

1
2
3
4
5
6
7
// Number range check with custom error message
Field::inst( 'range' )
    ->validator( Validate::minNum(
        16,
        ValidateOptions::inst()
            ->message( 'Minimum age is 16' )
    ) );

This time validating an e-mail address which cannot be empty and must be submitted:

1
2
3
4
5
6
Field::inst( 'email' )
    ->validator( Validate::email(
        ValidateOptions::inst()
            ->allowEmpty( false )
            ->optional( false )
    ) );

A join with dbValues which will accept an empty value, which is stored as null on the database:

1
2
3
4
5
6
7
Field::inst( 'users.site' )
    ->options( Options::inst()
        ->table( 'sites' )
        ->value( 'id' )
        ->label( 'name' )
    )
    ->validator( Validate::dbValues() ),

Allow only certain values to be submitted:

1
2
Field::inst( 'group' )
    ->validator( Validate::values( array('CSM''FTA''KFVC') ) )

The following shows a complete Editor example with validation methods applied:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ditor::inst( $db'staff' )
    ->fields(
        Field::inst( 'first_name' )
            ->validator( Validate::notEmpty( ValidateOptions::inst()
                ->message( 'A first name is required' )
            ) ),
        Field::inst( 'last_name' )
            ->validator( Validate::notEmpty( ValidateOptions::inst()
                ->message( 'A last name is required' 
            ) ),
        Field::inst( 'position' ),
        Field::inst( 'email' )
            ->validator( Validate::email( ValidateOptions::inst()
                ->message( 'Please enter an e-mail address' )  
            ) ),
        Field::inst( 'office' ),
        Field::inst( 'extn' ),
        Field::inst( 'age' )
            ->validator( Validate::numeric() )
            ->setFormatter( Format::ifEmpty(null) ),
        Field::inst( 'salary' )
            ->validator( Validate::numeric() )
            ->setFormatter( Format::ifEmpty(null) ),
        Field::inst( 'start_date' )
            ->validator( Validate::dateFormat( 'Y-m-d' ) )
            ->getFormatter( Format::dateSqlToFormat( 'Y-m-d' ) )
            ->setFormatter( Format::dateFormatToSql('Y-m-d' ) )
    )
    ->process( $_POST )
    ->json();

Global validators

You may also find it useful to be able to define a global validator that will execute whenever a request is made to the server and the Editor->process() method is executed. This method can be used to provide security access restrictions, validate input data as a whole or even to check that a user is logged in before processing the request.

Function

The function that is given to the Editor->validator() method has the following signature:

  1. $editor - The Editor instance that the function is being executed for.
  2. $action - The action being performed - this will be one of:
    • Editor::ACTION_READ - Read / get data
    • Editor::ACTION_CREATE - Create a new record
    • Editor::ACTION_EDIT - Edit existing data
    • Editor::ACTION_DELETE - Delete existing row(s)
    • Editor::ACTION_UPLOAD - Upload a file.
  3. $data - The data submitted by the client.

The return value from the function should be a string if the validation fails, where the string returned is the error message to show the end user. If the validation passes, return an empty string, null or simply have no return statement.

Note that this function is executed only once when the Editor->process() method is called, rather than once per submitted row.

Examples

1
2
3
4
5
6
7
8
9
10
// Allow read only access based on a session variable
Editor::inst( $db'table' )
    ->fields( ... )
    ->validator( function $editor$action$data ) {
        if $action !== Editor::ACTION_READ && $_SESSION['read_only'] ) {
            return 'Cannot modify data';
        }
    } )
    ->process( $_POST )
    ->json();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Create and edit with dependent validation
Editor::inst( $db'table' )
    ->fields( ... )
    ->validator( function $editor$action$data ) {
        if $action === Editor::ACTION_CREATE || $action === Editor::ACTION_EDIT ) {
            foreach $data['data'as $pkey => $values ) {
                if $values['country'] === 'US' && $values['location'] === 'London UK' ) {
                    return 'London UK is not in the US';
                }
            }
        }
    } )
    ->process( $_POST )
    ->json();

PHP API documentation

The PHP API developer documentation for the Editor PHP classes is available for detailed and technical discussion about the methods and classes discussed above.

257

主題

38

回帖

1138

積分

管理員

積分
1138
 樓主| 發表於 2023-5-25 11:08:05 | 顯示全部樓層

驗證

驗證數據是CRUD應用程序的一個基本重要方面。您需要確保客戶端發送給您的數據符合您的預期。這不僅是出於安全原因,保護您的數據免遭濫用和故意破壞,而且還僅僅是因為提交數據時出現了無意的錯誤。限制為特定長度的字符串,特定格式的日期和必填字段都是數據驗證的常用用法。

Editor PHP庫提供了兩種不同的驗證方法:

  • 基於字段,提交的每個單獨值都經過獨立驗證:Field->validator()
  • 全局驗證,客戶端提交的數據可以作為一個整體進行驗證:Editor->validator()

字段驗證是您最常使用的字段驗證 - 例如,檢查電子郵件地址字段實際上是否包含電子郵件地址,而編輯器為最常見的數據類型提供了許多可立即使用的驗證器以及能夠指定你自己的。在檢查現有數據集中的字段和衝突之間的依賴關係時,全局驗證非常有用。

現場驗證

編輯器PHP庫為提供了一種validator()方法,Field類中的許多預構建驗證方法提供了方法Validate這些驗證方法中的每一個都返回一個函數,該函數在驗證提交的數據時需要執行。

請考慮以下示例 - 該Validate::minNum()函數配置了一個數字,並返回一個可用於字段驗證器的函數。

1
2
Field::inst("age")
    ->validator(Validate::minNum( 16 ));

請參閱下面的更多詳細示例。

驗證選項

Validation提供的每個驗證方法都可以選擇接受參數來告訴它如何驗證數據(例如,該minLen方法將接受一個整數來指示可接受字符串的最小長度),但是所有這些都可以選擇接受一個ValidateOptions類實例。此類定義了所有驗證方法之間共享的許多選項。

ValidateOptions類構造有ValidateOptions::inst()(或new ValidateOptions()在PHP 5.4+)類似於其他編輯器類。它有三種方法可用於改變驗證行為:

  • ->allowEmpty( boolean ):如何處理空數據(即零長度字符串):
    • true (默認) - 允許字段的輸入為零長度
    • false - 禁止零長度輸入
  • ->message( string ):驗證失敗時顯示的錯誤消息。默認情況下,這只是“輸入無效”,因此您可能希望根據自己的需要進行自定義。
  • ->optional( boolean ):要求提交字段或不提交。此選項在編輯器中特別有用,因為編輯器不會為尚未提交的字段設置值 - 只能提交部分選項列表。
    • true (默認) - 該字段不需要位於客戶端發送的參數列表中。
    • false - 該字段必須包含在客戶提交的數據中。

示例 - 設置自定義錯誤消息

1
2
3
4
6
Field::inst( "stock_name" )
    ->validator( Validate::minNum(
        10,
        new ValidateOptions::inst()
            ->message( 'Stock name must be at least 10 characters long' )
    ) );

多個驗證器

將多個驗證器一起使用通常很有用,例如確認輸入字符串少於一定數量的字符,並且它在數據庫中是唯一的。只需Field->validator()多次調用該方法即可將多個驗證器添加到字段中它實際上將它們加在一起,而不是覆蓋先前的驗證器。它們按照添加的順序運行,並且所有驗證器必須通過才能接受數據作為有效數據。

作為示例,請考慮以下代碼,該代碼將檢查數據的最小和最大長度,以及它是唯一的:

1
2
3
4
Field::inst( 'stock_name' )
    ->validator( Validate::minLen( 10 ) )
    ->validator( Validate::maxLen( 12 ) )
    ->validator( Validate::unique() );

準備使用現場驗證器

Validate編輯器PHP庫中類有許多方法可用於非常快速和輕鬆地執行驗證。這些是:

基本

  • none( ValidateOptions $cfg=null ) - 未執行驗證
  • basic( ValidateOptions $cfg=null)- 基本驗證 - 僅ValidateOptions執行提供的驗證
  • required( ValidateOptions $cfg=null) - 必須提交字段,且數據長度不得為零。請注意,編輯器可以選擇不提交所有字段(例如,在內聯編輯時),因此notEmpty()建議使用驗證器。
  • notEmpty( ValidateOptions $cfg=null) - 不需要提交字段,但如果是,則不能包含零長度數據
  • boolean( ValidateOptions $cfg=null) - 檢查是否已提交布爾數據(包括1,true on,yes,0,false,off和no)

數字

  • numeric( string $decimalChar=".", ValidateOptions $cfg=null) - 檢查任何輸入是否為數字。
  • minNum( integer $min, string $decimalChar=".", ValidateOptions $cfg=null) - 數字輸入大於或等於給定數字
  • maxNum( integer $max, string $decimalChar=".", ValidateOptions $cfg=null) - 數字輸入小於或等於給定數字
  • minMaxNum( integer $min, integer $max, string $decimalChar=".", ValidateOptions $cfg=null) - 數字輸入在給定範圍內(包括)

字符串

  • email( ValidateOptions $cfg=null) - 將輸入驗證為電子郵件地址。
  • ip( ValidateOptions $cfg=null) - 驗證為IP地址。
  • minLen( integer $min, ValidateOptions $cfg=null) - 驗證字符串是否具有最小長度。
  • maxLen( integer $max, ValidateOptions $cfg=null) - 驗證字符串不超過最大長度。
  • minMaxLen( integer $min, integer $max, ValidateOptions $cfg=null) - 驗證字符串在一定範圍內具有給定長度
  • noTags( ValidateOptions $cfg=null) - 不允許HTML標記
  • url( ValidateOptions $cfg=null) - 驗證為URL地址。
  • values(array $values, ValidateOptions $cfg=null) - 僅允許在選項數組中指定的值(第一個參數)。如果您希望將自由格式輸入或事件作為選擇列表,並且想要確認提交的值是否在給定數據集內,則這可能很有用(dbValues()如果有效值存儲在數據庫中,請參閱方法)。請注意,values數組中給出的值將根據提交的數據作為區分大小寫的數據進行檢查(即“A”!=“a”)。
  • xss( ValidateOptions $cfg=null)- 檢查輸入是否包含XSS攻擊這使用了FieldXSS格式化函數來確定輸入字符串是否需要格式化。

約會時間

  • dateFormat( string $format, ValidateOptions $cfg=null) - 檢查是否給出了有效的日期輸入。格式由PHP的date()方法定義,該方法用於解析日期和時間字符串。

數據庫

  • dbValues( ValidateOptions $cfg=null, string $column=null, string $table=null, Database $db=null, array $valid=null) - 僅允許數據庫列中存在的值。這是專門為連接表使用而設計的(即確保在使用之前存在引用行),但它也可能用於需要引用完整性的其他情況。
  • unique( ValidateOptions $cfg=null, string $column=null, string $table=null, array $db=null) - 確保提交的數據在表格列中是唯一的。

自定義字段驗證器

如果上面提供的方法不適合您正在尋找的驗證類型,則絕對可以提供自定義驗證方法。validator()現場方法將接受返回任一功能true或一字符串並接受以下輸入參數:

  1. value - 要驗證的值
  2. data - 相關行的數據集合
  3. field- 主機Field實例
  4. host- 有關主機Editor實例的信息

返回值應該true表示傳遞了validate,或者如果驗證失敗則返回包含錯誤消息的字符串。

以下簡單示例顯示瞭如何maxLen使用自定義驗證方法實現字符串檢查:

1
2
3
4
6
Field::inst( 'last_name' )
    ->validator( function $val$data$field$host ) {
        return strlen$val ) > 50 ?
            'Name length must be 50 characters or less' :
            true;
    } );

現場驗證示例

使用此Validation.minNum()方法將輸入驗證為數字且大於或等於給定數字(未指定驗證選項,因此使用默認值):

1
2
3
// Simple non-empty field
Field::inst( 'age' )
    ->validator( Validate::minNum( 16 ) )

如上所述,但ValidateOptions用於設置錯誤消息:

1
2
3
4
6
7
// Number range check with custom error message
Field::inst( 'range' )
    ->validator( Validate::minNum(
        16,
        ValidateOptions::inst()
            ->message( 'Minimum age is 16' )
    ) );

這次驗證一個不能為空的電子郵件地址,必須提交:

1
2
3
4
6
Field::inst( 'email' )
    ->validator( Validate::email(
        ValidateOptions::inst()
            ->allowEmpty( false )
            ->optional( false )
    ) );

與之dbValues接受的連接將接受一個空值,該值存儲null在數據庫中:

1
2
3
4
6
7
Field::inst( 'users.site' )
    ->options( Options::inst()
        ->table( 'sites' )
        ->value( 'id' )
        ->label( 'name' )
    )
    ->validator( Validate::dbValues() ),

僅允許提交特定值:

1
2
Field::inst( 'group' )
    ->validator( Validate::values( array('CSM''FTA''KFVC') ) )

以下顯示了應用驗證方法的完整編輯器示例:

1
2
3
4
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
三十
ditor::inst( $db'staff' )
    ->fields(
        Field::inst( 'first_name' )
            ->validator( Validate::notEmpty( ValidateOptions::inst()
                ->message( 'A first name is required' )
            ) ),
        Field::inst( 'last_name' )
            ->validator( Validate::notEmpty( ValidateOptions::inst()
                ->message( 'A last name is required' 
            ) ),
        Field::inst( 'position' ),
        Field::inst( 'email' )
            ->validator( Validate::email( ValidateOptions::inst()
                ->message( 'Please enter an e-mail address' )  
            ) ),
        Field::inst( 'office' ),
        Field::inst( 'extn' ),
        Field::inst( 'age' )
            ->validator( Validate::numeric() )
            ->setFormatter( Format::ifEmpty(null) ),
        Field::inst( 'salary' )
            ->validator( Validate::numeric() )
            ->setFormatter( Format::ifEmpty(null) ),
        Field::inst( 'start_date' )
            ->validator( Validate::dateFormat( 'Y-m-d' ) )
            ->getFormatter( Format::dateSqlToFormat( 'Y-m-d' ) )
            ->setFormatter( Format::dateFormatToSql('Y-m-d' ) )
    )
    ->process( $_POST )
    ->json();

全球驗證人員

您還可能會發現,只要向服務器發出請求並Editor->process()執行方法,就可以定義一個全局驗證器此方法可用於提供安全訪問限制,整體驗證輸入數據,甚至可在處理請求之前檢查用戶是否已登錄。

功能

給該Editor->validator()方法的函數具有以下簽名:

  1. $editor - 正在執行該函數的Editor實例。
  2. $action - 正在執行的操作 - 這將是以下之一:
    • Editor::ACTION_READ - 讀取/獲取數據
    • Editor::ACTION_CREATE - 創建新記錄
    • Editor::ACTION_EDIT - 編輯現有數據
    • Editor::ACTION_DELETE - 刪除現有行
    • Editor::ACTION_UPLOAD - 上傳一個文件。
  3. $data - 客戶提交的數據。

如果驗證失敗,函數的返回值應為字符串,返回的字符串是顯示最終用戶的錯誤消息。如果驗證通過,則返回空字符串,null或者只是沒有return語句。

請注意,此函數僅在Editor->process()調用方法時執行一次,而不是每個提交的行執行一次

例子

1
2
3
4
6
7
8
9
10
// Allow read only access based on a session variable
Editor::inst( $db'table' )
    ->fields( ... )
    ->validator( function $editor$action$data ) {
        if $action !== Editor::ACTION_READ && $_SESSION['read_only'] ) {
            return 'Cannot modify data';
        }
    } )
    ->process( $_POST )
    ->json();
1
2
3
4
6
7
8
9
10
11
12
13
14
// Create and edit with dependent validation
Editor::inst( $db'table' )
    ->fields( ... )
    ->validator( function $editor$action$data ) {
        if $action === Editor::ACTION_CREATE || $action === Editor::ACTION_EDIT ) {
            foreach $data['data'as $pkey => $values ) {
                if $values['country'] === 'US' && $values['location'] === 'London UK' ) {
                    return 'London UK is not in the US';
                }
            }
        }
    } )
    ->process( $_POST )
    ->json();

PHP API文檔

編輯PHP類PHP API開發人員文檔可用於有關上述方法和類的詳細和技術討論。

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

Archiver|手機版|小黑屋|DoIT 科技論壇

GMT+8, 2025-6-16 04:46 , Processed in 0.030631 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回復 返回頂部 返回列表