SQLSTATE[42S22]: Колонка не найдена: 1054 Неизвестная колонка ‘reports.’

Вопрос или проблема

Итак, я пытаюсь открыть один из моих отчетов, который содержит данные о сообщении. Но он выдает ошибку, и вот контроллер:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Report;

class ReportController extends Controller
{
    public function approve(Request $request, $id)
    {
        $report = Report::findOrFail($id);

        $data = $request->validate([
            'response_message' => 'required|string|max:1000',
        ]);

        $report->update([
            'status' => 'approved',
            'response_message' => $data['response_message'],
        ]);

        session()->flash('success', 'Отчет успешно одобрен и сообщение отправлено.');
        return redirect()->back();
    }

    public function store(Request $request)
    {
        $user = auth()->id();
        if ($user === null) {
            return redirect()->route('login')->with('error', 'Идентификатор пользователя не найден. Убедитесь, что вы вошли в систему.');
        }

        $data = $request->validate([
            'reason' => 'required|string|max:255',
            'description' => 'nullable|string',
            'reportable_id' => 'required|integer',
            'reportable_type' => 'required|string',
        ]);

        $data['user_id'] = auth()->id();
        Report::create($data);

        return response()->json(['success' => true]);
    }

    public function showReports()
    {
        $reports = Report::with('user')->latest()->get();
        return view('admins.adminnotifikasi', compact('reports'));
    }

    public function userShow()
    {
        $reports = Report::where('user_id', auth()->id())
            ->where('status', 'approved')
            ->get();

        return view('pages.utama.user.show', compact('reports'));
    }

    public function deleteReport($id)
    {
        $report = Report::findOrFail($id);

        if (auth()->user()->role !== 'admin' && $report->user_id !== auth()->id()) {
            return redirect()->back()->with('error', 'У вас нет прав для удаления этого отчета.');
        }

        $report->delete();
        session()->flash('success', 'Отчет успешно удален.');
        return redirect()->back();
    }
}

это модель:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;

class Report extends Model
{
    use HasFactory;

    protected $table="reports";
    protected $fillable = [
        'reason',
        'description',
        'user_id',
        'status',
        'response_message',
        'reportable_id',
        'reportable_type',
    ];

    protected static function booted()
    {
        static::creating(fn($report) => $report->user_id = Auth::id());
    }

    public function user()
    {
        return $this->belongsTo(User::class, 'user_id'); // убедитесь, что 'user_id' - это правильный внешний ключ
    }

    public function reportable()
    {
        return $this->morphTo();
    }
}

а ниже модель, которую я сообщил

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;

class AdaApa extends Model
{
    use HasFactory;

    protected $table="adaapa";
    protected $fillable = ['title', 'content', 'image'];

    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }

    public function likes(): MorphMany
    {
        return $this->morphMany(Like::class, 'likeable');
    }

    public function reports(): MorphMany
    {
        return $this->morphMany(Report::class, 'reportable');
    }
}

модель пользователя:

<?php

namespace App\Models;

use App\Http\Controllers\DiscussionsController;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    /**
     * Атрибуты, которые можно массово назначать.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'username', // Добавьте имя пользователя здесь
        'email',
        'password',
        'role',
    ];

    /**
     * Атрибуты, которые следует скрыть для сериализации.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Получить атрибуты, которые следует преобразовать.
     *
     * @return array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    public function discussions()
    {
        return $this->hasMany(Discussions::class);
    }

    /**
     * Отношение к модели Report.
     */
    public function reports()
    {
        return $this->hasMany(Report::class);
    }

}

И в моей базе данных нет ничего неправильного, я успешно отправил ее в свою базу данных здесьвведите описание изображения здесь. Итак, в моем маршруте тоже нет ничего неправильного, но я не знаю, почему он продолжает выдавать ошибку. Также это моя блейд-шаблон, который я использую для отображения данных:

@foreach ($reports as $report)
        <div class="alert alert-info">
            <strong>Имя пользователя:</strong> {{ $report->user->name ?? 'Неизвестно' }}<br>
            <strong>Отчет о новостях:</strong> {{ $report->reportable->title ?? 'Неизвестно' }}<br>
            <strong>Причина:</strong> {{ $report->reason }}<br>
            <strong>Статус:</strong> {{ $report->status }}<br>
            <strong>Описание:</strong> {{ $report->description ?? 'Нет описания' }}<br>
            <small>Дата отчета: {{ $report->created_at }}</small>

            <!-- Форма для одобрения и отправки ответного сообщения пользователю -->
            <form action="{{ route('report.approve', $report->id) }}" method="POST" class="mt-3">
                @csrf
                <div class="mb-2">
                    <label for="responseMessage">Ответное сообщение:</label>
                    <textarea name="response_message" class="form-control" rows="2" placeholder="Введите ответное сообщение для пользователя..."></textarea>
                </div>
                <button type="submit" class="btn btn-success">Одобрить отчет</button>
            </form>
            <form action="{{ route('report.delete', $report->id) }}" method="POST" class="mt-2" onsubmit="return confirm('Вы уверены, что хотите удалить этот отчет?');">
                @csrf
                @method('DELETE')
                <button type="submit" class="btn btn-danger">Удалить отчет</button>
            </form>
        </div>
    @endforeach

Ответ или решение

Ошибка SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘reports’ указывает на то, что SQL-запрос, который выполняется в программе, ссылается на поле или столбец, который не может быть найден в таблице. Давайте разберемся с возможными причинами этой ошибки в контексте предоставленного кода и структуры.

