Переход от 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 способ объявления глобальной переменной; основной результат очень похож на использование необъявленных глобалов. Однако есть два отличия:

  1. Вы явно заявляете, что хотите, чтобы переменная была глобальной. Это хорошая практика, так как использование глобальных переменных должно быть исключительным случаем. Из-за этого вы можете создать глобальный таким образом, даже если вы use strict;,
  2. Переменная, объявленная с 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 только для особых случаев, подобных показанным выше.

Другие вопросы по тегам