Вопрос или проблема
Итак, я пытаюсь открыть один из моих отчетов, который содержит данные о сообщении. Но он выдает ошибку, и вот контроллер:
<?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-запрос, который выполняется в программе, ссылается на поле или столбец, который не может быть найден в таблице. Давайте разберемся с возможными причинами этой ошибки в контексте предоставленного кода и структуры.
Основные причины ошибки
-
Опечатка в названии столбца: Убедитесь, что вы правильно указали все имена столбцов в запросах. Если в вашем коде (например, в
Report
модели) есть ссылки на поля, то в базе данных должны существовать соответствующие столбцы. -
Неверное название таблицы: В вашей модели
Report
установлено свойство$table
как"reports"
. Проверьте, действительно ли в базе данных существует таблица с таким именем. Если таблица называется по-другому (например,report
илиreporting
), это также может быть причиной ошибки. -
Миграции и изменения схемы: Если вы изменяли структуру таблиц после создания базы данных, убедитесь, что все миграции были успешно выполнены. Проверьте, были ли созданные столбцы в таблице при помощи команды
php artisan migrate
. Если изменения были внесены вручную, может возникнуть несоответствие между кодом и базой данных. -
Отсутствие данных в таблице: Если запрос к таблице
reports
возвращает пустое значение, возможно, что же ошибка в выборке происходит из-за отсутствия данных для данного идентификатора.
Рекомендации по устранению неполадок
-
Проверка структуры таблицы:
- Запустите команду
SHOW COLUMNS FROM reports;
в вашей базе данных, чтобы убедиться, что все указанные в модели столбцы (например,reason
,description
,user_id
,status
,response_message
,reportable_id
,reportable_type
) действительно существуют.
- Запустите команду
-
Проверка запросов:
- Посмотрите, как выполняются SQL-запросы. Вы можете включить вывод SQL-запросов в Laravel, добавив следующую строку в файл
AppServiceProvider
:\DB::listen(function ($query) { \Log::info($query->sql); });
- Это поможет отследить, какой именно SQL-запрос вызывает ошибку.
- Посмотрите, как выполняются SQL-запросы. Вы можете включить вывод SQL-запросов в Laravel, добавив следующую строку в файл
-
Диагностика логики приложения:
- Проверьте контекст выполнения метода
approve
. Важно, чтобы именно тотreport
, который вы пытаетесь обновить, существовал в базе данных. Это можно сделать, проверив, возвращает ли методfindOrFail
ожидаемый результат.
- Проверьте контекст выполнения метода
-
Тестирование:
- Если возможно, протестируйте каждый метод контроллера отдельно и протестируйте их в удобном окружении. Убедитесь, что все проверки выполняются должным образом.
-
Логирование ошибок:
- Используйте встроенные механизмы логирования Laravel для вывода дополнительной информации о возникающих ошибках, чтобы легче было определить местоположение проблемы.
Заключение
Важно поэтапно проверять каждый из вышеперечисленных пунктов, чтобы локализовать проблему. Не забывайте, что использование методов отладки и ведение журналов запросов могут заметно упростить процесс выявления и исправления ошибки. Если проблема сохраняется после выполнения всех рекомендаций, возможно, имеет смысл обратиться к более детальному анализу кода и логов приложения.
Здравствуйте!
Я внимательно ознакомился с вашим кодом и проблемой, связанной с ошибкой 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);
});
Это поможет увидеть, какие именно запросы выполняются и где может возникать ошибка.
Надеюсь, это поможет решить вашу проблему!