Php глобальная ссылка this

Область видимости переменной

Область видимости переменной — это контекст, в котором эта переменная определена. В большинстве случаев все переменные PHP имеют только одну область видимости. Эта единая область видимости охватывает также включаемые (include) и требуемые (require) файлы. Например:

Здесь переменная $a будет доступна внутри включенного скрипта b.inc . Однако определение (тело) пользовательской функции задает локальную область видимости данной функции. Любая используемая внутри функции переменная по умолчанию ограничена локальной областью видимости функции. Например:

$a = 1 ; /* глобальная область видимости */

function test ()
<
echo $a ; /* ссылка на переменную локальной области видимости */
>

Этот скрипт не сгенерирует никакого вывода, поскольку выражение echo указывает на локальную версию переменной $a , а в пределах этой области видимости ей не было присвоено значение. Возможно вы заметили, что это немного отличается от языка C в том, что глобальные переменные в C автоматически доступны функциям, если только они не были перезаписаны локальным определением. Это может вызвать некоторые проблемы, поскольку люди могут нечаянно изменить глобальную переменную. В PHP, если глобальная переменная будет использоваться внутри функции, она должна быть объявлена глобальной внутри определения функции.

Ключевое слово global

Сначала пример использования global:

Пример #1 Использование global

function Sum ()
global $a , $b ;

Вышеприведенный скрипт выведет 3. После определения $a и $b внутри функции как global все ссылки на любую из этих переменных будут указывать на их глобальную версию. Не существует никаких ограничений на количество глобальных переменных, которые могут обрабатываться функцией.

Второй способ доступа к переменным глобальной области видимости — использование специального, определяемого PHP массива $GLOBALS . Предыдущий пример может быть переписан так:

Пример #2 Использование $GLOBALS вместо global

function Sum ()
$GLOBALS [ ‘b’ ] = $GLOBALS [ ‘a’ ] + $GLOBALS [ ‘b’ ];
>

$GLOBALS — это ассоциативный массив, ключом которого является имя, а значением — содержимое глобальной переменной. Обратите внимание, что $GLOBALS существует в любой области видимости, это объясняется тем, что $GLOBALS является суперглобальным. Ниже приведен пример, демонстрирующий возможности суперглобальных переменных:

Пример #3 Суперглобальные переменные и область видимости

function test_global ()
// Большинство предопределенных переменных не являются
// «супер», и чтобы быть доступными в локальной области
// видимости, функции требуют указания ‘global’.
global $HTTP_POST_VARS ;

echo $HTTP_POST_VARS [ ‘name’ ];

// Суперглобальные переменные доступны в любой области
// видимости и не требуют указания ‘global’.
// Суперглобальные переменные доступны, начиная с PHP 4.1.0, а
// использование HTTP_POST_VARS считается устаревшим.
echo $_POST [ ‘name’ ];
>
?>

Замечание:

Использование ключевого слова global вне функции не является ошибкой. Оно может быть использовано в файле, которые включается внутрь функции.

Использование статических (static) переменных

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

Пример #4 Демонстрация необходимости статических переменных

Эта функция довольно бесполезна, поскольку при каждом вызове она устанавливает $a в 0 и выводит 0. Инкремент переменной $a ++ здесь не играет роли, так как при выходе из функции переменная $a исчезает. Чтобы написать полезную считающую функцию, которая не будет терять текущего значения счетчика, переменная $a объявляется как static:

Читайте также:  Java jdk path setting

Пример #5 Пример использования статических переменных

Теперь $a будет проинициализирована только при первом вызове функции, а каждый вызов функции test() будет выводить значение $a и инкрементировать его.

Статические переменные также дают возможность работать с рекурсивными функциями. Рекурсивной является функция, вызывающая саму себя. При написании рекурсивной функции нужно быть внимательным, поскольку есть вероятность сделать рекурсию бесконечной. Вы должны убедиться, что существует адекватный способ завершения рекурсии. Следующая простая функция рекурсивно считает до 10, используя для определения момента остановки статическую переменную $count :

Пример #6 Статические переменные и рекурсивные функции

