Unable to create data through show method in Laravel 5.3 - php

I am working on notifications I have 2 tables: one is notify and the other is notify_status. Through notify I am showing data like title and description and in notify_status I have field read_status which is by default 0. After I show it I want to change it to 1. I also have notify_id in it as a foreign key. This is my show method:
public function show($id)
{
$notify = Notify::find($id);
$notify_status = NotifyStatus::where('notify_id', $id)->get();
$user_data['read_status'] = 1;
$user = NotifyStatus::create($user_data);
return view('notify.desr')->with(compact('notify'));
}
But it isn't creating against notify_id. What should I do?

Your models should define the following relationships:
class Notify extends Model
{
public function setAsRead()
{
$this->status->read_status = 1
$this->status->save();
}
public function wasRead()
{
return (bool) $this->status->read_status;
}
public function status()
{
return $this->hasOne(NotifyStatus::class);
}
}
class NotifyStatus extends Model
{
public function notify()
{
return $this->belongsTo(Notify::class);
}
}
Take a look at Laravel Eloquent Relationships for further reading.
In your controller you can use it like:
$notify = Notify::find($id);
$notify->status->read_status = 1;
$notify->status->save();
return view('notify.desr')->with(compact('notify'));
Or you can simply create a new method to set the new status (take a look at first method of Notify class):
$notify = Notify::find($id);
$notify->setAsRead();
return view('notify.desr')->with(compact('notify'));

public function show($id)
{
$notify = Notify::find($id);
$notify_status = NotifyStatus::where('notify_id', $id)->first();
$notify_status->read_status = 1;
$notify_status->save()
return view('notify.desr')->with(compact('notify'));
}

Related

Returning furnitures of each Person in the controller

I have this controller and I would like to return each person's furniture. This 'chilren' method didn't work. The relationship between the two 'one to many' is working correctly. It isn't mandatory to use children method. Any resource to solve the problem is accetable.
IMPORTANT: Laravel Version 5.8
PersonController.php
public function showPersonFurnitures($id) {
$person = Person::findOrFail($id);
$furnituresOfEachPerson = $person->childs();
return response()->json($furnituresOfEachPerson);
}
you are not triggering the query :
use this (with eager loading)
public function showPersonFurnitures($id) {
$person = Person::with('childs')->findOrFail($id);
$furnituresOfEachPerson = $person->childs;
return response()->json($furnituresOfEachPerson);
}
or this : (calling the relationship directly)
public function showPersonFurnitures($id) {
$person = Person::findOrFail($id);
$furnituresOfEachPerson = $person->childs()->get();
return response()->json($furnituresOfEachPerson);
}
or third option if the person->childs() relationship is a belongsTo :
public function showPersonFurnitures($id) {
$furnituresOfEachPerson = Child::where('person_id', $id)->get();
return response()->json($furnituresOfEachPerson);
}

How to get ID from a relationship table, Laravel

I have 4 table : Users, CompanyRegister, VoucherDetails, Addvoucher.
So the Authenticate Users Id will be submit as user_id in companyRegister table,and then companyRegister ID will be submit as company_id in Voucherdetails table, and lastly voucherDetails Id will be submit in addVoucher table as voucher_ID. I am new to using eloquent and also laravel, I cant understand why I cant get the id from voucherdetails and submit in addvoucher but I can get id from companyregister and submit in company_id in voucherdetails. I'm using the same method to get id but not work, I hope can get solution and explanation here,Thank you in advance!!
My users model
public function companyregisters()
{
return $this->hasOne('App\companyregisters');
}
public function voucherdetails()
{
return $this->hasMany('App\voucherdetails');
}
public function addvoucher()
{
return $this->hasMany('App\addvoucher');
}
public function roles()
{
return $this->belongsToMany('App\role');
}
public function hasAnyRoles($roles)
{
if($this->roles()->whereIn('name', $roles)->first()){
return true;
}
return false;
}
public function hasRole($role)
{
if($this->roles()->where('name', $role)->first()){
return true;
}
return false;
}
my companyregister model
public function User(){
return $this->belongsTo('App\User');
}
public function voucherdetails()
{
return $this->hasMany('App\voucherdetails');
}
my voucherdetails model
public function User(){
return $this->belongsTo('User');
}
public function companyregisters(){
return $this->belongsTo('App\companyregisters');
}
public function addvoucher()
{
return $this->hasOne('App\addvoucher');
}
my addvoucher model
public function User(){
return $this->belongsTo('App\User');
}
public function voucherdetails(){
return $this->belongsTo('App\voucherdetails');
}
my voucherdetailsController
public function store(Request $request){
$voucherdetail = new voucherdetails();
$voucherdetail->title = $request->input('title');
$voucherdetail->description = $request->input('description');
$voucherdetail->user_id = Auth::user()->id;
$id = Auth::user()->id;
$user = User::find($id);
$company = $user->companyregisters;
$companyId = $company->id;
$voucherdetail->company_id = $companyId;
$voucherdetail->save();
return redirect()->to('addvoucher');
}
my addvoucherController
public function store(Request $request){
$addvoucher = new addvoucher();
$addvoucher->voucherTitle = $request->input('voucherTitle');
$addvoucher->voucherCode = $request->input('voucherCode');
$addvoucher->user_id = Auth::user()->id;
//Here(the voucherdetails id cant get to submit in voucher_id)
$id = Auth::user()->id;
$user = User::find($id);
$voucher = $user->voucherdetails;
$voucherID = $voucher->id;
$addvoucher->voucher_id = $voucherID;
$addvoucher->save();
return redirect()->to('displayVouchers');
}
This code works because companyregisters is a hasOne relationship for which the docs say:
Once the relationship is defined, we may retrieve the related record
using Eloquent's dynamic properties.
public function companyregisters()
{
return $this->hasOne('App\companyregisters');
}
$company = $user->companyregisters; // ie this returns the single related record
$companyId = $company->id; // and it has an `id` property, all good here
However, this code fails because voucherdetails is a hasMany relationship for which the docs say:
Once the relationship has been defined, we can access the "collection"
of comments by accessing the comments property.
More info on collections
public function voucherdetails()
{
return $this->hasMany('App\voucherdetails');
}
$voucher = $user->voucherdetails; // ie this returns a "collection" of related records
$voucherID = $voucher->id; // this "collection" does NOT have an id property, but each record IN the collection does.
In summary, either your relationship is defined incorrectly (hasMany vs hasOne) or, you'll need to loop over the related records to get the id from each.

