Laravel 4 deleting multiple models related by foreign keys - php

So I have three models and when when one of them dAgency is deleted delete-() I'd like all three to be deleted. The problem is that two of them are being deleted, while the top parent one DemDataSet isn't being deleted. Additionally, when I call:
echo "<pre>", dd(dAgency::find(21)->DemographicReport()->DemDataSet()->get()), "</pre>";
I get this error: Call to undefined method Illuminate\Database\Query\Builder::DemDataSet() But when I try:
echo "<pre>", dd(dAgency::find(21)->DemographicReport()->get()), "</pre>";
It works. So I know the problem is my relation between my DemDataSet model. Below is my model:
<?php
class DemDataSet extends Eloquent {
public $timestamps = false;
protected $connection = 'epcr_dem_data';
protected $table = 'DEMDataSet';
protected $primaryKey = 'pk_DEMDataSet';
public function DemographicReport(){
return $this->hasOne('DemographicReport','fk_DEMDataSet','pk_DEMDataSet');
}
}
class DemographicReport extends Eloquent {
public $timestamps = false;
protected $connection = 'epcr_dem_data';
protected $table = 'DemographicReport';
protected $primaryKey = 'pk_DemographicReport';
public function DemDataSet (){
return $this->belongsTo('DemDataSet','fk_DEMDataSet','pk_DEMDataSet');
}
public function dAgency(){
return $this->hasOne('dAgency','fk_DemographicReport','pk_DemographicReport');
}
public function delete(){
parent::delete();
return $this->DemDataSet()->delete();
}
}
class dAgency extends Eloquent {
public $timestamps = false;
protected $connection = 'epcr_dem_data';
protected $table = 'dAgency';
protected $primaryKey = 'pk_dAgency';
public function DemographicReport(){
return $this->belongsTo('DemographicReport','fk_DemographicReport','pk_DemographicReport');
}
public function dAgency_10(){
return $this->hasMany('dAgency_10','fk_dAgency','pk_dAgency');
}
public function delete(){
parent::delete();
return $this->DemographicReport->delete();
}
}
?>
I've been wrestling with this one for two days now! I really appreciate you taking the time to look at this.

The right way to query laravel model with relationship is this way:
//This is to pull all DemDataSet from DemographicReport
dAgency::find(21)->DemographicReport()->first()->DemDataSet;
//If you need further query, then you call DemDataSet as a method
dAgency::find(21)->DemographicReport()->first()->DemDataSet()->where('your condition here')->get();

Related

Laravel - using inRandomOrder() on belongsToMany RelationShips

in this code as:
$latestHerbsInformation = \App\ContentCategories::find('14')->contents->take(5);
which that work fine i want to use inRandomOrder() to get random rows from contents, Contents and ContentCategories are belongsToMany RelationShips and this code:
$latestHerbsInformation = \App\ContentCategories::find('14')->contents->inRandomOrder()->take(5);
don't work for me.
Contents model:
class Contents extends Model
{
use Sluggable;
protected $table = 'contents';
protected $guarded = ['id'];
public function categories()
{
return $this->belongsToMany(ContentCategories::class);
}
}
ContentCategories model:
class ContentCategories extends Model
{
protected $table = 'contents_categories';
protected $guarded = ['id'];
public function contents()
{
return $this->belongsToMany(Contents::class);
}
}
i get this error:
Method inRandomOrder does not exist.
how can i solve this problem? Thanks in advance
The correct query is:
\App\ContentCategories::find('14')->contents()->inRandomOrder()->take(5)->get();
Because this will execute the query and will return a collection:
\App\ContentCategories::find('14')->contents

Delete hasManyThrough relationship rows using Laravel's Eloquent