Замечание:

Статические переменные могут быть объявлены так, как показано в предыдущем примере. Попытка присвоить этим переменным значения, являющиеся результатом выражений, вызовет ошибку обработки.

Пример #7 Объявление статических переменных

function foo () static $int = 0 ; // верно
static $int = 1 + 2 ; // неверно (поскольку это выражение)
static $int = sqrt ( 121 ); // неверно (поскольку это тоже выражение)

Замечание:

Статические объявления вычисляются во время компиляции скрипта.

Ссылки с глобальными (global) и статическими (static) переменными

Движок Zend Engine 1, лежащий в основе PHP 4, оперирует модификаторами переменных static и global как ссылками. Например, реальная глобальная переменная, внедренная в область видимости функции указанием ключевого слова global, в действительности создает ссылку на глобальную переменную. Это может привести к неожиданному поведению, как это показано в следующем примере:

function test_global_noref () global $obj ;
$obj = new stdclass ;
>

test_global_ref ();
var_dump ( $obj );
test_global_noref ();
var_dump ( $obj );
?>

Результат выполнения данного примера:

Аналогично ведет себя и выражение static. Ссылки не хранятся статично:

echo ‘Статический объект: ‘ ;
var_dump ( $obj );
if (!isset( $obj )) // Присвоить ссылку статической переменной
$obj = &new stdclass ;
>
$obj -> property ++;
return $obj ;
>

echo ‘Статический объект: ‘ ;
var_dump ( $obj );
if (!isset( $obj )) // Присвоить объект статической переменной
$obj = new stdclass ;
>
$obj -> property ++;
return $obj ;
>

$obj1 = get_instance_ref ();
$still_obj1 = get_instance_ref ();
echo «\n» ;
$obj2 = get_instance_noref ();
$still_obj2 = get_instance_noref ();
?>

Результат выполнения данного примера:

Статический объект: NULL
Статический объект: NULL

Статический объект: NULL
Статический объект: object(stdClass)(1) [«property»]=>
int(1)
>

Этот пример демонстрирует, что при присвоении ссылки статической переменной она не запоминается, когда вы вызываете функцию &get_instance_ref() во второй раз.

Источник

Php глобальная ссылка this

points to post below me.
When you’re doing the references with loops, you need to unset($var).

In reply to lars at riisgaardribe dot dk,

When a variable is copied, a reference is used internally until the copy is modified. Therefore you shouldn’t use references at all in your situation as it doesn’t save any memory usage and increases the chance of logic bugs, as you discoved.

I think a correction to my last post is in order.

When there is a constructor, the strange behavior mentioned in my last post doesn’t occur. My guess is that php was treating reftest() as a constructor (maybe because it was the first function?) and running it upon instantiation.

Читайте также:  Windows php command not found

class reftest
public $a = 1 ;
public $c = 1 ;

public function __construct ()
return 0 ;
>

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

In this example class name is different from its first function and however there is no construction function. In the end as you guess «a» and «c» are equal. So if there is no construction function at same time class and its first function names are the same, «a» and «c» doesn’t equal forever. In my opinion php doesn’t seek any function for the construction as long as their names differ from each others.

class reftest_new
<
public $a = 1 ;
public $c = 1 ;

$reference = new reftest_new ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

It matters if you are playing with a reference or with a value

Here we are working with values so working on a reference updates original variable too;

$b++;
echo «$a, $b»;//Output: 2, 2 both values are updated

$b = 10;
echo «$a, $b»;//Output: 10, 10 both values are updated

$b =$c; //This assigns value 2 to $b which also updates $a
echo «$a, $b»;//Output: 22, 22

But, if instead of $b=$c you do
$b = &$c; //Only value of $b is updated, $a still points to 10, $b serves now reference to variable $c

The order in which you reference your variables matters.

echo $a1 ; //Echoes «One»
echo $b1 ; //Echoes «One»

echo $a2 ; //Echoes «Four»
echo $b2 ; //Echoes «Four»
?>

If you set a variable before passing it to a function that takes a variable as a reference, it is much harder (if not impossible) to edit the variable within the function.