Delete record from one-to-many relationship

I have 3 tables:
users
id
role
email
typable_id
typable_type
buyers
id
name
address
avatar
email
residential_id
residentials
id
name
city
state
And here is my model that shows the relationship
User.php
public function typable()
{
return $this->morphTo();
}
Buyer.php
public function residential()
{
return $this->belongsTo(Residential::class);
}
public function user()
{
return $this->morphMany(User::class, 'typable');
}
Residential.php
public function buyer()
{
return $this->hasMany(Buyer::class);
}
If I want to delete the residential, all buyers from that residential need to be deleted. Same as users need to be deleted too when the buyers is deleted. How can I do that? This is what insides my Residential Controller for destroy function.
ResidentialController
public function destroy(Request $request)
{
$residentials = Residential::find($request->input('id'));
$residentials->id = $request->input('id');
$residentials->name = $request->input('name');
$residentials->delete($residentials);
return response()->json($residentials);
}
I have tried to put this code to delete the buyers (for users not yet) inside destroy() but nothing is changed for the buyers to be deleted.
$buyers = Buyer::where('residential_id','=',$request->residential_id)->first(); $buyers->delete($buyers);
While this is the code that I managed to do if I want to delete the buyers, the users are deleted too.
BuyerController
public function destroy(Request $request)
{
$users = User::where('email', '=', $request->email)->first();
$buyers = Buyer::find($request->input('id'));
$buyers->id = $request->input('id');
$buyers->name = $request->input('name');
$buyers->delete($buyers);
$users->delete($users);
return response()->json($buyers);
}
I hope there is someone to help and teach me the correct way.
Approach-1
you can override the delete function for any model.
//Residential.php
public function delete()
{
$this->buyer->delete();
return parent::delete();
}
//Buyer.php
public function delete()
{
$this->user->delete();
return parent::delete();
}
Now when you delete any Residential record, the chain will first delete any related user and then delete buyer and finally delete the Residential record.
Approach-2
You can use each() method to get all relating buyer and then get all relating user.
$residentials->buyer
->each(function ($b) {
$b->user->each(function ($u) {
$u->delete();
});
$b->delete();
});
$residentials->delete();
You might want to register model events to handle that:
class Residential extends Model
{
// Lets use plural form for a HasMany relationship.
public function buyers()
{
return $this->hasMany(Buyer::class);
}
protected static function booted()
{
static::deleting(function ($user) {
// I am using Higher Order Message, check this out: https://laravel.com/docs/8.x/collections#higher-order-messages
$this->buyers->each->delete();
});
}
}
class Buyer extends Model
{
// Lets use the plural form for a MorpMany relationship.
public function users()
{
return $this->morphMany(User::class, 'typable');
}
protected static function booted()
{
static::deleting(function ($user) {
$this->users->each->delete();
});
}
}
And you only have to remove a single object in your controller:
class ResidentialController
{
public function destroy(Request $request)
{
$residential = Residential::findOrFail($request->input('id'));
$residential->delete();
// The framework is gonna automatically convert this to a JSON object.
return $residential;
}
}
class BuyerController
{
public function destroy(Request $request)
{
$buyer = Buyer::findOrFail($request->input('id'));
$buyer->delete();
// The framework is gonna automatically convert this to a JSON object.
return $buyer;
}
}

