Laravel. SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row
Ошибка возникла после добавления таблицы “profileavatar”. Запись в таблицу не добавляется. Файл падает в нужное место, но путь не вставляется в таблицу.
Полный текст ошибки:
"SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (marketplace
.vendors
, CONSTRAINT vendors_id_foreign
FOREIGN KEY (id
) REFERENCES users
(id
) ON DELETE CASCADE) (SQL: insert into vendors
(profileavatar
, id
, updated_at
, created_at
) values (images/1680006898.jpeg, f3806db0-cd64-11ed-b7f1-57830e4062ab, 2023-03-28 12:34:58, 2023-03-28 12:34:58))
Миграция
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVendorsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('vendors', function (Blueprint $table) {
$table->uuid('id');
$table->unsignedInteger('vendor_level')->default(0);
$table->integer('experience')->default(0);
$table->text('about')->nullable();
$table->string('profileavatar')->nullable();
$table->text('profilebg')->nullable();
$table->boolean('trusted')->default(false);
$table->timestamps();
$table -> primary('id');
$table -> foreign('id') -> references('id') -> on('users') -> onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('vendors');
}
}
Модель
<?php
namespace App;
use App\Marketplace\Payment\FinalizeEarlyPayment;
use App\Traits\Experience;
use App\Traits\Uuids;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class Vendor extends User
{
use Uuids;
use Experience;
protected $table = 'vendors';
protected $keyType = 'string';
protected $primaryKey = 'id';
protected $guarded = [];
protected $fillable = ['id', 'vendor_level', 'profileavatar', 'about', 'created_at', 'updated_at'];
/**
* @return Collection of \App\User instaces of all admins
*/
public static function allUsers()
{
$vendorIDs = Vendor::all() -> pluck('id');
return User::whereIn('id', $vendorIDs) -> get();
}
/**
* Return user instance of the vendor
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function user()
{
return $this -> hasOne(\App\User::class, 'id', 'id');
}
/**
* Returns collection of vendors sales
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function sales()
{
return $this -> hasMany(\App\Purchase::class, 'vendor_id', 'id') -> orderByDesc('created_at');
}
/**
* Unread sales
*
* @return int
*/
public function unreadSales()
{
return $this -> sales() -> where('read', false) -> count();
}
/**
* Returns number of the sales which has particular state or number of all sales
*
* @param string $state
* @return int
*/
public function salesCount($state = '')
{
// If state doesnt exist
if(!array_key_exists($state, Purchase::$states))
return $this -> sales() -> count();
return $this -> sales() -> where('state', $state) -> count();
}
/**
* Relationship one to many with feedback
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function feedback()
{
return $this -> hasMany(\App\Feedback::class, 'vendor_id', 'id');
}
/**
* @return mixed
*/
public function hasFeedback()
{
return $this -> feedback -> isNotEmpty();
}
/**
* Count number of feedback rates left on this vendor
*
* @return int
*/
public function countFeedback()
{
return $this -> feedback() -> count();
}
/**
* Returns all vendor's feedback by type
*
* @param string $type
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getFeedbackByType(string $type){
return $this->feedback()->where('type',$type)->get();
}
/**
* Count vendor's feedback by type
*
* @param string $type
* @param int $months
* @return int
*/
public function countFeedbackByType(string $type,int $months = null){
$query = $this->feedback()->where('type',$type);
if ($months != null){
$now = Carbon::now();
$start = $now->subMonths($months);
$query->where('created_at','>',$start);
}
return $query->count();
}
/**
* Return string number with two decimals of average rate
*
* @param $type = [ 'quality_rate' | 'communication_rate' | 'shipping_rate' ]
* @return string
*/
public function avgRate($type)
{
if(!$this -> hasFeedback())
return '0.00';
if(!in_array($type, Feedback::$rates))
$type = 'quality_rate';
if($this -> feedback -> isEmpty())
return '0.00';
return number_format($this -> feedback -> avg($type), 2);
}
/**
* Checks if vendor is trusted (set in admin panel)
*
* @return bool
*/
public function isTrusted(): bool{
if ($this->trusted){
return true;
}
$lvl = $this->getLevel();
$positive = $this->countFeedbackByType('positive');
$neutral = $this->countFeedbackByType('neutral');
$negative = $this->countFeedbackByType('negative');
$total = $positive+$negative+$neutral;
if($total == 0 || $lvl == 1 || $positive == 0){
return false;
}
$percentage = round(($positive / $total) * 100);
if ($lvl >= config('marketplace.trusted_vendor.min_lvl') &&
$total >= config('marketplace.trusted_vendor.min_feedbacks') &&
$percentage >= config('marketplace.trusted_vendor.percentage_of_feedback_positive')
){
return true;
}
return false;
}
/**
* Checks if vendor should have DWC tag
*
* @return bool
*/
public function isDwc(): bool{
if ($this->countFeedbackByType('negative') > config('marketplace.vendor_dwc_tag_count')){
return true;
} else {
return false;
}
}
/**
* Returns rounded avg rate of the feedback, half rounded on down
* 4.1 => 4
* 4.67 => 4.5
*
* @param $type
* @return float
*/
public function roundAvgRate($type)
{
$avgRateNumeric = (float)$this -> avgRate($type);
return floor($avgRateNumeric * 2) / 2;
}
/**
* If there is profile bg, return it, if not set random bg
*/
public function getProfileBg(){
if ($this->profilebg == null){
$this->profilebg = array_random(config('vendor.profile_bgs'));
$this->save();
}
return $this->profilebg;
}
/**
* Vendors with most sales all time
* @return mixed
*/
public static function topVendors(){
$vendors = Cache::remember('top_vendors_frontpage',config('marketplace.front_page_cache.top_vendors'),function(){
return self::with('sales')
->join('purchases', 'purchases.vendor_id', '=', 'vendors.id')
->select('vendors.*', DB::raw('COUNT(purchases.id) as purchases_count')) // Avoid selecting everything from the stocks table
->orderBy('purchases_count', 'DESC')
->groupBy('vendors.id')
->limit(5)
->get();
});
return $vendors;
}
/**
* Vendors with most sales in last 7 days
* @return mixed
*/
public static function risingVendors(){
$vendors = Cache::remember('rising_vendors_frontpage',config('marketplace.front_page_cache.rising_vendors'),function(){
return self::with('sales')
->join('purchases', 'purchases.vendor_id', '=', 'vendors.id')
->select('vendors.*', DB::raw('COUNT(purchases.id) as purchases_count')) // Avoid selecting everything from the stocks table
->orderBy('purchases_count', 'DESC')
->groupBy('vendors.id')
->where('vendors.created_at','>=',Carbon::now()->subDays(7))
->limit(5)
->get();
});
return $vendors;
}
public function getId(){
return $this->id;
}
/**
* Can Vendor use FE
*
* @return bool
*/
public function canUseFe(){
return $this->can_use_fe == 1 && FinalizeEarlyPayment::isEnabled();
}
/**
* Check if vendor can use specific product type
*
* @param string $type
*
* @return bool
*/
public function canUseType(string $type){
if ($type == 'fe'){
return $this->canUseFe();
}
return true;
}
}
Контроллер
<?php
namespace App\Http\Controllers;
use App\Vendor;
use App\Jobs\CreateAvatarsShops;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use App\Http\Controllers\Controller;
use Validator;
class ImageController extends Controller
{
/**
* Показ формы загрузки
*
* @param Request $request
* @return Response
*/
public function index(Request $request)
{
return view('upload_picture');
}
/**
* Загрузка картинки
*
* @param Request $request
* @return Response
*/
public function upload(Request $request)
{
$image = $request->file('demo_image');
//Загружаем картинку
$input['demo_image'] = time().'.'.$image->getClientOriginalExtension();
$destinationPath = public_path('/images');
$image->move($destinationPath, $input['demo_image']);
//Создаем запись в таблице для картинки
$image = new Vendor;
$image->profileavatar = 'images' . DIRECTORY_SEPARATOR . $input['demo_image'];
$image->save();
//Запускаем процесс обработки очереди
CreateAvatarsShop::dispatch($image);
return Redirect::to('pictures/index')->
with('message', 'Аватар успешно загружен!');
}
}