Mugluck Mugluck - 10 days ago 7
PHP Question

onetoMany relationships not working or printing the wrong data. Laravel 5.3

So, this is weird. I have been implementing ontoMany relationships between users and various data sets. The first one worked... sort of. I set up the pivot table and what not, the data is correct on both ends of the table but the result when laravel calls the data is not even close:

Let's take this show user data function:

public function show($id)
{
try {
$loc = UserEdit::findorFail($id);
$array = UserEdit::findorFail($id)->toArray();
//$prefs = Ministry_Prefs_User::find($id);
return view('UserEdit', compact('array', 'loc'));

} catch(\Exception $e) {
return \Redirect::route('users.index')
->withMessage('This user does not exist');
}


}


In the blade I print out the tags for their preferences:

Preferences:<br>
{{ $array['Preferences'] }}<br>
@foreach ($loc->prefs_user as $tag)
{{ $tag->tag }}<br>
@endforeach<br><br><br>


The first array prints what's stored in the original untouched user data from the old table I inherited. That's so I can compare and make sure I'm getting the right data from the pivot tables I had to generate from this info. Turns out that was a good idea, coz this is what's printing:

1A-4,1-2,1-3,2-3,3-6,4-7,6-11,8-6,8-10,9-4,7A-4
1A-1
1A-1
1A-1
1A-3
1A-4
1A-5
1A-7
1-1
1-1
1-6
1A-8


I can see no pattern other than alphabetical order? Why would this happen?

The next point is even weirder. Using the same code get's me no results at all from the other pivot tables I've set up:

public function country() {

return $this->belongsToMany('App\Country', 'country_user', 'user_id', 'country_id');
}

public function prefs_user() {

return $this->belongsToMany('App\Prefs_User', 'tag_user', 'user_id', 'tag_id');
}

public function language() {

return $this->belongsToMany('App\language', 'language_user', 'user_id', 'language_id');


Why would this happen? The models look like this:

Prefs_User

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Prefs_User extends Model
{
protected $table = 'prefs';

public function prefs_user() {

return $this->belongsToMany('App\UserEdit', 'tag_user', 'tag_id', 'user_id');
}
}


Country


namespace App;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
protected $table = 'countries';

public function country_user() {

return $this->belongsToMany('App\UserEdit', 'country_user', 'country_id', 'user_id');
}
//protected $fillable = ['region', 'country'];
}


language

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class language extends Model
{
protected $table = 'languages';
//protected $fillable = ['user_id','language_id'];
public function language() {

return $this->belongsToMany('App\UserEdit', 'language_user', 'language_id', 'user_id');
}
}

Answer

Ok. So this was a problem caused by a function of how Laravel works.

After some trial and error, I made a guess that Laravel only checks for id's when using pivot magic methods and does not search for any other data.

So I wrote a function to get the preferences, explode them out into the original tags, then compare that tag against the preference list, get the id associated with that tag and then print it to the pivot table with the other data. For testing and double checking purposes the original tag was initially included, then removed later.

public function move() {
        //get the preferences from the users table (this is stored badly "1-7,3-4,4-6,6-6,6-10,8-5,8-9,8-10,8-13,9-3,9-9") this returns a collection
        $prefs = DB::table('users')->select('id', 'Preferences')->where('Preferences', '!=', '')->get();
            //iterate through each item in the collection
            foreach ($prefs as $pref) {
                 //get the tags only
                 $tags = $pref->Preferences;
                 //break up the tags into a searchable array by exploding each preference at the comma
                 $tag = explode(',', $tags);
                 //for each tag in the array assign it to t
                 foreach ($tag as $t) {
                     //get the id from the preference table when the tag matches t
                     $new = DB::table('prefs')->select('id')->where('tag', $t)->first();
                     //make a new model instance to insert data
                     $taguser = new Tag(array(
                                       'user_id' => $pref->id,
                                       'tag_id' => $t,
                                       'tags' => $new->id
                                      ));
                     //insert data
                     $taguser->save(); //save in table
                     //dd($taguser); <- Since we have a lot of items, dd will break the printout after the first, meaning you can check to see if your information is being handled properly
                 }
             }
             return view('refactor');

getting rid of the original tag-id and replacing it with just the plain id that referenced the tag meant that laravel could now search against the correct data and return useful results.