Bao gồm hằng trong chuỗi mà không nối


166

Có cách nào trong PHP để bao gồm một hằng trong một chuỗi mà không nối không?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";

12
Trực giác nói với tôi rằng "Đây là hằng số của tôi: {MY_CONSTANT}" sẽ hoạt động. Nó không. Chỉ cần đặt cái này ở đây trong trường hợp ai đó nghĩ giống như tôi
Mikael Lindqvist

Câu trả lời:


148

Không.

Với String, PHP không có cách nào để phân biệt dữ liệu chuỗi ngoài các định danh không đổi. Điều này áp dụng cho bất kỳ định dạng chuỗi nào trong PHP, bao gồm cả heredoc.

constant() là một cách khác để có được một hằng số, nhưng một lệnh gọi hàm không thể được đặt thành một chuỗi mà không cần nối.

Hướng dẫn về hằng số trong PHP


1
Dù sao +1 cũng chắc chắn là câu trả lời đúng. Đầu tiên tôi muốn viết giống như bạn, nhưng sau khi đọc của bạn, tôi nghĩ rằng tôi phải trình bày một cái gì đó khác biệt;)
Felix Kling

3
Hehe! Nhưng một +1 xứng đáng cho mọi người cho sự sáng tạo. :)
Pekka

59
"chức năng gọi không thể được đặt thành một chuỗi" có, nó có thể:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren

1
@Raveren, trong khi các ứng dụng khác cung cấp các biến thể gián tiếp, tạo các hàm không cần thiết, thì các hàm của bạn là giải pháp ngắn nhất và dựa trên các hàm biến, tính năng được đánh giá thấp và rất ít được sử dụng của PHP. Trong toàn bộ chủ đề này, tôi đã đi với giải pháp cụ thể CỦA BẠN. Tôi ước tôi có thể +1 nó nhiều lần.
hndcrftd

4
Tôi chỉ chỉ ra rằng nó có thể, không bình luận về cách nào là tốt hơn.
raveren

111

Vâng, đó là (theo một cách nào đó;)):

define('FOO', 'bar');

$test_string = sprintf('This is a %s test string', FOO);

Đây có lẽ không phải là những gì bạn đang hướng tới, nhưng tôi nghĩ, về mặt kỹ thuật, đây không phải là sự kết hợp mà là sự thay thế và từ giả định này, nó bao gồm một hằng số trong một chuỗi mà không cần nối .


5
@Pekka: Tôi biết :-D (chỉ trong thời gian này ...;))
Felix Kling

1
Cách tiếp cận của :) @ Juraj.blahunka thậm chí còn lén lút hơn. Nó trả lời câu hỏi bằng thư, nhưng không phải tinh thần của nó. :)
Pekka

2
@blahunka: phương châm tốt đẹp. Chúng tôi có thể sử dụng nó hàng ngày
Alfabravo

57

Để sử dụng hằng trong chuỗi, bạn có thể sử dụng phương pháp sau:

define( 'ANIMAL', 'turtles' ); 
$constant = 'constant';

echo "I like {$constant('ANIMAL')}";


Cái này hoạt động ra sao?

Bạn có thể sử dụng bất kỳ tên hàm chuỗi và tham số tùy ý

Người ta có thể đặt bất kỳ tên hàm nào trong một biến và gọi nó với các tham số bên trong một chuỗi trích dẫn kép. Hoạt động với nhiều tham số quá.

$fn = 'substr';

echo "I like {$fn('turtles!', 0, -1)}";

Sản xuất

tôi thích rùa

Chức năng ẩn danh quá

Bạn cũng có thể sử dụng các hàm ẩn danh với điều kiện bạn đang chạy PHP 5.3+.

$escape   = function ( $string ) {
    return htmlspecialchars( (string) $string, ENT_QUOTES, 'utf-8' );
};
$userText = "<script>alert('xss')</script>";
echo( "You entered {$escape( $userText )}" );

Sản xuất thoát html đúng như mong đợi.

Mảng gọi lại không được phép!