I have three models, Advertiser, PtcAd, and PtcCampaign. When deleting a Advertiser I want to delete all related PtcAds and PtcCampaigns. The Advertiser has many PtcCampaigns through PtcAds.
Advertiser Model
use SoftDeletes;
protected $dates = ['deleted_at'];
public function ptcAds()
{
return $this->hasMany('App\PtcAd');
}
public function ptcCampaigns()
{
return $this->hasManyThrough('App\PtcCampaign', 'App\PtcAd');
}
public function delete()
{
$this->ptcAds()->delete();
// I'VE TRIED WITH AND WITHOUT THIS
$this->ptcCampaigns()->delete();
return parent::delete();
}
PtcAd Model
use SoftDeletes;
protected $fillable = ['advertiser_id', 'title'];
protected $dates = ['deleted_at'];
public function advertiser()
{
return $this->belongsTo('App\Advertiser');
}
public function ptcCampaigns()
{
return $this->hasMany('App\ptcCampaign');
}
public function delete()
{
$this->ptcCampaigns()->delete();
return parent::delete();
}
PtcCampaign Model
use SoftDeletes;
public $timestamps = false;
protected $fillable = ['ptc_ad_id', 'clicks'];
protected $dates = ['paused_at', 'deleted_at'];
public function ptcAd()
{
return $this->belongsTo('App\PtcAd');
}
My tests:
public function test_delete_advertiser()
{
$advertiser = factory(Advertiser::class)->create();
$ptcAd = factory(PtcAd::class)->create(['advertiser_id' => $advertiser->id]);
$ptcCampaign = factory(PtcCampaign::class)->create(['ptc_ad_id' => $ptcAd->id]);
$this->assertTrue($advertiser->delete());
$this->assertFalse(Advertiser::all()->contains($advertiser));
$this->assertFalse(PtcAd::all()->contains($ptcAd));
// THE FOLLOWING TEST DOESN'T WORK!
$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign));
}
// ALL OF THE FOLLOWING TESTS WORK!
public function test_delete_ad()
{
$ptcAd = factory(PtcAd::class)->create();
$ptcCampaign = factory(PtcCampaign::class)->create(['ptc_ad_id' => $ptcAd->id]);
$this->assertTrue($ptcAd->delete());
$this->assertFalse(PtcAd::all()->contains($ptcAd));
$this->assertFalse(PtcCampaign::all()->contains($ptcCampaign));
}
The $this->assertFalse(PtcCampaign::all()->contains($ptcCampaign)) in the test_delete_advertiser() test fails, why?
I have more tests to make sure all the relationships work so I really don't know what could possibly be wrong. My next attempt would be to make foreach in the Advertiser's delete() method but maybe there's something simpler and I want to understand why this doesn't work.
It looks the problem is with the sequence of delete statement.
Try by changing the sequence like below:
public function delete()
{
$this->ptcCampaigns()->delete();
$this->ptcAds()->delete();
return parent::delete();
}
You can use Laravel's Model Events (deleting) to delete related models like this:
class Advertiser extends Eloquent
{
public function ptcAds()
{
return $this->hasMany('PtcAd');
}
// this is a recommended way to declare event handlers
protected static function boot() {
parent::boot();
static::deleting(function($adv) { // before delete() method call this
$adv->ptcAds()->delete();
// do the rest of the cleanup...
});
}
}
// Same for PtcCompaigns
class PtcAd extends Eloquent
{
public function ptcCompaigns()
{
return $this->hasMany('PtcCompaigns');
}
// this is a recommended way to declare event handlers
protected static function boot() {
parent::boot();
static::deleting(function($ptc_ad) { // before delete() method call this
$ptc_ad->ptcCompaigns()->delete();
// do the rest of the cleanup...
});
}
}
Hope this helps!

eloquent boot not firing only for one class

I'm using eloquent for a project and I would like to delete articles. The problem is that the database is complicated. There are articles, that have article_lvl1 and article_lvl1 have article_lvl2. When I delete an article the event functions work fine :
<?php
namespace app\model;
class Article extends \Illuminate\Database\Eloquent\Model
{
public static function boot()
{
parent::boot();
// cause a delete of a product to cascade to children so they are also deleted
static::deleting(function($article)
{
$article->ArticleNiveau1()->delete();
$article->ArticleNiveau2()->delete();
});
}
public function ArticleNiveau1()
{
return $this->hasMany('app\model\ArticleNiveau1', 'id_article');
}
public function ArticleNiveau2()
{
return $this->hasMany('app\model\ArticleNiveau2', 'id_article');
}
protected $table = 'Article';
public $timestamps = false;
protected $primaryKey = 'id_article';
}
But an article can also have article_Informations, which can have article_Date. My problem is that everything in the boot functions executes fine on delete, but not the article_Date. Here is the code :
<?php
namespace app\model;
class Article_Informations extends \Illuminate\Database\Eloquent\Model
{
public function Article()
{
return $this->belongsTo('app\model\Article', 'id_article');
}
public function ArticleNiveau1()
{
return $this->belongsTo('app\model\ArticleNiveau1', 'id_nv1');
}
public function ArticleNiveau2()
{
return $this->belongsTo('app\model\ArticleNiveau2', 'id_nv2');
}
public function Article_Date()
{
return $this->hasMany('app\model\Article_Date', 'id_info');
}
public static function boot()
{
parent::boot();
// cause a delete of a product to cascade to children so they are also deleted
static::deleting(function($info)
{
$info->Article_Date()->delete();
});
}
protected $table = 'Article_Informations';
public $timestamps = false;
protected $primaryKey = 'id_info';
}
I don't know why, it's the only event that is not fired on delete.
Can someone explain me ?

