Необходимо выполнить итерацию хеша, полученного из запроса MySQL

Хорошо, у меня есть следующая функция-член:

sub GetCategories {
    my $sth = $dbh->prepare("SELECT CatID, CatName, CatLink FROM Categories");
    $sth->execute() or die $DBI::errstr;
    my $results = $sth->fetchall_arrayref({});
    return($results);
    $sth->finish();
}

Я называю это с помощью:

my $Cats = $d2s->GetCategories();

my $vars = my $vars = {
    categories => $Cats,
};

Однако мой вопрос: как мне это детализировать и извлечь значения в Perl?

Это сводит меня с ума — ниже приведен формат данных $vars из Data::Dumper —

$VAR1 = {
      'categories' => \[
                          [
                            1,
                            'General',
                            './PostList.pl?cat=General'
                          ],
                          [
                            2,
                            'DevOps',
                            './PostList.pl?cat=DevOps'
                          ]
     };

Я ожидал увидеть

 'categories' => [ { 'CatID' => 1, 'CatLink' => './PostList.pl?cat=General', 
'CatName' => 'General' }, { 'CatID' => 2, 'CatLink' => './PostList.pl?cat=DevOps', 'CatName' => 'DevOps' }, 

и так далее

как мне, например, распечатать значение DevOps во второй структуре в Perl-скрипте. Я могу сделать это в шаблоне tt, но не в Perl.

Если вы return из подпрограммы, последняя строка $sth->finish() никогда не выполняется. Возврат должен быть последней строкой в ​​вашем субтитуле (в данном случае). Кроме того, ваш код содержит странные обратные кавычки. Если этого нет в вашем реальном коде, этого не должно быть в этом коде. Исправьте это, если это опечатка.

TLP 21.08.2024 15:34

Показанный вами код не дает показанного вами результата. Вы действительно передали пустой хеш-ссылку в качестве аргумента, например fetchall_arrayref({})? Это должно возвращать одну хэш-ссылку на строку. Также ваш вывод Dumper показывает ссылку на ссылку на массив. Ваш код этого не дает.

clamp 21.08.2024 17:27
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
2
71
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Если переменная содержит ссылку, вам необходимо разыменовать ее, чтобы получить доступ к объекту, на который указывает ссылка.

my $VAR1 = {
    categories => \[
                      [
                        1,
                        'General',
                        './PostList.pl?cat=General'
                      ],
                      [
                        2,
                        'DevOps',
                        './PostList.pl?cat=DevOps'
                      ]
                  ]  # <- this was missing in your code!
};
print ${ $VAR1->{categories} }->[1][1];  # DevOps

$VAR1 — это ссылка на хэш, мы можем разыменовать ее, используя стрелку.

$VAR1->{categories}

Значение, связанное с «категориями», является ссылкой на ссылку на массив, поэтому нам нужно разыменовать его как скаляр, чтобы получить ссылку на массив.

${ $VAR1->{categories} }

тогда мы сможем снова использовать стрелку, чтобы попасть в массив.

${ $VAR1->{categories} }->[1]

Кстати, если $sth->finish(); стоит после return, он никогда не будет выполнен.

«Значение, связанное с «категориями», является ссылкой на ссылку на массив, поэтому нам нужно разыменовать его как скаляр, чтобы получить ссылку на массив». Это именно то, что я не знаю, как сделать. У вас есть пример того, как это сделать? Кстати: я изучаю Perl всего меньше месяца, но пишу сценарии Bash уже давно, и до сих пор мне нравится Perl.

user3183111 21.08.2024 13:17

Это показано в последней строке примера кода. О ссылках читайте в очень коротком руководстве Марка о ссылках и Perl-ссылках и вложенных структурах данных

choroba 21.08.2024 13:36

Код, который вы показываете для GetCategories(), предназначен для возврата массива ссылок Hashrefs. Обратите внимание на использование пустой хеш-ссылки в качестве аргумента fetchall_arrayref({}), что описано здесь (если $slice является хэш-ссылкой, fetchall_arrayref извлекает каждую строку как хэш-ссылку). Однако остальная часть вашего вопроса показывает структуру, которая не была создана этим кодом. Вот полный пример, демонстрирующий использование fetchall_arrayref({}) и способ доступа к определенному элементу в возвращаемой структуре (извините, это postgres, но здесь это не имеет значения):

use 5.030;
use warnings;
use Data::Dumper;
use DBD::Pg;
my $sql =q|
SELECT * FROM
(VALUES( 1,
        'General',
        './PostList.pl?cat=General'),
       ( 2,
         'DevOps',
         './PostList.pl?cat=DevOps')
)AS categories("CatID", "CatName", "CatLink")|; 


my $dh = DBI->connect(
    "DBI:Pg:dbname=postgres; host=127.0.0.1", "postgres");
die $DBI::errstr unless $dh;
my $sth = $dh->prepare($sql);
$sth->execute();
my $res = $sth->fetchall_arrayref({});

my $vars = {categories => $res};

print Dumper $vars;

#access CatName of 2nd row:

say $vars->{categories}[1]{CatName};

принты:

$VAR1 = {
          'categories' => [
                            {
                              'CatLink' => './PostList.pl?cat=General',
                              'CatName' => 'General',
                              'CatID' => 1
                            },
                            {
                              'CatLink' => './PostList.pl?cat=DevOps',
                              'CatName' => 'DevOps',
                              'CatID' => 2
                            }
                          ]
        };
DevOps

Хорошее объяснение (думаю, вы имели в виду use DBI, а не use DBD::Pg)

Bruce Van Allen 21.08.2024 22:45

Я использовал DBD::Pg, который использует DBI, но, как я уже писал, это пример pg, он также будет работать с MySQL.

clamp 21.08.2024 22:54

Интересный. Я всегда следил за документами DBI и DBD::Pg, которые предполагают следующее: use DBI; $dbh = DBI->connect("dbi:Pg:dbname=$dbname", ...); # OR $dbh = DBI->connect("dbi:SQLite:dbname=$dbname", ...)

Bruce Van Allen 22.08.2024 03:45

Это должно работать в любом случае. За исключением случаев, когда вы use DBI он умрет во время выполнения, когда DBD::Pg не установлен. С use DBD::Pg он умирает во время компиляции - здесь это не имеет значения.

clamp 22.08.2024 08:53

Я попробую это позже.

Я добился того, что мне нужно, следующим образом, но это не идеально. Как только я разберусь со ссылками на Perl и областью видимости переменных, я последую вашему совету, потому что он выглядит более компактным и универсальным, а это то, чего я хочу.

$sth->execute() or die $DBI::errstr;
    my @arrRtn;
    my $i=0;

  while ( my @row = $sth->fetchrow_array ) {
    my ($cat_id, $cat_name, $cat_link ) = @row;
    @arrRtn[$i] = {
        'CatID'  => $cat_id,
        'CatName' => $cat_name,
        'CatLink' => $cat_link,
    };
    $i++;
}
      
$sth->finish();
#print Dumper(@hRtn);
foreach (@arrRtn)
{
    print "ID: $_->{'CatID'}<br>NAME: $_->{'CatName'}<br>LINK: $_->{CatLink}<br><br>";
} 

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