Nếu bây giờ bạn có ấn tượng rằng tên hàm có thể gọi được, thì đó không phải là trường hợp, vì một mảng trả về true khi được truyền vào is_callablesẽ gây ra lỗi nghiêm trọng khi được sử dụng bên trong chuỗi:

class Arr
{

    public static function get( $array, $key, $default = null )
    {
        return is_array( $array ) && array_key_exists( $key, $array ) 
            ? $array[$key] 
            : $default;
    }
}

$fn = array( 'Arr', 'get' );
var_dump( is_callable( $fn ) ); // outputs TRUE

// following line throws Fatal error "Function name must be a string"
echo( "asd {$fn( array( 1 ), 0 )}" ); 

Ghi nhớ

Cách làm này không được khuyến khích, nhưng đôi khi dẫn đến mã dễ đọc hơn nhiều, do đó tùy thuộc vào bạn - khả năng là có.


1
Đây là một mẹo hay! Giống như các câu trả lời khác, không thực sự là một chiến thắng lớn về sự kết hợp về mặt nỗ lực và khả năng đọc, nhưng thật tuyệt khi biết. Nó thậm chí còn quyến rũ hơn khi bạn làm một cái gì đó như $_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}". Phiên bản của Thetaiko loại bỏ sự cần thiết của dấu ngoặc kép và dấu gạch dưới rất dễ thương.
Beejor

2
Tôi có thể thấy điều này hữu ích cho việc xây dựng một công cụ mẫu, nhưng có vẻ như quá lén lút để thực sự sử dụng.
Mnebuerquo

21
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";

4
Đây là cái tôi sử dụng nhiều nhất, khi tôi có một chuỗi các chuỗi SQL điên để soạn. Còn ... thụ động-hung hăng nhiều? ;-)
Beejor

2
Cái này có ít ma thuật nhất, với chi phí tìm kiếm dư thừa
BrDaHa

Giải pháp tuyệt vời. Đơn giản và nhanh chóng.
Roger Hill

14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";

13

Nếu bạn thực sự muốn lặp lại hằng số mà không cần nối thì đây là giải pháp:

define('MY_CONST', 300);
echo 'here: ', MY_CONST, ' is a number';

lưu ý : trong ví dụ này, echo có một số tham số ( nhìn vào dấu phẩy ), vì vậy nó không phải là nối thực sự

Echo hoạt động như một hàm, cần nhiều tham số hơn, hiệu quả hơn so với ghép, bởi vì nó không phải nối và sau đó lặp lại, nó chỉ lặp lại mọi thứ mà không cần tạo đối tượng nối chuỗi mới :))

BIÊN TẬP

Ngoài ra nếu bạn xem xét concatenating chuỗi, passings chuỗi như thông số hoặc viết toàn bộ chuỗi với "The , (dấu phẩy version) luôn được nhanh nhất, tiếp theo đi . (Nối với ' dấu nháy đơn) và chuỗi chậm nhất phương pháp xây dựng đang sử dụng dấu ngoặc kép " , bởi vì các biểu thức được viết theo cách này phải được đánh giá theo các biến và hàm được khai báo ..


11

Bạn có thể làm:

define( 'FOO', 'bar' );

$constants = get_defined_constants(true); // the true argument categorizes the constants
$constants = $constants[ 'user' ]; // this gets only user-defined constants

echo "Hello, my name is {$constants['FOO']}";

6

Cách dễ nhất là

define('MY_CONSTANT', 42);

$my_constant = MY_CONSTANT;
echo "This is my constant: $my_constant";

Một cách khác sử dụng (s)printf

define('MY_CONSTANT', 42);

// Note that %d is for numeric values. Use %s when constant is a string    
printf('This is my constant: %d', MY_CONSTANT);

// Or if you want to use the string.

$my_string = sprintf('This is my constant: %d', MY_CONSTANT);
echo $my_string;

Tôi coi đây là một giải pháp tốt. Trong một số trường hợp, chuỗi kết nối sẽ không hoạt động nếu sử dụng CONSTANT trực tiếp bên trong.
kta

5

Như những người khác đã chỉ ra rằng bạn không thể làm điều đó. PHP có một chức năng constant()không thể được gọi trực tiếp trong một chuỗi nhưng chúng ta có thể dễ dàng làm việc xung quanh vấn đề này.