Accessing nested relationship with Laravel 4

I'm having trouble figuring out how to access a nested relationship within Laravel. The specific example I have is a Movie that has many entires in my Cast table which has one entry in my People table. These are my models:
MOVIE
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
MOVIECAST
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public function person()
{
return $this->hasOne('Person', 'person_id');
}
public function netflix()
{
return $this->belongsTo('Movie', 'movie_id');
}
}
PERSON
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}
In my controller I can access the cast (containing person_id and role_id) like so:
public function movie($id)
{
$movie = Movie::find($id);
$cast = $movie->cast();
return View::make('movie')->with(array(
'movie' => $movie,
'cast' => $cast
));
}
...but I don't know how to access the corresponding name field in my People table.
EDIT 1:
Using the classes exactly as defined below in #msturdy's answer, with the controller method above I try to render the person names like so inside my view:
#foreach($cast->person as $cast_member)
{{$cast_member->person->name}}
#endforeach
Doing this i get the error:
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$person
I don't know if it makes a difference or not but I have no id field on my People table. person_id is the primary key.
It should be simple, once you have accessed the cast...
Route::get('movies', function()
{
$movie = Movie::find(1);
$cast = $movie->cast;
return View::make('movies')->with(array(
'movie' => $movie,
'cast' => $cast));
});
Note: at this point, $cast is an instance of the Collection class, not a single object of the MovieCast class, as the
relationship is defined with hasMany()
you can iterate over it in the View (in my case /app/views/movies.blade.php
#foreach($cast as $cast_member)
<p>{{ $cast_member->person->name }}</p>
#endforeach
Class definitions used for testing:
class Movie extends Eloquent {
protected $primaryKey = 'movie_id';
protected $table = 'movie';
public $timestamps = false;
// Relationships
public function cast()
{
return $this->hasMany('MovieCast', 'movie_id');
}
}
class MovieCast extends Eloquent {
protected $table = 'movie_cast';
public $timestamps = false;
public function person()
{
return $this->hasOne('Person', 'person_id');
}
}
class Person extends Eloquent {
protected $primaryKey = 'person_id';
protected $table = 'people';
public $timestamps = false;
public function movieCast()
{
return $this->belongsTo('MovieCast', 'person_id');
}
}

Eloquent ORM Movie Location

I am using Laravel 4 and eloquent orm to build a movie session database.
Now I have the following Models.
class Location extends \Eloquent
{
public $timestamps = false;
public $table = 'movsys_location';
protected $fillable = array('name', 'desc');
public function sessions(){
return $this->hasMany('Session', 'location_id');
}
}
class Session extends \Eloquent
{
public $timestamps = false;
public $table = 'movsys_session';
protected $fillable = array('time');
public function location(){
return $this->hasOne('Location', 'id');
}
}
(Note: These models are stripped to the necessary code.)
Now in my controller, I have the following.
$Sessions = Session::all();
foreach($Sessions as $Session){
echo (isset($Session->location->name) ? $Session->location->name : 'NO LOCATION');
}
And this is what my database looks like:
Now, everything seems to work, but even though both sessions have the same location, ONLY the first session will return the name of the location! The second echo will return "NO LOCATION".
Any idea or help as to why would be appreciated. If this answer isnt clear enough let me know.
Try this one in place of yours:
class Session extends \Eloquent
{
public $timestamps = false;
public $table = 'movsys_session';
protected $fillable = array('time');
public function location(){
return $this->belongsTo('Location');
}
}

Categories