I'm facing a weird problem that only accurs when I use pagination with livewire components,
this is the error:
BadMethodCallException
Method Illuminate\Support\Collection::items does not exist.
I know what this errors means, the problem is why it only accurs when I change page in pagination:
this is my Component:
<?php
namespace App\Http\Livewire\Admin;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\WithFileUploads;
use App\Models\Product;
use App\Models\Category;
use File;
use GlobalsHelper;
class Products extends Component
{
use WithPagination, WithFileUploads;
public $products;
public $subcategories;
// Form
public $name;
public $description;
public $price;
public $quantity;
public $category_id = null;
public $sub_category_id = null;
public $image;
public $selected = [];
public $query = '';
public $filter_by_category = '';
protected $paginationTheme = 'bootstrap';
public function render()
{
$pagination = $this->products;
$this->products = collect($this->products->items());
return view('livewire.admin.products', [
'categories' => Category::all(),
'subcategories' => $this->subcategories,
'products' => $this->products,
'pagination' => $pagination
]);
}
// public function render()
// {
// return view('livewire.admin.products', [
// 'categories' => Category::all(),
// 'subcategories' => $this->subcategories,
// 'products' => $this->products,
// ]);
// }
public function mount()
{
$this->getSubcategories();
$this->index();
}
public function getSubcategories()
{
$this->subcategories = [];
if ( !$this->category_id )
{
$this->category_id = (Category::first()) ? Category::first()->id : null;
}
$category = Category::find($this->category_id);
if ( !$category )
{
return null;
}
$this->subcategories = $category->children;
$this->sub_category_id = ($this->subcategories->first()) ? $this->subcategories->first()->id : null;
}
public function store()
{
$fields = $this->validate([
'name' => ['required', 'string', 'min:5', 'max:250'],
'description' => ['string', 'max:250'],
'price' => ['required', 'numeric', 'min:1'],
'quantity' => ['required', 'numeric', 'min:1'],
'category_id' => ['nullable'],
'sub_category_id' => ['nullable'],
]);
$fields['user_id'] = GlobalsHelper::auth()->id;
$product = Product::create($fields);
if ( !$product )
{
session()->flash('error', __('messages.error_create'));
return;
}
// upload image
$this->storeImage($product);
$this->resetFields();
session()->flash('success', __('messages.success_create'));
}
public function search()
{
$results = Product::where('name', 'LIKE', '%'.$this->query.'%')
->orderBy('id', 'desc')->paginate(5);
$this->products = $results;
}
public function index()
{
$this->products = Product::orderBy('id', 'desc')->paginate(5);
}
public function filterByCategory()
{
$results = Product::where('category_id', '=', $this->filter_by_category)
->orderBy('id', 'desc')->paginate(5);
$this->products = $results;
}
// private
private function resetFields()
{
$this->name = null;
$this->description = null;
$this->price = 0;
$this->quantity = 1;
$this->image = null;
$this->filename = '...';
}
private function storeImage($product)
{
$this->validate([
'image' => ['nullable', 'image', 'max:1024'],
]);
if ( $this->image )
{
// Delete old image if exists
if ( $product->image )
{
File::delete([$product->image->fullpath]);
}
$filename = sha1( uniqid('', true) );
$ext = $this->image->getClientOriginalExtension();
$fullpath = $this->image->store(GlobalsHelper::PRODUCTS_UPLOADS_DIR.'/'.$product->id, 'public');
$product->update([
'image' => [
'name' => basename($fullpath),
'type' => $ext,
'fullpath' => GlobalsHelper::STORAGE_DIR.$fullpath,
'url' => asset(GlobalsHelper::STORAGE_DIR.$fullpath)
]
]);
}
}
}
The idea is that I want to achieve search, store, update, delete, filter operations in same compoenent like in laravel controller, I found solutions online, but only 50% of what I need to achieve.
I have been wasting a lot of time trying to figure this out.
If any one would help me, I will be much appreciated.
At first glance without seeing the view, you are getting the $produts via the mount() method, this will only run ONCE when the livewire component is first rendered. From the docs:
mount() is only ever called when the component is first mounted and will not be called again even when the component is refreshed or rerendered.
Related
This is my Item model. I have made a function arrayPackageItemSelect that gets the id and equivalent it to the item name.
class Item extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'name',
'price',
'itemdescription',
'activeInactive'
];
public function packageitems()
{
return $this->hasMany(PackageItem::class);
}
public static function arrayPackageItemSelect()
{
$arr = [];
$items = Item::all();
foreach($items as $item){
$arr[$item->id] = $item->name;
}
return $arr;
}
}
my PackageItem Model
class PackageItem extends Model
{
protected $fillable = [
'user_id',
'item_id',
'price'
];
protected $table='packageitems';
public static function itemModel()
{
return $this->belongsTo(Item::class);
}
}
my PackageItem Controller (CREATE) and getting the Item ID from another table (Foreign key) so I can put a category for it.
public function addPackageItem(Request $request)
{
$user = Auth::user();
$item = Item::arrayPackageItemSelect();
echo $item; // when I echo this I get Array to Conversion String in POSTMAN
$fields = $request->validate([
'user_id' => 'required',
'item_id' => 'required',
'price' => 'required|numeric'
]);
// // echo $items;
$package = PackageItem::create([
'user_id' => $user->id,
'item_id' => $item,
'price'=> $fields['price']
]);
return response($package, 201);
}
What I get when I echo the Items
The results I get from POSTMAN
My Schema
This is where my reference is https://www.artofcse.com/learning/product-view-insert-update-delete
Can anybody help me what is wrong?
In your controller (addPackageItem method):
$package = PackageItem::create([
'user_id' => $user->id,
'item_id' => $fields['item_id'],
'price'=> $fields['price']
]);
Also, i think there is an error in your PackageItem model. belongsTo should not be called in a static method :
public function itemModel()
{
return $this->belongsTo(Item::class);
}
I am using Laravel-8 and Maatwebsite-3.1 package to import Excel into the DB using Laravel API as the endpoint.
Trait:
trait ApiResponse {
public
function coreResponse($message, $data = null, $statusCode, $isSuccess = true) {
if (!$message) return response() - > json(['message' => 'Message is required'], 500);
// Send the response
if ($isSuccess) {
return response() - > json([
'message' => $message,
'error' => false,
'code' => $statusCode,
'results' => $data
], $statusCode);
} else {
return response() - > json([
'message' => $message,
'error' => true,
'code' => $statusCode,
], $statusCode);
}
}
public
function success($message, $data, $statusCode = 200) {
return $this - > coreResponse($message, $data, $statusCode);
}
public
function error($message, $statusCode = 500) {
return $this - > coreResponse($message, null, $statusCode, false);
}
}
Import:
class EmployeeImport extends DefaultValueBinder implements OnEachRow, WithStartRow, SkipsOnError, WithValidation, SkipsOnFailure
{
use Importable, SkipsErrors, SkipsFailures;
public function onRow(Row $row)
{
$rowIndex = $row->getIndex();
if($rowIndex >= 1000)
return; // Not more than 1000 rows at a time
$row = $row->toArray();
$employee = Employee::create([
'first_name' => $row[0],
'other_name' => $row[1] ?? '',
'last_name' => $row[2],
'email' => preg_replace('/\s+/', '', strtolower($row[3])),
'created_at' => date("Y-m-d H:i:s"),
'created_by' => Auth::user()->id,
]);
public function startRow(): int
{
return 2;
}
}
Controller:
public function importEmployee(Request $request)
{
try {
$validator = Validator::make($request->all(), [
'document' => 'file|mimes:xls,xlsx|max:5000',
]);
if ($request->hasFile('document'))
{
if($validator->passes()) {
$import = new EmployeeImport;
$file = $request->file('document');
$file->move(public_path('storage/file_imports/employee_imports'), $file->getClientOriginalName());
Excel::import($import, public_path('storage/file_imports/employee_imports/' . $file->getClientOriginalName() ));
foreach ($import->failures() as $failure) {
$importerror = new ImportError();
$importerror->data_row = $failure->row(); // row that went wrong
$importerror->data_attribute = $failure->attribute(); // either heading key (if using heading row concern) or column index
$importerror->data_errors = $failure->errors()[0]; // Actual error messages from Laravel validator
$importerror->data_values = json_encode($failure->values());
$importerror->created_by = Auth::user()->id;
$importerror->created_at = date("Y-m-d H:i:s");
$importerror->save();
}
return $this->success('Employees Successfully Imported.', [
'file' => $file
]);
}else{
return $this->error($validator->errors(), 422);
}
}
} catch(\Throwable $e) {
Log::error($e);
return $this->error($e->getMessage(), $e->getCode());
}
}
I made it to SkipOnError and SkipOnFailure.
If there's error, it saves the error into the DB. This is working.
However, there is issue, if some rows fail it still display success (Employees Successfully Imported) based on this:
return $this->success('Employees Successfully Imported.
When there is partial upload, or all the rows or some of the rows have issues, I want to display this to the user. So that it will be interactive.
How do I achieve this?
Thanks
I have an Image model it saves data through the controller but it doesn't display data, please what's the issue.
The Model
namespace App;
use App\Event\NotifyPhoto;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
public $table = "images";
protected $guarded = [];
public $timestamps = false;
public function property_user()
{
return $this->belongsTo('App\PropertyUser');
}
public function facility(){
return $this->belongsTo('App\Facility');
}
}
The Image controller
namespace App\Http\Controllers;
use App\Http\Requests\ImageRequest;
use App\Property;
use App\PropertyUser;
use Illuminate\Http\Request;
use App\Facility;
use App\Image;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Carbon;
class ImageController extends Controller
{
public function create()
{
dd(Image::all());//This comes back empty
return view('settings.photos');
}
public function store(Request $request)
{
$property_users = PropertyUser::where('user_id', '=', Auth::user()- >id)->get();
foreach ($property_users as $property_user) {
$id = $property_user->property_id;
}
$rules = [
'file' => 'required',
'description' => 'required',
'tag' => 'required'
];
$request->file('file');
if (!empty($request->file('file'))) {
$file_count = count($request->file('file'));
} else $file_count = null;
foreach (range(0, $file_count) as $index) {
$rules['file.' . $index] = 'image|mimes:jpeg,gif,webp,bmp,png|max:2048';
}
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return back()
->withErrors($validator)
->withInput();
} else {
$files = $request->file('file');
$description = $request->input('description');
$tag = $request->input('tag');
$i = 0;
foreach ($files as $file) {
$i++;
$file1 = $file->move(public_path() . '/upload_images/', $file->getClientOriginalName());
$url1 = $url = URL::to("/") . '/upload_images/' . $file->getClientOriginalName();
$image = Image::create([
'filename' => $url,
'description' => $description,
'facility_id' => 16, //$new_fac->id ?? $f->id,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
'tag' => $tag
]);
dd($image);//This displays the files saved and their ids in the table
]
}
return redirect('settings/photos');
}
}
}
Try adding this to your App/Image:
protected $fillable = [
'filename',
'description',
'facility_id',
'created_at',
'updated_at',
'tag',
];
https://laravel.com/docs/5.6/eloquent#mass-assignment
Also, can you confirm a new row is being added to the database?
I have an asset_category table(columns 'asset_category_id', 'category') and an asset table(columns 'asset_id', 'asset_category_id') and want display the (columns 'asset_id', 'asset_category_id.category,') from the asset table instead of just the 'asset_id' n 'asset_category_id' columns.
Asset_CatoriesController
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Asset_category;
class Asset_CategoriesController extends Controller
{
public function asset_category(){
$asset_categories = Asset_category::all();
return view('category', ['asset_categories' => $asset_categories]);
}
public function add(Request $request){
$this->validate($request, [
'asset_category_id' => '',
'category' => 'required'
]);
$asset_categories = new Asset_category;
$asset_categories ->asset_category_id = $request->input('asset_category_id');
$asset_categories ->category = $request->input('category');
$asset_categories ->save();
return redirect('/category') ->with('info', 'New Category Saved Successfully!');
}
public function update($id){
$asset_categories = Asset_category::find($id);
return view('update', ['asset_categories' => $asset_categories]);
}
public function edit(Request $request, $id){
$this->validate($request, [
'asset_category_id' => '',
'category' => 'required'
]);
$data = array(
'category' => $request ->input('category')
);
Asset_category::where('asset_category_id', $id)->update($data);
return redirect('/category') ->with('info', 'Category Updated Successfully!');
}
public function delete($id){
Asset_category::where('asset_category_id', $id)
->delete();
return redirect('/category') ->with('info', 'Category Deleted Successfully!');
}
}
AssetController
<?php
namespace App\Http\Controllers;
use App\Asset;
use App\Asset_category;
use App\Manufacturer;
use App\Department;
use Illuminate\Http\Request;
class AssetController extends Controller
{
public function asset(){
$assets = Asset::all();
// return view::make('viewAsset')->with('assets', $assets);
return view('viewAsset', ['assets' => $assets]);
}
public function manufacturer(){
$manufacturers = Manufacturer::all();
return view('asset', ['manufacturers' => $manufacturers]);
}
public function add(Request $request){
$this->validate($request, [
'asset_id' => '',
'asset_category_id' => 'required',
'manufacturer_id' => 'required',
'department_id' => 'required',
]);
$assets = new Asset;
$assets ->asset_id = $request->input('asset_id');
$assets ->asset_category_id = $request->input('asset_category_id');
$assets ->manufacturer_id = $request->input('manufacturer_id');
$assets ->department_id = $request->input('department_id');
$assets ->save();
return redirect('/viewAsset') ->with('info', 'New Asset Saved Successfully!');
}
public function update($id){
$assets = Asset::find($id);
return view('updateAsset', ['assets' => $assets]);
}
public function edit(Request $request, $id){
$this->validate($request, [
'asset_id' => '',
'asset_category_id' => 'required',
'manufacturer_id'=> 'required',
'department_id' => 'required'
]);
$data = array(
'asset_category_id' => $request ->input('asset_category_id'),
'manufacturer_id' => $request ->input('manufacturer_id'),
'department_id' => $request ->input('department_id')
);
Asset::where('asset_id', $id)->update($data);
return redirect('/viewAsset') ->with('info', 'Asset Updated Successfully!');
}
public function delete($id){
Asset::where('asset_id', $id)
->delete();
return redirect('/viewAsset') ->with('info', 'Asset Deleted Successfully!');
}
}
Asset.php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Asset_category;
class Asset extends Model
{
protected $primaryKey = 'asset_id';
public function category(){
return $this->belongsTo('Asset_category');
//$this->belongsTo('Asset_category');
//Asset_category::where('asset_category_id', $this->asset_category_id)->first()->category;
}
}
Asset_category.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Asset;
class Asset_category extends Model
{
protected $primaryKey = 'asset_category_id';
public function asset() {
return $this->hasMany('Asset', 'asset_category_id');
}
}
viewAsset.php
#foreach($assets->all() as $asset)
<tr>
<td>{{ $asset->asset_id}}</td>
<td>{{ $asset->category->category}}</td>
when i run the project i get a FatalErrorExeception which says
Class 'Asset_category' not found in HasRelationships.php
You have Asset_category in a namespace. Try changing this:
return $this->belongsTo('Asset_category');
to this:
return $this->belongsTo(Asset_category::class);
You must end #foreach with #endforeach
You must declare protected $table = 'table_name'; in model because in default laravel generate table name to plural form of model's class name
Try to return this:
return $this->belongsTo('Asset_category');
return $this->hasMany('Asset', 'asset_category_id');
to this:
return $this->belongsTo(Asset_category::class);
return $this->hasMany(Asset::class, 'asset_category_id');
I have a problem with insert_id. I'm using CodeIgniter. I have a method in which I insert some values and in it I return
$insert_id=$this->db->insert_id();
return $insert_id;`
I want to use this value in another method in the same model. I tried that: $insert_id=$this->add_teacher_subject(); but in this way first method runs again and I doesn't receive last_insert_id , but this value +1. Please, tell me how could I solve this problem?
My model is:
public function add_teacher_subject() {
$date = new DateTime("now");
$data=array(
'teacher_id'=>$this->input->post('teacher'),
'user_id'=>$this->session->userdata['user_id'],
'created_at'=>$date->format('Y-m-d H:i:s')
);
$this->db->insert('student_surveys',$data);
$insert_id=$this->db->insert_id();
return $insert_id;
}
public function survey_fill()
{
$insert_id=$this->add_teacher_subject();
if ($this->input->post('answer')) {
$answers= $this->input->post('answer');
if (null !==($this->input->post('submit'))) {
$date = new DateTime("now");
foreach($answers as $question_id=>$answer)
{
$data = array(
'user_id'=>$this->session->userdata['user_id'],
'question_id'=>$question_id,
'answer'=>$answer,
'student_survey_id' => $insert_id
);
$this->db->insert('survey_answers', $data);
}
}
You can use SESSION[] for keeping last insert id:
public function add_teacher_subject() {
$date = new DateTime("now");
$data = array(
'teacher_id' => $this->input->post('teacher'),
'user_id' => $this->session->userdata['user_id'],
'created_at' => $date->format('Y-m-d H:i:s')
);
$this->db->insert('student_surveys', $data);
$insert_id = $this->db->insert_id();
$newdata = array('insert_id' => $insert_id);
$this->session->set_userdata($newdata);
return $insert_id;
}
public function survey_fill() {
$insert_id = $this->session->userdata('insert_id');
if ($this->input->post('answer')) {
$answers = $this->input->post('answer');
if (null !== ($this->input->post('submit'))) {
$date = new DateTime("now");
foreach ($answers as $question_id => $answer) {
$data = array(
'user_id' => $this->session->userdata['user_id'],
'question_id' => $question_id,
'answer' => $answer,
'student_survey_id' => $insert_id
);
$this->db->insert('survey_answers', $data);
}
}
}
}