$constant = function($cons){
   return constant($cons);
};

và một ví dụ cơ bản về cách sử dụng của nó:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 

Bạn chỉ có thể làm $constant = 'constant';thay vì xác định chức năng khác và nó sẽ hoạt động giống hệt vì chức năng đó đã tồn tại.
trả lại

2

Dưới đây là một số lựa chọn thay thế cho các câu trả lời khác, dường như chủ yếu tập trung vào thủ thuật "{$}". Mặc dù không có đảm bảo nào được thực hiện về tốc độ của chúng; Đây là tất cả đường cú pháp tinh khiết. Đối với những ví dụ này, chúng tôi sẽ giả sử tập hợp các hằng số bên dưới được xác định.

define( 'BREAD', 'bread' ); define( 'EGGS', 'eggs' ); define( 'MILK', 'milk' );

Sử dụng trích xuất ()
Cái này là tốt vì kết quả là giống hệt với các biến. Đầu tiên bạn tạo một chức năng có thể sử dụng lại:

function constants(){ return array_change_key_case( get_defined_constants( true )[ 'user' ] ); }

Sau đó gọi nó từ bất kỳ phạm vi:

extract( constants() );
$s = "I need to buy $bread, $eggs, and $milk from the store.";

Ở đây, nó viết thường các hằng số để dễ dàng hơn trên ngón tay của bạn, nhưng bạn có thể xóa mảng_change_key_case () để giữ nguyên trạng. Nếu bạn đã có xung đột tên biến cục bộ, hằng số sẽ không ghi đè chúng.

Sử dụng thay thế chuỗi
Cái này tương tự như sprintf (), nhưng sử dụng một mã thông báo thay thế duy nhất và chấp nhận số lượng đối số không giới hạn. Tôi chắc chắn có nhiều cách tốt hơn để làm điều này, nhưng hãy tha thứ cho sự vụng về của tôi và cố gắng tập trung vào ý tưởng đằng sau nó.

Giống như trước đây, bạn tạo một chức năng có thể sử dụng lại:

function fill(){
    $arr = func_get_args(); $s = $arr[ 0 ]; array_shift( $arr );
    while( strpos( $s, '/' ) !== false ){
        $s = implode( current( $arr ), explode( '/', $s, 2 ) ); next( $arr );
    } return $s;
}

Sau đó gọi nó từ bất kỳ phạm vi:

$s = fill( 'I need to buy /, /, and / from the store.', BREAD, EGGS, MILK );

Bạn có thể sử dụng bất kỳ mã thông báo thay thế nào bạn muốn, như% hoặc #. Tôi đã sử dụng dấu gạch chéo ở đây vì nó dễ gõ hơn một chút.


0

Thật thú vị khi bạn có thể sử dụng từ khóa 'const' làm tên cho chức năng của mình để ngăn chặn việc xả rác không gian tên:

define("FOO","foo");
${'const'} = function($a){return $a;};
echo "{$const(FOO)}"; // Prints "foo"
echo const(FOO); // Parse error: syntax error, unexpected T_CONST

Bạn cũng có thể sử dụng $ GLOBALS để truyền bá chức năng 'const' trên toàn bộ mã:

$GLOBALS['const'] = function($a){return $a;};

Không chắc chắn là nó an toàn cho việc sử dụng trong tương lai. Và điều tồi tệ hơn - nó vẫn trông xấu xí.


-2

Tôi tin rằng điều này trả lời câu hỏi ban đầu của OP. Điều duy nhất là khóa chỉ mục toàn cầu dường như chỉ hoạt động như chữ thường.

define('DB_USER','root');
echo "DB_USER=$GLOBALS[db_user]";

Đầu ra:

DB_USER=root

1
Điều này dường như không hoạt động (ngay cả khi bạn sử dụng chữ hoa liên tiếp) $ GLOBALS là an associative array containing references to all variables.
har-wradim

Câu trả lời này là sai. cách duy nhất mà điều này có thể tạo ra đầu ra đó là nếu ở đâu đó trong kịch bản của bạn, bạn cũng có$db_user = 'root';
Jeff Puckett
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.