2011-05-02 2 views
3

У меня есть простой сценарий входа с использованием Perl WWW :: Mechanize. Я использую скрипты для входа в систему Moodle. Когда я просто выполняю шаги входа в систему как процедурные шаги, он работает. Например (предположит, что «$ SITE_URL», имя пользователя и пароль был установлен соответствующим образом):Perl WWW :: Механизировать как дочерний класс; не может оставаться включенным на очищенный сайт

#THIS WORKS 
$updater->get("http://".$site_url."/login/index.php"); 
$updater->form_id("login"); 
$updater->field('username', USERNAME); 
$updater->field('password', PASSWORD); 
$updater->click(); 
$updater->get("http://".$site_url."/"); 
print $updater->content(); 

Когда я пытаюсь инкапсулировать эти шаги внутри класса ребенка WWW: Механизируйте, ГЮТ() и содержание() и другие методы, похоже, работают, но войти на сайт не работает. У меня такое чувство, что оно связано с переменной областью видимости, но я не знаю, как ее разрешить.

Пример (сбой):

my $updater = new AutoUpdater($site_url, USERNAME, PASSWORD); 
$updater->do_login(); 

{ 
package AutoUpdater; 
use base qw(WWW::Mechanize); 

sub new { 
    my $class = shift; 
    my $self = { 
     site_url => shift, 
     USERNAME => shift, 
     PASSWORD => shift, 
    }; 
    bless $self, $class; 
    return $self; 
} 

sub do_login { 
    my $self = shift; 
    $self->get("http://".$site_url."/"); 
    $self->get("http://".$site_url."/login/index.php"); 
    $self->form_id("login"); 
    $self->field("username", $self->{USERNAME}); 
    $self->field("password", $self->{PASSWORD}); 
    $self->click(); 
    $self->get("http://".$site_url."/"); 
    print $self->content(); 
} 
} 

Это терпит неудачу. «Fail» означает, что он не входит в систему. Однако он захватывает веб-страницу, и я могу манипулировать данными HTML. Он просто не входит. Ягр! (Да, «yargh» был необходим)

Спасибо!

+0

Что-то с печеньем возможно? Сделайте некоторые работы с cookie_jar – snoofkin

+0

Кроме того, просто предложение, если вы хотите использовать OO в Perl, используйте Moose, он будет делать магию. – snoofkin

ответ

2

Вот пересмотренная версия:

use strict; 
use warnings; 

my $updater = AutoUpdater->new($site_url, USERNAME, PASSWORD); 
$updater->do_login(); 

{ 
package AutoUpdater; 
use parent qw(WWW::Mechanize); 

sub new { 
    my $class = shift; 

    my $self = $class->SUPER::new(); 

    $self->{AutoUpdater} = { 
    site_url => shift, 
    USERNAME => shift, 
    PASSWORD => shift, 
    }; 

    return $self; 
} 

sub do_login { 
    my $self = shift; 
    my $data = $self->{AutoUpdater}; 

    $self->get("http://$data->{site_url}/login/index.php"); 
    $self->form_id("login"); 
    $self->field("username", $data->{USERNAME}); 
    $self->field("password", $data->{PASSWORD}); 
    $self->click(); 
    $self->get("http://$data->{site_url}/"); 
    print $self->content(); 
} 
} # end package AutoUpdater 

Некоторые примечания:

Вы должны всегда использовать strict и warnings, чтобы помочь поймать ваши ошибки.

Непрямой синтаксис объекта не рекомендуется. Используйте Class->new вместо new Class.

У прагмы base есть некоторые нежелательные эффекты, которые не могут быть исправлены по соображениям обратной совместимости. Для его замены была разработана прагма parent.

Ваша большая проблема заключалась в том, что Perl автоматически не инициализирует базовые классы. Вы должны явно позвонить $class->SUPER::new, если необходимо.

Другой важной проблемой было понимание того, как обрабатываются данные экземпляра объекта. Большинство объектов Perl являются hashrefs, и вы получаете доступ к данным экземпляра, используя синтаксис hashref. При подклассификации класса, который я не писал, мне нравится использовать второй hashref, чтобы избежать конфликтов с родительским классом. Помните, что вы делите объект с базовыми классами. Если ваш подкласс использует поле site_url, а затем более поздняя версия базового класса начнет использовать site_url для чего-то еще, ваш код внезапно сломается без видимой причины. Используя только один ключ в базовом объекте hashref (и тот, который базовый класс вряд ли начнет использовать), вы минимизируете вероятность поломки в будущем.

В то время как Moose предоставляет некоторые интересные функции для программирования OO Perl, если вы просто пишете довольно простой подкласс класса, отличного от Moose, вероятно, лучше его избегать.

+0

OMG, спасибо. Вы ответили не только на мой основной вопрос, но и на 5 вторичных небольших вопросов, которые у меня были. Я не использовал Perl в то время, и моя мышца Perl довольно вялая. Извините, это получилось не так, но вы понимаете, я уверен. О, также, я использовал «строгие» и «предупреждения» - я просто не включил это в фрагмент кода вместе с некоторыми другими материалами преамбулы, которые я забыл. – JDS

+0

Итак, у нас возникли новые вопросы.Любая информация/Docs/URL,/и т.д. по этой части: "$ самостоятельно -> {AutoUpdater} = {..." ... И позже использовать его ... «мой $ данных = $ самостоятельно -> {AutoUpdater};» Я не понимаю, почему я не могу просто использовать «$ self -> {site_url}» напрямую. Спасибо – JDS

+0

@JDS. Я объяснил, почему я рекомендую в своем ответе '$ self -> {AutoUpdater} {site_url}' вместо '$ self -> {site_url}'. – cjm