2026年6月19日
2026年6月19日
LearnDashのエラーを解決する方法
はじめに
LearnDashでレッスンを完了しても進捗率が更新されない・クイズを送信しても採点結果が表示されずフリーズする・コース修了条件をすべて満たしているのに修了証が発行されない・コースへのアクセス制限が機能せず未購入ユーザーがコンテンツを閲覧できるといった問題は、データベースの進捗テーブル・クイズ設定・アクセス制限フックの設定が原因です。
症状・原因
- レッスンの「完了」ボタンを押しても翌日には進捗がリセットされている
- クイズ送信ボタンを押すとぐるぐるローディングのまま何も起きない
- すべてのレッスン・クイズを完了したが「コースを修了する」ボタンが表示されない
- WooCommerceで購入済みのコースに「アクセスが制限されています」と表示されてしまう
解決手順
ステップ1:LearnDashの状態を確認する
# LearnDashの設定確認
wp eval "
if (defined('LEARNDASH_VERSION')) {
echo 'LearnDash version: ' . LEARNDASH_VERSION . PHP_EOL;
}
// コース一覧を確認
\$courses = get_posts([
'post_type' => 'sfwd-courses',
'post_status' => 'publish',
'posts_per_page' => 10,
]);
echo 'Published courses: ' . count(\$courses) . PHP_EOL;
foreach (\$courses as \$course) {
\$lessons = learndash_get_course_lessons_list(\$course->ID);
\$quizzes = learndash_get_course_quiz_list(\$course->ID);
printf(' #%d: %s | Lessons: %d | Quizzes: %d' . PHP_EOL,
\$course->ID,
\$course->post_title,
count(\$lessons),
count(\$quizzes)
);
}
// ユーザー進捗確認
\$user_id = 2; // 確認するユーザーID
\$course_id = 10; // 確認するコースID
\$progress = learndash_user_get_course_progress(\$user_id, \$course_id);
echo 'User #' . \$user_id . ' progress on course #' . \$course_id . ':' . PHP_EOL;
echo ' Completed steps: ' . (\$progress['completed'] ?? 0) . PHP_EOL;
echo ' Total steps: ' . (\$progress['total'] ?? 0) . PHP_EOL;
echo ' Status: ' . (\$progress['status'] ?? 'not started') . PHP_EOL;
"
ステップ2:コース進捗管理をカスタマイズする
// functions.php: LearnDash進捗管理
// ① レッスン完了時にカスタム処理を実行
add_action('learndash_lesson_completed', function(array $data): void {
$user_id = $data['user']->ID;
$lesson_id = $data['lesson']->ID;
$course_id = $data['course']->ID;
// 完了時刻を記録
update_user_meta($user_id, '_ld_lesson_' . $lesson_id . '_completed_at', current_time('mysql'));
// 進捗率を計算してメタ更新
$progress = learndash_user_get_course_progress($user_id, $course_id);
$pct = $progress['total'] > 0
? round($progress['completed'] / $progress['total'] * 100)
: 0;
update_user_meta($user_id, '_ld_course_' . $course_id . '_progress_pct', $pct);
error_log(sprintf('[LD] User #%d completed lesson #%d (%d%% of course #%d)',
$user_id, $lesson_id, $pct, $course_id));
});
// ② コース修了時の処理
add_action('learndash_course_completed', function(array $data): void {
$user_id = $data['user']->ID;
$course_id = $data['course']->ID;
// 修了証メールを送信
$user = get_userdata($user_id);
wp_mail(
$user->user_email,
sprintf('[%s] コース修了おめでとうございます!', get_bloginfo('name')),
sprintf("こんにちは %s さん、\n\n「%s」の修了おめでとうございます!\n\n修了証はこちらからダウンロードできます。",
$user->display_name,
get_the_title($course_id)
)
);
// 修了証に関連するカスタムロールを付与
$wp_user = new WP_User($user_id);
$wp_user->add_role('course_graduate');
error_log(sprintf('[LD] User #%d completed course #%d', $user_id, $course_id));
});
// ③ 進捗が保存されない問題のデバッグ
add_action('learndash_user_course_status_changed', function(int $user_id, int $course_id, string $old, string $new): void {
error_log(sprintf('[LD] Status change: user #%d course #%d: %s -> %s', $user_id, $course_id, $old, $new));
}, 10, 4);
ステップ3:クイズ設定を修正する
// functions.php: クイズ設定
// ① クイズ完了時の処理
add_action('learndash_quiz_completed', function(array $data, WP_User $user): void {
$quiz_id = $data['quiz']->ID;
$course_id = $data['course']->ID;
$score = $data['pass'] ? '合格' : '不合格';
$percentage = round($data['percentage'] ?? 0);
error_log(sprintf('[LD] Quiz #%d: user #%d scored %d%% (%s)',
$quiz_id, $user->ID, $percentage, $score));
// 不合格の場合はリトライメールを送信
if (!$data['pass']) {
wp_mail(
$user->user_email,
sprintf('[%s] クイズ再挑戦のご案内', get_bloginfo('name')),
sprintf("今回は%d%%でした(合格ライン未達)。\n\n再度挑戦して合格を目指しましょう!", $percentage)
);
}
}, 10, 2);
// ② クイズの制限時間を動的に設定
add_filter('learndash_quiz_time_limit', function(int $time_limit, int $quiz_id): int {
// 上級クイズは90分に設定
if (get_post_meta($quiz_id, '_ld_quiz_level', true) === 'advanced') {
return 5400; // 90分(秒)
}
return $time_limit;
}, 10, 2);
// ③ クイズのランダム出題を有効化
add_filter('learndash_quiz_questions_random', function(bool $random, int $quiz_id): bool {
// 本番クイズは必ずランダム出題
if (get_post_meta($quiz_id, '_ld_quiz_type', true) === 'final') {
return true;
}
return $random;
}, 10, 2);
ステップ4:修了証の発行を修正する
# 修了証テンプレートと発行状況を確認
wp eval "
// 修了証テンプレートを確認
\$certificates = get_posts([
'post_type' => 'sfwd-certificates',
'post_status' => 'publish',
'posts_per_page' => 10,
]);
echo 'Certificate templates: ' . count(\$certificates) . PHP_EOL;
foreach (\$certificates as \$cert) {
printf(' #%d: %s' . PHP_EOL, \$cert->ID, \$cert->post_title);
}
// 特定ユーザーの修了証発行状況を確認
\$user_id = 2;
\$course_id = 10;
\$cert_link = learndash_get_course_certificate_link(\$course_id, \$user_id);
echo 'Certificate link for user #' . \$user_id . ': ' . (\$cert_link ?: 'not available') . PHP_EOL;
// コースの完了要件を確認
\$course_meta = get_post_meta(\$course_id, '_sfwd-courses', true);
echo 'Certificate ID: ' . (\$course_meta['sfwd-courses_certificate'] ?? 'not set') . PHP_EOL;
echo 'Completion button: ' . (\$course_meta['sfwd-courses_button_complete'] ?? 'default') . PHP_EOL;
echo 'Min percentage: ' . (\$course_meta['sfwd-courses_course_min_percentage'] ?? 0) . '%' . PHP_EOL;
"
ステップ5:コースアクセス制限を修正する
// functions.php: アクセス制限
// ① WooCommerce購入後のコースアクセスを設定
add_action('woocommerce_order_status_completed', function(int $order_id): void {
$order = wc_get_order($order_id);
if (!$order) return;
foreach ($order->get_items() as $item) {
$product_id = $item->get_product_id();
// 商品に紐付いたコースIDを取得
$course_ids = get_post_meta($product_id, '_ld_course_ids', true);
if (empty($course_ids)) continue;
$user_id = $order->get_customer_id();
foreach ((array) $course_ids as $course_id) {
// コースへのアクセスを付与
ld_update_course_access($user_id, $course_id);
error_log(sprintf('[LD] Course #%d access granted to user #%d via order #%d',
$course_id, $user_id, $order_id));
}
}
});
// ② 期限付きコースアクセスを設定
add_filter('ld_course_access_expires_at', function(int $access_expires, int $user_id, int $course_id): int {
// コースの標準アクセス期間は180日
$enrolled_at = (int) get_user_meta($user_id, 'course_' . $course_id . '_access_from', true);
if ($enrolled_at > 0) {
return $enrolled_at + (180 * DAY_IN_SECONDS);
}
return $access_expires;
}, 10, 3);
注意事項
- LearnDashの進捗データが保存されない場合は
wp_usermetaテーブルのcourse_completedとlearndash_course_progressメタキーを確認してください。データが重複または破損している場合はlearndash_user_get_course_progress()が誤った値を返すことがあります - クイズのフリーズはJavaScriptの競合が原因のことが多いです。ブラウザのコンソールでエラーを確認し、
wp_dequeue_script()で競合スクリプトを特定してください。テーマのスクリプトと競合している場合はLearnDashのレッスンページではテーマのJSを無効化する設定が有効です - WooCommerceとLearnDashの連携には公式の「LearnDash WooCommerce Integration」プラグインが必要です。手動でコースアクセスを付与する場合は
ld_update_course_access()関数を使用してください
まとめ
LearnDash修復は①learndash_user_get_course_progress()でコース別進捗・完了ステップ数を確認、②learndash_lesson_completedフックで完了時刻記録・進捗率更新・learndash_course_completedフックで修了証メール送信・ロール付与、③learndash_quiz_completedフックでスコア記録・不合格時リマインダーメール・learndash_quiz_time_limitフィルターで制限時間設定、④learndash_get_course_certificate_link()で修了証発行状況確認・コース完了要件(修了証ID・最低点)を確認、⑤woocommerce_order_status_completedフックでld_update_course_access()によるコースアクセス付与・ld_course_access_expires_atフィルターで期限設定する手順で解決します。