Проблема в вашей функции getAge()
, и это должно быть очевидно, если вы посмотрите на столбец возраста в вашей таблице. Ваш код:
function getAge($date)
{
return intval(substr(date('Ymd') - date('Ymd', strtotime($date)), 0, -4));
}
Функция date [) PHP возвращает строку в формате 'YYYMMDD'
. У вас их два, и вы их вычитаете. Предположим, что это '20190414'
и '20020321'
, вычитание их приведет к 170093
, а если взять последние два символа с substr()
, то вам будет 93
для кого-то, кто родился в 2002 году. Вы не заметили что?
Итак, давайте напишем лучшую getAge()
функцию. Работать точно со временем сложно. Однако на самом деле внутри PHP есть функция для вычисления разницы дат:
https://www.php.net/manual/en/datetime.diff.php
Если мы используем это для создания функции, мы получим:
function getAge($dateStr)
{
$birthDate = new DateTime($dateStr); // check the valid formats in the manual!
$currentDate = new DateTime();
return $birthDate->diff($currentDate, true)->y; // return difference in years
}
Эта функция может быть написана в одной строке кода вместо трех, но это будет сложнее читать, поэтому не делайте этого.
Это работает для вас? В вашем коде могут быть и другие ошибки, хороший способ отладки ошибок Javascript - взглянуть на ваши инструменты разработчика .
Другие уже представили синтаксис, который Вы запросили, но я рекомендую использовать более явные ссылки подпрограммы для этого, так, чтобы можно было свободно управлять ссылкой, не управляя определением. Например:
sub square_difference { return ($_[0] - $_[1]) ** 2 }
sub constant_difference { return 1 }
my %lookup = (
'square' => \&square_difference,
'constant' => \&constant_difference,
);
my $difference = $lookup{$ARGV[0]} || die "USAGE: $0 square|constant\n";
print &$difference(4, 1), "\n";
Это - тот же основной подход, но я думаю, что этот синтаксис позволит Вам отобразить аргументы подпрограммам немного более удобно, как Вы добавляете больше из каждого. Обратите внимание, что это - вариация на Стратегическую модель, если Вы в такую вещь.
То, что Вы хотите сделать, может быть достигнуто как это:
if ($ARGV[0] eq 'square') {
*difference = sub { return ($_[0] - $_[1]) ** 2 };
}
elsif ($ARGV[0] eq 'constant') {
*difference = sub { return 1 };
}
Нижние индексы определяются во время компиляции->, если бы у Вас были "предупреждения использования", включил, Вы видели бы сообщение об ошибке о переопределении подпрограммы.
Я лично не сделал большого количества этого, но Вы могли бы хотеть использовать переменную для содержания подпрограммы:
my $difference;
if ("square" eq $ARGV[0]) {$difference = sub {return ($_[0] - $_[1]) ** 2}}
elsif ("constant" eq $ARGV[0]) {$difference = sub {return 1}}
Звоните с:
&{ $difference }(args);
Или:
&$difference(args);
Или, как предложил Leon Timmermans:
$difference->(args);
Немного объяснения - это объявляет названную переменную $difference
и, в зависимости от Ваших условий, наборы это для содержания ссылки на анонимную подпрограмму. Таким образом, необходимо разыменовать $difference
как подпрограмма (следовательно &
впереди) для него для вызова подпрограммы.
Править: Код протестирован и работы.
Еще одно РЕДАКТИРОВАНИЕ:
Jesus, я так привык к use
луг strict
и warnings
то, что я забываю, что они являются дополнительными.
Но серьезно. Всегда use strict;
и use warnings;
. Это поможет поймать вещи как это и дать Вам хорошие полезные сообщения об ошибках, которые объясняют что случилось. Я никогда не должен был использовать отладчик в своей жизни из-за strict
и warnings
- это - насколько хороший сообщения проверки ошибок. Они поймают все виды вещей как это и даже дадут Вам полезные сообщения относительно того, почему они неправы.
Таким образом, каждый раз, когда Вы пишете что-то, неважно, как маленький (если это не запутывается), всегда use strict;
и use warnings;
.
Спасибо за все предложения для того, как заставить код работать. Только для полноты, я дам высокоуровневые ответы на свой вопрос.
Первая конструкция не работает, потому что функции определяются во время компиляции, но условия, и/или параметры командной строки оценены во времени выполнения. К тому времени, когда условие оценено, именованная функция была уже определена.
Компилятор действительно дает предупреждение с "предупреждениями использования", хотя не один это очень полезно для программиста, не знающего 1 :-) Трудность с предоставлением значимого предупреждения состоит в том, что определение функций в, если оператор может иметь смысл, если Вы также делаете что-то с функцией в если оператор, как в предложении Leon Timmermans. Исходный код компилирует в вырожденное, если оператор и компилятор не установлены предупредить о них.
Строго говоря не возможно условно определить функции, но возможно условно определить ссылки (rbright) или псевдонимы (Leon Timmermans) к функциям. Согласие, кажется, что ссылки лучше, чем псевдонимы, хотя я не совсем уверен почему.
Отметьте приблизительно 1: порядок оценки не очевиден, пока Вы на самом деле не столкнулись с проблемой как это; можно было предположить Perl, который оценит условия во время компиляции каждый раз, когда он мог быть сделан безопасно. По-видимому, Perl не делает этого, так как следующий код также дает предупреждение о переопределенной подпрограмме.
use warnings ;
if (1) {sub jack {}} else {sub jack {}}
Другие ответы корректны, с помощью или ссылки кода или псевдонима. Но примеры искажения представляют yicky typeglob синтаксис и забывают иметь дело со строгим.
Псевдоним является модулем, о котором часто забывают, который оборачивает все волшебство, должен был дать ссылке имя все при сохранении строгим.
use strict;
use Alias;
my $difference_method = $ARGV[0];
if( "square" eq $difference_method ) {
alias difference => sub { return ($_[0] - $_[1]) ** 2 };
}
elsif( "constant" eq $difference_method ) {
alias difference => sub { return 1 };
}
else {
die "Unknown difference method $difference_method";
}
И теперь difference($a, $b)
работы.
Если только необходимо звонить difference()
в Вашем собственном коде, т.е. Вы не собираетесь экспортировать его как функцию, я просто использовал бы ссылку кода и забыл бы искажение.
my $difference_method = $ARGV[0];
my $Difference;
if( "square" eq $difference_method ) {
$Difference => sub { return ($_[0] - $_[1]) ** 2 };
}
elsif( "constant" eq $difference_method ) {
$Difference => sub { return 1 };
}
else {
die "Unknown difference method $difference_method";
}
$Difference->($a, $b);
Условно изменение, что делает функция, делает код тяжелее для следования и менее гибкий, точно так же, как изменяющееся поведение на любом глобальном. Становится более очевидно, когда Вы понимаете, что просто оптимизируете это:
my $Difference_Method = $ARGV[0];
sub difference {
if( $Difference_Method eq 'square' ) {
return ($_[0] - $_[1]) ** 2;
}
elsif( $Difference_Method eq 'constant' ) {
return 1;
}
else {
die "Unknown difference method $Difference_Method";
}
}
Любое время у Вас есть подпрограмма формы...
sub foo {
if( $Global ) {
...do this...
}
else {
...do that...
}
}
У Вас есть проблема.
Искажение является самым полезным для генерации подобных функций во время выполнения с помощью закрытий, вместо того, чтобы сократить и вставляя их вручную. Но это для другого вопроса.
Еще один путь:
my $diffmode;
BEGIN { $diffmode = $ARGV[0] }
sub difference {
if ($diffmode eq 'square') { ($_[0] - $_[1]) ** 2 }
elsif ($diffmode eq 'constant') { 1 }
else { "It don't make no never mind" }
}