foo ( $unset );
echo( $unset );
foo ( $set = «set\n» );
echo( $set );

It baffles me, but there you have it.

In reply to Drewseph using foo($a = ‘set’); where $a is a reference formal parameter.

$a = ‘set’ is an expression. Expressions cannot be passed by reference, don’t you just hate that, I do. If you turn on error reporting for E_NOTICE, you will be told about it.

Resolution: $a = ‘set’; foo($a); this does what you want.

Here’s a good little example of referencing. It was the best way for me to understand, hopefully it can help others.

When using references in a class, you can reference $this-> variables.

class reftest
public $a = 1 ;
public $c = 1 ;

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

However, this doesn’t appear to be completely trustworthy. In some cases, it can act strangely.

class reftest
public $a = 1 ;
public $c = 1 ;

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 3.
echo $reference -> c ; //Echoes 2.
?>

In this second code block, I’ve changed reftest() so that $b increments instead of just gets changed to 2. Somehow, it winds up equaling 3 instead of 2 as it should.

Читайте также:  Http запрос авторизация php

I discovered something today using references in a foreach

echo $a1 [ ‘a’ ]; // will echo b (!)
?>

After reading the manual this looks like it is meant to happen. But it confused me for a few days!

(The solution I used was to turn the second foreach into a reference too)

An interesting if offbeat use for references: Creating an array with an arbitrary number of dimensions.

For example, a function that takes the result set from a database and produces a multidimensional array keyed according to one (or more) columns, which might be useful if you want your result set to be accessible in a hierarchial manner, or even if you just want your results keyed by the values of each row’s primary/unique key fields.

function array_key_by ( $data , $keys , $dupl = false )
/*
* $data — Multidimensional array to be keyed
* $keys — List containing the index/key(s) to use.
* $dupl — How to handle rows containing the same values. TRUE stores it as an Array, FALSE overwrites the previous row.
*
* Returns a multidimensional array indexed by $keys, or NULL if error.
* The number of dimensions is equal to the number of $keys provided (+1 if $dupl=TRUE).
*/
// Sanity check
if (! is_array ( $data )) return null ;

// Allow passing single key as a scalar
if ( is_string ( $keys ) or is_integer ( $keys )) $keys = Array( $keys );
elseif (! is_array ( $keys )) return null ;

// Our output array
$out = Array();

// Loop through each row of our input $data
foreach( $data as $cx => $row ) if ( is_array ( $row ))

// Loop through our $keys
foreach( $keys as $key )
$value = $row [ $key ];

if (!isset( $last )) // First $key only
if (!isset( $out [ $value ])) $out [ $value ] = Array();
$last =& $out ; // Bind $last to $out
>
else // Second and subsequent $key.
if (!isset( $last [ $value ])) $last [ $value ] = Array();
>

if (isset( $last ))
// At this point, copy the $row into our output array
if ( $dupl ) $last [ $cx ] = $row ; // Keep previous
else $last = $row ; // Overwrite previous
>
unset( $last ); // Break the reference
>
else return NULL ;

// A sample result set to test the function with
$data = Array(Array( ‘name’ => ‘row 1’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_a’ , ‘baz’ => ‘baz_a’ ),
Array( ‘name’ => ‘row 2’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_a’ , ‘baz’ => ‘baz_b’ ),
Array( ‘name’ => ‘row 3’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_b’ , ‘baz’ => ‘baz_c’ ),
Array( ‘name’ => ‘row 4’ , ‘foo’ => ‘foo_b’ , ‘bar’ => ‘bar_c’ , ‘baz’ => ‘baz_d’ )
);

// First, let’s key it by one column (result: two-dimensional array)
print_r ( array_key_by ( $data , ‘baz’ ));

// Or, key it by two columns (result: 3-dimensional array)
print_r ( array_key_by ( $data , Array( ‘baz’ , ‘bar’ )));

// We could also key it by three columns (result: 4-dimensional array)
print_r ( array_key_by ( $data , Array( ‘baz’ , ‘bar’ , ‘foo’ )));

Источник

Оцените статью