سلام به همگی
من یه فروشگاه با لاراول درست کردم برای محصولات فیزیکی
الان میخام تو همین پروژه یه بخش اضافه کنم برای دانلود فایل که کاربر بعد از پرداخت بتونه فایل دانلود کنه
میخواستم بدونم دوتا سبد خرید باید درست کرد؟ ممنون میشم راهنمایی کنید
من کدهای زیر رو نوشتم برای اینکه اطلاعات فایل تو دیتابیس ذخیره بشه ولی یک ارور دارم
ارور
Call to undefined method App\User::file()
دیتابیس
Schema::create('files', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('title');
$table->text('description');
$table->integer('price');
$table->string('image');
$table->string('file');
$table->string('slug')->unique();
$table->integer('hit');
$table->tinyInteger('status');
$table->integer('inventory')->default(0);
$table->timestamps();
});
Schema::create('category_file' , function(Blueprint $table) {
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->unsignedBigInteger('file_id');
$table->foreign('file_id')->references('id')->on('files')->onDelete('cascade');
$table->primary(['category_id' , 'file_id']);
});
مدل یوزر
public function files()
{
return $this->hasMany(File::class);
}
مدل فایل
public function users()
{
return $this->belongsToMany(User::class);
}
کنترلر
public function store(Request $request , File $files)
{
$validData = $request->validate([
'title' => 'required',
'description' => 'required',
'image' => 'required',
'file' => 'required',
'categories' => 'required',
'slug' => 'unique:files',
'status' => ''
]);
if (empty($request->slug)) {
$slug = SlugService::createSlug(File::class, 'slug', $request->title);
} else {
$slug = SlugService::createSlug(File::class, 'slug', $request->slug);
}
$request->merge(['slug' => $slug]);
$files = auth()->user()->file()->create($request->all());
$files->categories()->sync($validData['categories']);
alert()->success('مطلب مورد نظر با موفقیت ثبت شد' , 'با تشکر');
return redirect(route('admin.files.index'));
}
سلام.
@muhammad
متاسفانه موفق نشدم و چون تازه کارم گیج شدم
اگه با کد بهم بگید چیکار کنم ممنون میشم ازتون
اسم متد رو گذاشتین files، پس هر جا استفاده کردین باید بذارین files نه file. هرچند من حدس میزنم یه جای کار جدولهاتون میلنگه چون گفتین هر فایل میتونه متعلق به چند یوزر باشه.
الان به این شکل نوشتم غلطه؟
ارور زیر برمیگردونه
Call to a member function getClientOriginalName() on null
public function store(Request $request , File $files)
{
$validData = $request->validate([
'title' => 'required',
'description' => 'required',
'image' => 'required',
'file' => 'required',
'categories' => 'required',
'slug' => 'unique:files',
'status' => ''
]);
if (empty($request->slug)) {
$slug = SlugService::createSlug(File::class, 'slug', $request->title);
} else {
$slug = SlugService::createSlug(File::class, 'slug', $request->slug);
}
$request->merge(['slug' => $slug]);
$files = Storage::disk('public')->putFileAs('files' , $request->file('file') , $request->file('file')->getClientOriginalName($files))->create($request->all());
$files->categories()->sync($validData['categories']);
alert()->success('مطلب مورد نظر با موفقیت ثبت شد' , 'با تشکر');
return redirect(route('admin.files.index'));
}
الان مدل هام یعنی مشکل داره؟
تو مدل فایل اینو نباید بزارم؟
public function users()
{
return $this->belongsToMany(User::class);
}
و تو مدل یوزر اینو نباید میزاشتم؟
public function files()
{
return $this->hasMany(File::class);
}
سلام.
اولین نکته ای که باید در نظر داشته باشین اینه که این رابطه باید یک به چند باشه، در واقع هر کاربر میتونه تعداد زیادی فایل دانلود کنه و هر فایل مربوط به یک کاربر میشه، درسته؟ اگه جوابتون مثبت هست پس روابط در مدل هاتون باید به صورت زیر نوشته بشه.
مدل User:
public function files() {
return $this->hasMany(File::class);
}
مدل File:
public function user() {
return $this->belongsTo(User::class);
}
کد قسمت متد store واضح نیست و اصلا معلوم نیست میخواین چیکار کنید، روی کدتون یه توضیحی بدین تا بشه راهنمایی کرد.
@rezajahangir
بله کاملا درسته
برای فانکشن من میخام فایل با اسمی که رو خود فایل هست تو دیتابیس ذخیره بشه ولی اون ارور دارم
درکل هیچ جوره نتونستم فایل رو تو دیتابیس ذخیره کنم
<div class="row">
<div class="col-lg-12">
@include('admin.layouts.errors')
<div class="card">
<div class="card-header">
<h3 class="card-title">فرم ایجاد فایل</h3>
</div>
<!-- /.card-header -->
<!-- form start -->
<form class="form-horizontal" action="{{ route('admin.files.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="card-body">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">نام فایل</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror" id="inputEmail3" placeholder="نام فایل را وارد کنید" value="{{ old('title') }}">
@error('title')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label for="title" >نام مستعار :</label>
<div class="input-group">
<input type="text" class="form-control @error('slug') is-invalid @enderror" name="slug" value="{{old('slug')}}">
</div>
@error('slug')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">توضیحات</label>
<textarea class="form-control" name="description" id="description" cols="30" rows="10" style="min-height: 300px">{{ old('description') }}</textarea>
</div>
<div class="form-group">
<label for="title" > وضعیت : </label>
<div class="input-group">
<select class="form-control" name="status" >
<option value="0">منتشر نشده</option>
<option value="1">منتشر شده</option>
</select>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">قیمت</label>
<input type="number" name="price" class="form-control @error('price') is-invalid @enderror" id="inputPassword3" placeholder="قیمت را وارد کنید" value="{{ old('price') }}">
@error('price')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">موجودی</label>
<input type="number" name="inventory" class="form-control @error('inventory') is-invalid @enderror" id="inputPassword3" placeholder="موجودی را وارد کنید" value="{{ old('inventory') }}">
@error('inventory')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label class="col-sm-2 control-label">آپلود تصویر شاخص</label>
<div class="input-group">
<input type="text" id="image_label" class="form-control" name="image">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="button-image">انتخاب</button>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">آپلود فایل</label>
<div class="input-group">
<input type="text" id="file_label" class="form-control" name="file">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="button-file">انتخاب</button>
</div>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">دسته بندی ها</label>
<select class="form-control" name="categories[]" id="categories" multiple>
@foreach(\Modules\Category\Entities\Category::all() as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
</select>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-info">ثبت فایل</button>
<a href="{{ route('admin.files.index') }}" class="btn btn-default float-left">لغو</a>
</div>
<!-- /.card-footer -->
</form>
</div>
</div>
</div>
قسمت بلید 3 تا مشکل داره.
مشکل اول اینه که input آپلود فایل رو به صورت زیر بنویسید.
<input type="file" id="file_label" class="form-control" name="file">
و اگر میخواین در این input، فقط pdf آپلود کنید باید به صورت زیر بنویسید که کاربر دیگه نتونه عکس یا فایل دیگه ای آپلود کنه:
<input type="file" id="file_label" class="form-control" name="file" accept="application/pdf>
مشکل دوم اینه که input آپلود عکس هم به صورت زیر بنویسید.
<input type="file" id="image_label" class="form-control" name="image">
و اگر فقط میخواین در این input، عکس آپلود کنید باید به صورت زیر بنویسید که کاربر دیگه نتونه نوع فایل دیگه ای آپلود کنه:
<input type="file" id="image_label" class="form-control" name="image" accept="image/*">
مشکل سوم اینه که حلقه foreach رو چرا به این صورت نوشتین؟ در صورتی که باید به صورت زیر باشه.
@foreach(\App\Models\Category::all() as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
@rezajahangir
برای تصاویر چون از فایل منیجر و تصاویر شاخص استفاده میکنم type از نوع text گذاشتم این قسمت به درستی کار میکنه مشکلی نداره
برای foreach چون ماژول بندی کردم از اون مسیر داره میخونه category
تنها مشکلی که دارم فایل تو دیتابیس ذخیره نمیشه و اون اروری که فرستادم نمایش میده
مشکلم فقط قسمت کوئری store هست
اگه فایل پاک کنم اطلاعات تو دیتابیس ذخیره میشه ولی فایل اضافه میکنم اطلاعات ذخیره نمیشه
این خط تو فایل کنترلر ارور میگیره
$files = Storage::disk('public')->putFileAs('files' , $request->file('file') , $request->file('file')->getClientOriginalName($files))->create($request->all());
متن ارور
Call to a member function getClientOriginalName() on null
داخل بلیدی که فرستادین ckeditor نبود که؟
قصدتون اینه که فایلی که داخل ckeditor آپلود میشه داخل فیلد file ذخیره بشه؟
@rezajahangir
بله میخام هم یک تصویر داخل فایل منیجر ckeditor باشه
هم یک فایل حالا از نوع zip یا pdf تو قسمت دوم که نوشتم تو فایل منیجر ckeditor اپلود بشه و تو دیتابیس ذخیره شه
بلید به طور کامل میفرستم
@component('admin.layouts.content' , ['title' => 'ایجاد فایل'])
@slot('breadcrumb')
<li class="breadcrumb-item"><a href="/admin">پنل مدیریت</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.files.index') }}">لیست فایل</a></li>
<li class="breadcrumb-item active">ایجاد فایل</li>
@endslot
@slot('script')
<script src="/js/ckeditor/ckeditor.js"></script>
<script>
CKEDITOR.replace('description', { filebrowserImageBrowseUrl: '/file-manager/ckeditor' });
document.addEventListener("DOMContentLoaded", function() {
document.getElementById('button-image').addEventListener('click', (event) => {
event.preventDefault();
inputId = 'image_label';
window.open('/file-manager/fm-button', 'fm', 'width=1400,height=800');
});
document.getElementById('button-file').addEventListener('click', (event) => {
event.preventDefault();
inputId = 'file_label';
window.open('/file-manager/fm-button', 'fm2', 'width=1400,height=800');
});
});
// set file link
let inputId = '';
function fmSetLink($url) {
document.getElementById(inputId).value = $url;
}
$('#categories').select2({
'placeholder' : 'دسترسی مورد نظر را انتخاب کنید'
})
</script>
@endslot
<div class="row">
<div class="col-lg-12">
@include('admin.layouts.errors')
<div class="card">
<div class="card-header">
<h3 class="card-title">فرم ایجاد فایل</h3>
</div>
<!-- /.card-header -->
<!-- form start -->
<form class="form-horizontal" action="{{ route('admin.files.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="card-body">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">نام فایل</label>
<input type="text" name="title" class="form-control @error('title') is-invalid @enderror" id="inputEmail3" placeholder="نام فایل را وارد کنید" value="{{ old('title') }}">
@error('title')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label for="title" >نام مستعار :</label>
<div class="input-group">
<input type="text" class="form-control @error('slug') is-invalid @enderror" name="slug" value="{{old('slug')}}">
</div>
@error('slug')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">توضیحات</label>
<textarea class="form-control" name="description" id="description" cols="30" rows="10" style="min-height: 300px">{{ old('description') }}</textarea>
</div>
<div class="form-group">
<label for="title" > وضعیت : </label>
<div class="input-group">
<select class="form-control" name="status" >
<option value="0">منتشر نشده</option>
<option value="1">منتشر شده</option>
</select>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">قیمت</label>
<input type="number" name="price" class="form-control @error('price') is-invalid @enderror" id="inputPassword3" placeholder="قیمت را وارد کنید" value="{{ old('price') }}">
@error('price')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">موجودی</label>
<input type="number" name="inventory" class="form-control @error('inventory') is-invalid @enderror" id="inputPassword3" placeholder="موجودی را وارد کنید" value="{{ old('inventory') }}">
@error('inventory')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group">
<label class="col-sm-2 control-label">آپلود تصویر شاخص</label>
<div class="input-group">
<input type="text" id="image_label" class="form-control" name="image">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="button-image">انتخاب</button>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">آپلود فایل</label>
<div class="input-group">
<input type="text" id="file_label" class="form-control" name="file">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="button-file">انتخاب</button>
</div>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">دسته بندی ها</label>
<select class="form-control" name="categories[]" id="categories" multiple>
@foreach(\Modules\Category\Entities\Category::all() as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
</select>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-info">ثبت فایل</button>
<a href="{{ route('admin.files.index') }}" class="btn btn-default float-left">لغو</a>
</div>
<!-- /.card-footer -->
</form>
</div>
</div>
</div>
@endcomponent
اگه از ckeditor استفاده میکنید به ترتیب مراحل زیر رو کپی کنید.
توضیحات مربوط به ورژن ۴ هست.
روت:
Route::post('/editor/upload', [EditorUploadController::class, 'upload'])->name('editor-upload');
کنترلر مربوطه:
class EditorUploadController extends Controller
{
public function upload(Request $request) {
$file = $request->file('upload');
$base_name = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
$ext = $file->getClientOriginalExtension();
$file_name = $base_name . '_' . time() . '.' . $ext;
$file->storeAs('images/Articles', $file_name, 'public_files');
$function = $request->CKEditorFuncNum;
$url = asset('images/Articles/' . $file_name);
return response("<script>window.parent.CKEDITOR.tools.callFunction({$function}, '{$url}', 'فایل به درستی آپلود شد')</script>");
}
}
در بلید مربوطه کد زیر رو اضافه کنید.
<script src="https://cdn.ckeditor.com/4.16.0/standard/ckeditor.js"></script>
<script>
CKEDITOR.replace('file', {
language: 'fa',
filebrowserUploadUrl: '{{ route("editor-upload", ["_token" => csrf_token()]) }}',
filebrowserUploadMethod: 'form'
})
</script>
در آخر به مسیر زیر برید:
config\filesystems.php
و کد زیر رو اضافه کنید.
'public_files' => [
'driver' => 'local',
'root' => public_path(),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
متد store هم به صورت زیر بنویسید:
public function store(Request $request)
{
$file = $request->file('image');
$file_name = $file->getClientOriginalName();
$file->storeAs('images/image', $file_name, 'public_files');
$validData = $request->validate([
'title' => 'required',
'description' => 'required',
'image' => 'required',
'file' => 'required',
'categories' => 'required',
'slug' => 'unique:files',
'status' => ''
]);
$validData['image'] = $file_name;
$validData['user_id'] = auth()->user()->id;
$article = Article::create(
$validData
);
$article->categories()->attach($validData['categories']);
alert()->success('مطلب مورد نظر با موفقیت ثبت شد' , 'با تشکر');
return redirect(route('admin.files.index'));
}
موفق باشید.
@rezajahangir
ممنون ازتون
store به این شکل نوشتم درسته ؟
public function store(Request $request , File $files)
{
$validData = $request->validate([
'title' => 'required',
'description' => 'required',
'image' => 'required',
'file' => 'required',
'categories' => 'required',
'slug' => 'unique:files',
'status' => ''
]);
if (empty($request->slug)) {
$slug = SlugService::createSlug(File::class, 'slug', $request->title);
} else {
$slug = SlugService::createSlug(File::class, 'slug', $request->slug);
}
$request->merge(['slug' => $slug]);
$files = File::create($request->all());
$files->categories()->sync($validData['categories']);
alert()->success('مطلب مورد نظر با موفقیت ثبت شد' , 'با تشکر');
return redirect(route('admin.files.index'));
}
الان این ارور دارم
SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into `files` (`hit`, `title`, `slug`, `description`, `status`, `price`, `inventory`, `image`, `file`, `updated_at`, `created_at`) values (1, nbnb, nbnb, <p>jhjk</p>, 1, 6565, 8, http://localhost:8000/images/AI-Drug.jpg, http://localhost:8000/storage/files/file.rar, 2021-06-11 01:17:04, 2021-06-11 01:17:04))
سلام.
نیازی به دوتا سبد ندارید و از polymorphic ها در لاراول به راحتی استفاده کنید و لذت ببرید.داکیومنت رو در بخش relation ها بخونید تمومه و دستتون میاد
آیا مایل به ارسال نوتیفیکیشن و اخبار از طرف راکت هستید ؟