Основные причины ошибки

  1. Опечатка в названии столбца: Убедитесь, что вы правильно указали все имена столбцов в запросах. Если в вашем коде (например, в Report модели) есть ссылки на поля, то в базе данных должны существовать соответствующие столбцы.

  2. Неверное название таблицы: В вашей модели Report установлено свойство $table как "reports". Проверьте, действительно ли в базе данных существует таблица с таким именем. Если таблица называется по-другому (например, report или reporting), это также может быть причиной ошибки.

  3. Миграции и изменения схемы: Если вы изменяли структуру таблиц после создания базы данных, убедитесь, что все миграции были успешно выполнены. Проверьте, были ли созданные столбцы в таблице при помощи команды php artisan migrate. Если изменения были внесены вручную, может возникнуть несоответствие между кодом и базой данных.

  4. Отсутствие данных в таблице: Если запрос к таблице reports возвращает пустое значение, возможно, что же ошибка в выборке происходит из-за отсутствия данных для данного идентификатора.

Рекомендации по устранению неполадок

  1. Проверка структуры таблицы:

    • Запустите команду SHOW COLUMNS FROM reports; в вашей базе данных, чтобы убедиться, что все указанные в модели столбцы (например, reason, description, user_id, status, response_message, reportable_id, reportable_type) действительно существуют.
  2. Проверка запросов:

    • Посмотрите, как выполняются SQL-запросы. Вы можете включить вывод SQL-запросов в Laravel, добавив следующую строку в файл AppServiceProvider:
      \DB::listen(function ($query) {
      \Log::info($query->sql);
      });
    • Это поможет отследить, какой именно SQL-запрос вызывает ошибку.
  3. Диагностика логики приложения:

    • Проверьте контекст выполнения метода approve. Важно, чтобы именно тот report, который вы пытаетесь обновить, существовал в базе данных. Это можно сделать, проверив, возвращает ли метод findOrFail ожидаемый результат.
  4. Тестирование:

    • Если возможно, протестируйте каждый метод контроллера отдельно и протестируйте их в удобном окружении. Убедитесь, что все проверки выполняются должным образом.
  5. Логирование ошибок:

    • Используйте встроенные механизмы логирования Laravel для вывода дополнительной информации о возникающих ошибках, чтобы легче было определить местоположение проблемы.

Заключение

Важно поэтапно проверять каждый из вышеперечисленных пунктов, чтобы локализовать проблему. Не забывайте, что использование методов отладки и ведение журналов запросов могут заметно упростить процесс выявления и исправления ошибки. Если проблема сохраняется после выполнения всех рекомендаций, возможно, имеет смысл обратиться к более детальному анализу кода и логов приложения.

Оцените материал
Добавить комментарий

Капча загружается...

  1. Гость

    Здравствуйте!

    Я внимательно ознакомился с вашим кодом и проблемой, связанной с ошибкой SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘reports’. Хочу предложить возможное решение, которое, на мой взгляд, поможет устранить эту ошибку.

    Проблема может быть связана с тем, как Eloquent обрабатывает полиморфные связи через метод morphTo() в вашей модели Report. Дело в том, что по умолчанию Laravel ожидает, что в поле reportable_type будет указано полное имя класса модели, включая пространство имен. В вашем случае это должно быть App\Models\AdaApa, а не просто AdaApa.

    Если в базе данных в столбце reportable_type указано только AdaApa, Eloquent не сможет правильно построить запрос, что может привести к ошибке с неизвестным столбцом ‘reports’. Это связано с тем, что Laravel пытается использовать значение reportable_type в качестве имени таблицы без учета пространства имен.

    Что можно сделать:

    Проверьте значения в столбце reportable_type вашей таблицы reports. Убедитесь, что они содержат полные имена классов с пространством имен. Если там указано просто AdaApa, обновите эти значения на App\Models\AdaApa.

    Используйте morphMap для определения псевдонимов моделей. Это позволит вам использовать короткие имена в базе данных, а Eloquent будет знать, к каким моделям они относятся. Добавьте следующий код в метод boot() вашего AppServiceProvider:
    use Illuminate\Database\Eloquent\Relations\Relation;

    public function boot()
    {
    Relation::morphMap([
    'adaapa' => \App\Models\AdaApa::class,
    ]);
    }

    Не забудьте добавить соответствующий use-запрос для класса Relation.

    Измените способ сохранения значения reportable_type. В вашем методе store контроллера вы напрямую принимаете reportable_type из запроса, что может быть небезопасно. Вместо этого определите допустимые модели и используйте их:
    $allowedTypes = [
    'adaapa' => \App\Models\AdaApa::class,
    ];

    $data = $request->validate([
    'reason' => 'required|string|max:255',
    'description' => 'nullable|string',
    'reportable_id' => 'required|integer',
    'reportable_type' => 'required|string|in:' . implode(',', array_keys($allowedTypes)),
    ]);

    $data['reportable_type'] = $allowedTypes[$data['reportable_type']];
    $data['user_id'] = auth()->id();

    Report::create($data);
    Это гарантирует, что в базе данных будет сохранено полное имя класса, а не произвольное значение из запроса.

    Почему это важно:

    Использование полных имен классов в reportable_type обеспечивает правильную работу полиморфных связей в Eloquent. Кроме того, валидация и ограничение допустимых значений для reportable_type повышает безопасность вашего приложения, предотвращая возможные атаки через подмену этого значения.

    Заключение:

    Рекомендую внедрить указанные изменения и проверить работу вашего приложения снова. Это должно решить проблему с ошибкой SQL и обеспечить корректную работу полиморфных связей.

    Если после внесения изменений проблема сохраняется, рекомендую включить логирование SQL-запросов для более детального анализа:

    \DB::listen(function ($query) {
    \Log::info($query->sql, $query->bindings);
    });

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

    Надеюсь, это поможет решить вашу проблему!

    Ответить