Delete on Eloquent doesn't delete Laravel 5.4 - laravel

I am trying to make a delete functionality for pictures which users can upload. The model of the picture class:
class Picture extends Model
{
use SoftDeletes;
/**
* The attributes that are mass assignable.
* #var array
*/
protected $fillable = ['original_file', 'resized_file'];
/**
* The attributes that should be mutated to dates.
* #var array
*/
protected $dates = ['deleted_at'];
/**
* Get the category that owns the question.
*/
public function user()
{
return $this->belongsTo(User::class);
}
Migration:
$table->timestamps();
$table->softDeletes();
The delete function which I have:
public function destroyProgress(Picture $progress){
$progress->delete();
dd($progress);
return view('client.home.profile', ['user' => Auth::user()]);
}
This code is executed and stoped at the dd($progress);. I would expect that this would return null because the $progress has been deleted. But this still returns an instance! Could someone please explain to me what I am doing wrong because I am lost for words.

Hard to explain, the object $progress created by dependency injection is not actually a model instance. Therefore, the delete event will not be fired.
You should use delete method on a model instance:
$picture = App\Picture::find(1);
$picture->delete();

Related

Laravel many to many relation not working

I'm trying to fetch data from a relationship but only relationship properties are returned.
User Model
class User extends Authenticatable {
use SoftDeletes; use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [ 'name', 'email', ];
/*
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [ 'password', 'remember_token' ];
/*
* Get the images for the store.
*/
public function stores() {
return $this->belongsToMany('App\Store', 'store_user');
}
}
Stores Model
public function users() {
return $this->belongsToMany('App\User');
}
Pivot Table
public function up() {
Schema::dropIfExists('store_user');
Schema::create('store_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('store_id');
$table->integer('user_id');
$table->timestamps();
});
}
Existing relations between pivot table and ids are accurate.
Retrieving relations
$user = Auth::user();
$userStores = $user->stores;
$storesID = [];
foreach ($userStores as $store) {
$storesID[] = $store->id;
}
$builder->whereIn('store_id', $storesID);
This returns:
Undefined property: App\User::$stores
I tried
$userStores = $user->stores()->get();
but that freezes the page until it throws a request took more than 60 seconds error.
Do you have any idea what I'm doing wrong?
The problem is 100% inside of your OwnerScope file, you should review that file first and then review the line where you assigned $builder it's value, I can't be of more help because you didn't include code from either so it's all we can do until you update your question and include both.
Looks like $user is not logged in, maybe check first with:
if (Auth::check()) {
}

Defining many-to-many bidirectional relations more eloquently

I have implemented the relationship without Eloquent but I was wondering is there was a way to define this relationship in Eloquent so that my application can have more consistency.
table User
-id
-other user attributes
table friend_requests:
-id
-sender_id
-reciever_id
table friends
-id
-first
-second
The friendRequest relation has been easily implemented in the Eloquent but the problem lies in Friends.
If I do this in the User model class:
public function friends(){
return $this->belongsToMany(User::class,'friends','first','second');
}
This wouldn't work as you would have noticed. Let me explain with example:
Table: friends
id | first | second
1 | 1 | 2
2 | 3 | 1
you see that user_1 is friends with user_2 as well as user_3 as the relationship is bi-directional. But Eloquent will naturally return that user_1 is friends with user_2 only. After thinking for a while I tweaked the statement but made little progress'
public function friends(){
return $this->belongsToMany(User::class,'friends','first','second')
->orWhere('second',$this->id);
}
That is because now it selects both rows but the Users it returns are those whose id = second which means that in the second case it will return the user itself.
I implemented the relations with my own methods in User model class which use DB::table('friends')-> to addFriend(User $user), removeFriend(user $user) and returns list of friends(), but I'm disappointed that this isn't as eloquent as Eloquent relationships.
Perhaps some more experienced developers here would have come across this kind of problem and would have dealt better than I did. How do you propose I deal with this problem. Should I stick with my approach or is there a better way to deal with it?
A more manageable way to implement bidirectional relations would be to create two entries for each confirmed friendship.
So a user would make a friend request to another user. When the second user confirms the friend request, two friendships are created.
Example Controller
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use App\FriendRequest;
use App\Friendship;
class FriendshipController extends Controller
{
public function friendRequest(Request $request)
{
$receiver_id = $request->input('receiver_id');
$request->user()->friend_offers()->create([
'receiver_id' => $receiver_id
]);
}
public function friendshipConfirmation(Request $request)
{
$friend_request_id = $request->input('friend_request_id');
$friend_request = FriendRequest::find($friend_request_id);
$friend_request->receiver->friendships()->create([
'user_2_id' => $friend_request->sender->id
]);
$friend_request->sender->friendships()->create([
'user_2_id' => $friend_request->receiver->id
]);
}
}
Database Tables
(Note the proper spelling of receiver and plural users table)
table users
- id
- other user attributes
table friend_requests:
- id
- sender_id
- receiver_id
table friendships
- id
- user_1_id
- user_2_id
User Model
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable
{
use SoftDeletes;
public $timestamps = true;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
//
];
/**
* Return friend requests from other users
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function friend_requests()
{
return $this->hasMany(FriendRequest::class, 'receiver_id');
}
/**
* Return friend requests sent to other users
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function friend_offers()
{
return $this->hasMany(FriendRequest::class, 'sender_id');
}
/**
* Return friendships with other users
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function friendships()
{
return $this->hasMany(Friendship::class, 'user_1_id');
}
}
FriendRequest Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class FriendRequest extends Model
{
use SoftDeletes;
public $timestamps = true;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'sender_id',
'receiver_id'
];
/**
* Return the requesting user
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function sender()
{
return $this->belongsTo(User::class, 'sender_id');
}
/**
* Return the receiving user
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function receiver()
{
return $this->belongsTo(User::class, 'receiver_id');
}
}
Friendship Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Friendship extends Model
{
use SoftDeletes;
public $timestamps = true;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_1_id',
'user_2_id'
];
/**
* Return user_1
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function first()
{
return $this->belongsTo(User::class, 'user_1_id');
}
/**
* Return user_2
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function second()
{
return $this->belongsTo(User::class, 'user_2_id');
}
}

Laravel Model accessing a value of an instance of its self

I've got a model and the model its self could be linked to multiple other databases but only one at a time.
Instead of having a eloquent method for all the possible databases; it could have one that will use a variable from the self instance to choose the database and return just that.
It will save alot of work, as returning each one and testing to see if there are any results is cumbersome.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Feature extends Model
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'companies';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'db_name',
'enabled',
];
/**
* Uses the its own database name to determine which input to return.
*/
public function inputs() {
// if this->hidden->db_name == 'input type 1'
// return $this->HasMany(InputType1::class);
.... and so on
} // end function inputs
}
This is definitely a strange behaviour but I think you can achieve what you are looking for like so :
//in your model
public function inputs()
{
switch ($this->attributes['db_name']) {
case : 'input type 1':
return $this->hasMany(InputType1::class);
case : //some other database name
return //another relation
}
}
Expanding on shempognon answer, what I actually got to work was
switch($this->db_name) {
case 'Input_Timesheet':
return $this->hasMany(Input_type1::class);
}

