Sam
Sam

Reputation: 355

Unable to print arguments in perl tk callback

When submit button is clicked, a callback function should be called. printing all arguments passed during callback doesn't work. But it enters callback function. How can I access passed variables so that I can insert into table.

sub registerStu {
    use DBI;
    use strict;
    my $reg = $mw->Toplevel();
    $reg->title("Registration");
    $reg->geometry("500x500+0+0");
    #$button -> grid(-row=>5, -column=>5);
    my $name = $reg->Label( -text => "Name", -width => 20 )->pack( -side => "top" );
    my $ename = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $uid = $reg->Label( -text => "User name", -width => 20 )->pack( -side => "top" );
    my $euid = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $pwd = $reg->Label( -text => "Password", -width => 20 )->pack( -side => "top" );
    my $epwd = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $mail = $reg->Label( -text => "Email", -width => 20 )->pack( -side => "top" );
    my $email = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $dept = $reg->Label( -text => "Department", -width => 20 )->pack( -side => "top" );
    my $edept = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $gname = $ename->get();
    my $guid  = $euid->get();
    my $gpwd  = $epwd->get();
    my $gmail = $email->get();
    my $gdept = $edept->get();
    my $submit = $reg->Button(
        -text    => "Register",
        -command => sub { &InsertStu( $gname, $guid, $gpwd, $gmail, $gdept ); }
    )->pack( -side => "top" );
}

sub InsertStu {
    print "hello";
    print "@_\n";
    my $driver   = "mysql";
    my $database = "course";
    my $dsn      = "DBI:$driver:database=$database";
    my $userid   = "root";
    my $password = "pwd";

    my $dbh = DBI->connect( $dsn, $userid, $password, { AutoCommit => 1 } ) or die $DBI::errstr;
    #my $sth = $dbh->prepare("INSERT into student(sid,name,password,email,dept) values('$guid','$gname','$gpwd','$gmail','$gdept')");
    #$sth->execute() or die $DBI::errstr;
}

Upvotes: 0

Views: 110

Answers (2)

Miller
Miller

Reputation: 35198

You're pulling the values of your text fields prematurely.

# These values aren't set yet, so your callback function will always be
# passed an empty string for each of these values
my $gname = $ename->get();
my $guid  = $euid->get();
my $gpwd  = $epwd->get();
my $gmail = $email->get();
my $gdept = $edept->get();

Instead, pass the text fields to the callback function, so you can then pull the values that are set when the submit button is actually pressed:

sub registerStu {
    use DBI;
    use strict;
    my $reg = $mw->Toplevel();
    $reg->title("Registration");
    $reg->geometry("500x500+0+0");
    #$button -> grid(-row=>5, -column=>5);
    my $name = $reg->Label( -text => "Name", -width => 20 )->pack( -side => "top" );
    my $ename = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $uid = $reg->Label( -text => "User name", -width => 20 )->pack( -side => "top" );
    my $euid = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $pwd = $reg->Label( -text => "Password", -width => 20 )->pack( -side => "top" );
    my $epwd = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $mail = $reg->Label( -text => "Email", -width => 20 )->pack( -side => "top" );
    my $email = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $dept = $reg->Label( -text => "Department", -width => 20 )->pack( -side => "top" );
    my $edept = $reg->Entry( -width => 20, -background => 'white', -foreground => 'black' )->pack( -side => "top" );
    my $submit = $reg->Button(
        -text    => "Register",
        -command => sub { InsertStu( $ename, $euid, $epwd, $email, $edept ); }
    )->pack( -side => "top" );
}

sub InsertStu {
    my ( $ename, $euid, $epwd, $email, $edept ) = @_;

    my $gname = $ename->get();
    my $guid  = $euid->get();
    my $gpwd  = $epwd->get();
    my $gmail = $email->get();
    my $gdept = $edept->get();

    my $driver   = "mysql";
    my $database = "course";
    my $dsn      = "DBI:$driver:database=$database";
    my $userid   = "root";
    my $password = "pwd";

    my $dbh = DBI->connect( $dsn, $userid, $password, { AutoCommit => 1 } ) or die $DBI::errstr;
    my $sth = $dbh->prepare("INSERT into student(sid,name,password,email,dept) values(?,?,?,?,?)");
    $sth->execute( $guid, $gname, $gpwd, $gmail, $gdept ) or die $DBI::errstr;
}

Upvotes: 1

Borodin
Borodin

Reputation: 126722

You should avoid using an ampersand & when calling a Perl subroutine. It does something rather arcane and can be the source of awkward bugs. Just InsertStu($gname, $guid, $gpwd, $gmail, $gdept) is correct.

I presume you're saying that your InsertStu subroutine is printing hello but nothing else? I would say that's either because the get calls aren't working or you haven't put anything into those fields before you click Register.

It would be much easier to see exactly what is in the parameter list @_ if you use Data::Dump, like this

use Data::Dump;
dd \@_;

But it isn't a core module and may need installing first. You can use the core module Data::Dumper to similar effect if you prefer, but Data::Dump is much superior. If your fields are empty or contain only space characters then you won't see anything from a print call.

You should also try dumping the values returned by the five get calls in registerStu to see what is happening there.

You should note that it's poor practice to interpolate variable values into an SQL string for prepare. Much of the advantage of prepare is that you can call it just once using placeholders for the parameters, and then call execute as many times as you need afterwards. It would look like this

my $insert = $dbh->prepare('INSERT INTO student (sid, name, password, email, dept) VALUES (?, ?, ?, ?, ?)');

and then use

$insert->execute($guid, $gname, $gpwd, $gmail, $gdept) or die $DBI::errstr;

whenever you need to insert a record. The prepare call should be in the initialisation of your application together with the connect.

Upvotes: 0

Related Questions