Trying to fill the intermediate table using attach() but getting "Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::attach()"

I have tables called users, places and user_place. users has a column called id that contains the id of the user and places has a column called place_id as well. The user_place table has 2 columns called user_id and place_id and I'm trying to automatically populate them with the corresponding ids. I read I have to use attach() function after setting up the relationships which I believe I have done but I might be wrong. Here they are:
class PlaceController extends Controller
{
public function likePlace(Request $request){
$placeId = $request['placeId'];
$userId = $request['userId'];
$user = User::where('id', $userId)->first();
$place = new Place();
$place->place_id = $placeId;
$place->save();
$user->places()->attach($place);
}
}
User model:
class User extends \Eloquent implements Authenticatable
{
use AuthenticableTrait;
public function places(){
return $this->hasMany('App\Place');
}
}
Place mode:
class Place extends Model
{
public function user(){
return $this->belongsToMany('App\User');
}
}
In a Many to Many relationship, you should define both relationships like the following:
User.php
class User extends \Eloquent implements Authenticatable
{
use AuthenticableTrait;
public function places()
{
return $this->belongsToMany('App\Place', 'user_place', 'user_id', 'place_id');
} // ^^^^^^^^^^^^
}
Note: Given that your intermetiate table name doesn't follow the naming convention we specified so Laravel knows where table to look up.
Place.php
Notice that you mentioned that the primmary key of your Place model is place_id, and this also scapes from the Laravel convention you should specify it:
protected $primaryKey = 'place_id'; // <----
class Place extends Model
{
public function user()
{
return $this->belongsToMany('App\User', 'user_place', 'place_id', 'user_id');
}
}
So now in your controller:
class PlaceController extends Controller
{
public function likePlace(Request $request)
{
$placeId = $request['placeId'];
$userId = $request['userId'];
$user = User::where('id', $userId)->first();
$place = new Place();
$place->place_id = $placeId;
$place->save();
$user->places()->attach($place);
}
}
Side note
As I side note, you could save a couple of line replacing some sentences with their equivalent:
$userId = $request['userId'];
$user = User::where('id', $userId)->first();
Using the find() method, this is equal to:
$user = User::find($request['userId']);
Then, you could create your related object using the static method create of an Eloquent model so this:
$placeId = $request['placeId'];
$place = new Place();
$place->place_id = $placeId;
$place->save();
Is equal to this:
$place = Place::create(['place_id' => $request['placeId']]);
Then your controller will be reduced to this:
class PlaceController extends Controller
{
public function likePlace(Request $request)
{
$user = User::find($request['userId']);
$place = Place::create(['place_id' => $request['placeId']]);
$user->places()->attach($place);
}
}

How to dynamically set table name in Eloquent Model

I am new to Laravel. I am trying to use Eloquent Model to access data in DB.
I have tables that shares similarities such as table name.
So I want to use one Model to access several tables in DB like below but without luck.
Is there any way to set table name dynamically?
Any suggestion or advice would be appreciated. Thank you in advance.
Model:
class ProductLog extends Model
{
public $timestamps = false;
public function __construct($type = null) {
parent::__construct();
$this->setTable($type);
}
}
Controller:
public function index($type, $id) {
$productLog = new ProductLog($type);
$contents = $productLog::all();
return response($contents, 200);
}
Solution For those who suffer from same problem:
I was able to change table name by the way #Mahdi Younesi suggested.
And I was able to add where conditions by like below
$productLog = new ProductLog;
$productLog->setTable('LogEmail');
$logInstance = $productLog->where('origin_id', $carrier_id)
->where('origin_type', 2);
The following trait allows for passing on the table name during hydration.
trait BindsDynamically
{
protected $connection = null;
protected $table = null;
public function bind(string $connection, string $table)
{
$this->setConnection($connection);
$this->setTable($table);
}
public function newInstance($attributes = [], $exists = false)
{
// Overridden in order to allow for late table binding.
$model = parent::newInstance($attributes, $exists);
$model->setTable($this->table);
return $model;
}
}
Here is how to use it:
class ProductLog extends Model
{
use BindsDynamically;
}
Call the method on instance like this:
public function index()
{
$productLog = new ProductLog;
$productLog->setTable('anotherTableName');
$productLog->get(); // select * from anotherTableName
$productLog->myTestProp = 'test';
$productLog->save(); // now saves into anotherTableName
}
I created a package for this: Laravel Dynamic Model
Feel free to use it:
https://github.com/laracraft-tech/laravel-dynamic-model
This basically allows you to do something like this:
$foo = App::make(DynamicModel::class, ['table_name' => 'foo']);
$foo->create([
'col1' => 'asdf',
'col2' => 123
]);
$faz = App::make(DynamicModel::class, ['table_name' => 'faz']);
$faz->create([...]);

Categories