Переход от CGI к mod_perl. Понимание моего, нашего, местного
Я использую apache mod_cgi в течение нескольких лет. Теперь я перехожу к mod_perl и обнаружил некоторые проблемы, особенно с подпрограммами. До сих пор я никогда не использовал my
, our
ни local
; и сценарии CGI работали без проблем. После прочтения документации и даже некоторых предыдущих вопросов, опубликованных здесь, я более или менее понимаю, как my
, our
а также local
работает. Меня беспокоит то, какая информация будет передаваться между следующими запросами (если я правильно понимаю, это главная проблема, которую я должен иметь при запуске mod_perl вместо mod_cgi).
- Есть ли разница между использованием
our
в скаляре или просто скаляре, не объявляя ничего особенного, такого какmy
? Разве это не глобально? - Если я не объявлю скаляр как частный, будет ли делиться в следующем запросе? Даже в другой запрос другого сценария Perl на том же сервере?
- Как я могу поделиться значением скаляра внутри подпрограммы за пределами этой подпрограммы, но не за пределами того же файла или того же запроса?
- Если я использую
my
в скаляре внутриif
в том же уровне файла или в той же подпрограмме, и после этого я создаю другойif
где я использую тот же скаляр; этот скаляр разделен междуif
или каждыйif
значит разные блоки? Как насчетwhile
а такжеfor
Являются ли они различными блоками для ранее объявленного какmy
скаляр или что работает только для подпрограмм и файлов?
2 ответа
mod_perl работает, оборачивая каждый Perl-скрипт в подпрограмму с именем handler
в пакете на основе имени и пути скрипта. Вместо запуска нового процесса для запуска каждого сценария, этот handler
Подпрограмма вызывается одной из множества постоянных теорий Perl.
Обычно эти знания очень помогли бы понять изменения в среде от mod_cgi, но так как вы никогда не добавляли use strict
к вашим программам и ознакомьтесь с работой объявленных переменных, которые вам предстоит наверстать!
Среда mod_perl может привести к неочевидным нарушениям безопасности, и вам следует начать сейчас use strict
на каждом скрипте и объявить каждую переменную. use Carp
также поможет вам понять журналы ошибок.
Имя переменной объявлено с our
является синонимом в лексической области для переменной пакета с тем же именем, которая может использоваться без полной квалификации имени, включая имя пакета. Например, обычно переменная, объявленная с our $var
обеспечит доступ к $main::var
скаляр (если не было предшествующего package
декларация) без указания main::
, Тем не менее, такие переменные, которые начали жизнь со значением undef
в mod_cgi теперь будут сохранять их значения из предыдущего выполнения любого заданного потока mod_perl, и для согласованности безопаснее всегда инициализировать их в точке объявления. Обратите внимание, что имя пакета по умолчанию больше не main
из-за переноса, который делает mod_perl, поэтому вы больше не можете обращаться к переменным пакета, используя main::
префикс, и неразумно находить фактическое имя пакета и явно использовать его, потому что это будет очень длинное имя и изменится, если вы переместите или переименуете свой скрипт.
my
Переменная - это переменная, которая существует независимо от таблицы символов пакета, и обычно ее временем жизни является время выполнения включающего файла (для переменных, объявленных в области видимости файла) или подпрограммы. Они безопасны в mod_perl, если оба объявлены и используются в области действия скрипта или полностью внутри одной подпрограммы, но вы можете быть ошарашены, если вы смешаете области действия и объявите my $global
в области видимости файла, а затем попробуйте использовать его в подпрограмме. Причина этого не проста, но она вызвана тем, что mod_perl оборачивает ваш скрипт в handler
подпрограмма, так что вы вложили объявления подпрограммы. Внутренняя подпрограмма будет стремиться принять только первый экземпляр $global
и игнорировать любые другие, созданные последующими звонками handler
, Если вам нужна глобальная переменная, вы должны объявить ее с our
и инициализировать его в этом объявлении, как описано выше.
local
переменная очень похожа на our
переменная в том, что она образует синоним переменной пакета. Однако он временно сохраняет текущее значение этой переменной и предоставляет новую копию для использования до конца области файла или блока. Из-за его автоматического создания и удаления в пределах своей области он может быть полезной альтернативой my
переменная в скриптах mod_perl, особенно там, где вы используете указатели на структуры данных, такие как, например, экземпляр CGI
учебный класс. декларирование our $cgi = CGI->new
правильно создал бы объект, но из-за постоянства mod_perl оставил бы его в памяти, пока следующее выполнение потока не удалит его, чтобы освободить место для другого.
Что касается ваших вопросов:
Использование переменной без объявления либо приводит к ошибке времени компиляции, если
use strict
на месте, как и должно быть. В противном случае это синоним этой переменной в пространстве имен текущего пакета.Переменные являются либо пакетными переменными, либо лексическими переменными; нет способа объявить переменную закрытой как таковой. Лексические переменные (объявлены с
my
) будет создаваться и уничтожаться при каждом выполнении сценария, если только вы не создали недопустимое закрытие, как описано выше, написав подпрограмму, которая использует переменную, объявленную в более широкой области действия, когда переменная будет постоянной, но не будет делать то, что вы хочу этого. Переменная, объявленная сour
сохранит свое значение при вызовах скрипта, в то время как один объявлен сlocal
будет уничтожен, когда скрипт завершится. И то и другоеour
а такжеlocal
переменные являются пакетными переменными, и все ссылки на одно и то же имя переменной ссылаются на одну и ту же переменную.Чтобы объявить переменную, которая всегда доступна везде в любом вызове скрипта, вы можете использовать
local
переменная или инициализированныйour
переменная. На уровне файлаlocal $global
в значительной степени эквивалентноour $global = undef
для скриптов mod_perl. Если вы используетеour
переменная, чтобы указать на структуру данных, затем не забудьте уничтожить ее в конце скрипта сundef $global
,my
переменные являются уникальными и видимыми внутри блока, в котором они объявлены, независимо от того, является ли он блоком внутриif
,while
или жеfor
или даже просто голый{ ... }
блокировать область. Всегда используйтеmy
переменные для временных рабочих переменных, которые используются только внутри блока и доступны из ниоткуда.
надеюсь, это поможет
Редактировать: это общая информация только по области видимости переменной Perl. Пожалуйста, смотрите пост Бородина для конкретных mod_perl
проблемы.
Переменные, объявленные с my
лексические. Другими словами, они существуют только в пределах текущей области. Вы должны объявить все свои переменные с my
по умолчанию; делайте что-то еще, только когда вам конкретно нужен другой функционал.
Использование переменных с лексической областью является основной частью хорошего дизайна кода практически на любом языке. Ввод use strict;
а также use warnings;
во всех ваших сценариях от вас потребуется следовать этой хорошей практике.
our
способ объявления глобальной переменной; основной результат очень похож на использование необъявленных глобалов. Однако есть два отличия:
- Вы явно заявляете, что хотите, чтобы переменная была глобальной. Это хорошая практика, так как использование глобальных переменных должно быть исключительным случаем. Из-за этого вы можете создать глобальный таким образом, даже если вы
use strict;
, - Переменная, объявленная с
our
будет доступен по названию, которое вы объявляете во всех пакетах в текущей области. Необъявленная переменная, напротив, доступна только по простому имени в текущем пакете. Помимо этого, вы можете ссылаться только на это как$package::variable
,
Смотрите документацию для our
Больше подробностей.
local
не создает лексическую переменную; вместо этого это способ дать глобальной переменной временное значение в текущей области видимости. В основном он используется со специальными встроенными (пунктуальными) переменными Perl:
{
local $/; #make the record separator undefined in this scope only.
my $file = <FILE>; #read in an entire file at once.
}
Вы можете пойти далеко, просто используя my
всегда для ваших переменных и использования local
только для особых случаев, подобных показанным выше.