Call to a member function on a non-object eloquent attach

I am having an issue with laravel not seeing my tags() method for attaching new tags on a new entry. I keep getting Call to a member function on a non-object when I try to run the method and attach tags to my Tile model. All methods are returning their relations. I followed the same order as the documentation says eloquent.
Controller
$tile = \Tiles\Tile::find($tile_id);
$tile->tags()->attach($tag_array);
Model
<?php namespace Tiles;
use Illuminate\Database\Eloquent\Model;
class Tile extends Model {
/**
* The Tile table
* #var string
*/
protected $table = 'tiles';
/**
* Pivot table for tags
* #var string
*/
protected $pivot = 'tag_tile';
/**
* Get the tags associated with the given tile
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags() {
return $this->belongsToMany('Tiles\Tag', $this->pivot, 'tile_id', 'tag_id')->withTimestamps();
}
}
Try it
Model
public function tags() {
return $this->belongsToMany('Tiles\Tag', $this->pivot, 'tag_id', 'tile_id')->withTimestamps();
}
Thanks for all your help. I figured out the solution. I created a method in my model and pushed each to an array and fed it to the attach method. It works now.

Laravel Resource Router ignoring eager loaded data and getting a new query

In my resource router, I have this function, which is supposed to eager load only the rows that have the configureName of $id. The problem is that when I call $demo->demoSettings resource router is ignoring my eager load and grabbing all of the demoSettings related to this $demo.
This isn't the only instance of this problem that I have. I also have a couple loops where I am injecting data into my api index from related tables for convenience purposes. The moment I add a call to access my eager loaded data, it queries again and injects the data into my resource return. I've worked around it by using unset in the other instances, but this one is different because I actually want the list of data, rather than a single value.
public function show($demoId,$id)
{
$demo = Demo::with(array('DemoSettings' => function($query) use ($id)
{
$query->where('configureName', '=', $id);
}))->where('demoId','=',$demoId)->first();
return $demo->demoSettings;
}
Demo Model
class Demo extends Eloquent {
protected $table = 'Demo';
public $timestamps = false;
/**
* The key column used by the model.
* #var string
*/
protected $primaryKey = 'idDemos';
/**
* one(demo) to many(demoSettings) relationship
* #return array of the demoSettings associated with the demo
*/
public function demoSettings()
{
return $this->hasMany('DemoSettings','idDemos','idDemos')->orderBy('configureName','asc');
}
}
DemoSettings Model
class DemoSettings extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'DemoSettings';
/**
* The key column used by the model.
* #var string
*/
protected $primaryKey = 'idDemoSettings';
/**
* many(demoSettings) to one(demo) relationship
* #return demo the parent record
*/
public function demo()
{
return $this->belongsTo('Demo','idDemos','idDemos');
}
}
Route
Route::group(array('prefix' => 'api/v1'), function(){
Route::group(array('prefix' => 'demos'), function(){
Route::resource('/', 'api_DemosController', array('only' => array('index','store','destroy','show')));
Route::resource('/{demoId}/settings', 'api_DemoSettingsController', array('only' => array('index','store','show')));
});
});

Resources