Laravel 5 Seeding Pivot Tables - laravel

I was watching the following lesson and was following along with Roles and Permissions however now I"m to seeding my pivot table with a Seeder class but not sure how I should accomplish this.
https://laracasts.com/series/whats-new-in-laravel-5-1/episodes/16
This is the sort of thing I have right now but obviously with the givePermissionTo() inside of the Role model I'm sure there is a better way of handling this. I have a feeling I don't even need a PermissionRole model. The big issue here is that I run it for all 5 different roles and about 63 different permissions.
<?php
use Illuminate\Database\Seeder;
use App\PermissionRole;
class PermissionRoleTableSeeder extends Seeder
{
public function run()
{
PermissionRole::create([
'role_id' => 5,
'permission_id' => '1',
]);
PermissionRole::create([
'role_id' => 5,
'permission_id' => '2',
]);
PermissionRole::create([
'role_id' => 5,
'permission_id' => '3',
]);
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
public function givePermissionTo(Permission $permission)
{
return $this->permissions()->save();
}
public function users()
{
return $this->hasMany(User::class);
}
}
Can someone hint as to what that is?

You usually shouldn't have a model for your pivot table, although there are times when it makes sense to have it in the event you have an additional key in the pivot table which points to a table which isn't part of the belongs to many relationship. For example, if you had a created_by field in your pivot table which would be the id of the user which created that relation.
With that said, it also should not hurt anything to have a model for your pivot table to help you work with it directly like you are doing.
To see the table without the model, I'd use the Laravel functions provided. I don't know how that givePermissionTo function is supposed to work because you aren't actually using the argument provided.
I'd put some constraints on this, but one way you could do it would be to use the sync function. This will give all roles all permissions.
$roles = \App\Role::all();
$permissions = \App\Permission::all();
foreach($roles as $role) {
$role->permissions()->sync($permissions);
}

Related

Laravel cannot get relationship data of a selected profile

I just created a profile for users, and wish to show the education details related to the logged-in user or another selected user.
for this, I created an education model for users and gave a proper relationship to it both the sides. im not able to get any data from the education table of loged in user or another user. i used foreach tag in blade file. please revview my code. thanks.
Education Model
class Education extends Model
{
use HasFactory;
protected $primaryKey = 'education_id';
public function myusers()
{
return $this->belongsTo('App\Models\User','user_id','education_id');
}
}
User Model
public function myeducation()
{
return $this->hasMany('App\Models\Education','education_id','user_id');
}
Profile Controller
public function index()
{
$user = Auth::user();
return view('candidate.profile',['user'=>$user,]);
}
Blade file
#foreach ($user->myeducation as $education)
<div>
{{ $education->school }}
</div>
#endforeach
Table Structure of Education and Users
**Education Table**
{
Schema::create('education', function (Blueprint $table) {
$table->bigIncrements('education_id');
$table->bigInteger('user_id');
$table->string('school');
$table->string('degree');
$table->string('fieldOfStudy');
$table->date('startDate');
$table->date('endDate');
$table->string('grade');
$table->string('activities');
$table->string('description');
$table->timestamps();
});
}
user table.
$table->increments('user_id');
$table->bigInteger('role_id');
$table->bigInteger('membership_id')->nullable();
$table->string('firstname');
$table->string('lastname');
there is no error message, but just blank
Table entries
DB::table('education')
'user_id' => '2',
'school' => 'University of Bedfordshire',
'degree' => 'MBA',
]);
DB::table('users')->insert([
'user_id' => '1',
'role_id' => '1',
'firstname' => 'Mohammed',
'lastname' => 'Sabeel',
.......
]);
DB::table('users')
' user_id' => '2'
'role_id' => '2',
'firstname' => 'zahida',
'lastname' => 'sabeel',
.......
]);
the problem is in your relationship second and third argument. you are passing keys in wrong way.
in Education model use code like
public function myUser()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
you need not to pass the third argument if you use the primary key for relationship. though you can pass the third argument to define which column to use to join the tables
public function myUser()
{
return $this->belongsTo('App\Models\User', 'user_id', 'user_id');
// second argument user_id is from your education model while the third argument that is user_id is the primary key of your user model
// i have used singular name for the relationship name with camel case
}
now in User model
public function myEducations()
{
return $this->hasMany('App\Models\Education', 'user_id');
// user_id is the user_id of education model
// and this is a has many relation i used plural form
}
read more about relationship in laravel doc
Before we begin, make sure that you have Education associated with that logged in User.
Try eager loading you relationship. Sometime this worked for me.
In your profile controller,
public function index()
{
$user = Auth::user()->load('myeducation');
return view('candidate.profile',['user'=>$user,]);
}
Even if it didn't work, Please share your table structure and table entries. So that we can examine clearly.

Laravel getAttribute() on eloquent?

so i just wondered, if something like this is possible, since my code does not work.
protected $appends = ['position_name'];
public function getPositionNameAttribute()
{
return $this->belongsTo('App\EmployeePosition', 'employee_position_id')->name;
}
Can I append the name of Eloquen relationship model?
edit: so far, i am using this:
foreach ($employees as $e) {
$e->position_name = $e->position->name;
}
So, I needed to use the relation defined before.
protected $appends = ['position_name'];
public function position()
{
return $this->belongsTo('App\EmployeePosition', 'employee_position_id');
}
public function getPositionNameAttribute()
{
return $this->position->name;
}
Based on your comments i'd suggest to use the laravel default solution for your problems API resrouces
eg
class EmployeeResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'position_name' => $this->position->name,
];
}
}
note: using the with as other people suggested to preload information can increase performance by reducing the amount of queries, if you are returning a collection of employees.
Creating an accessor that looks up a value in another model and appending this field by using $appends is bad practice and will lead to n+1 queries whenever you fetch your Employee model. You should avoid doing this and just use $employee->position->name.
You should also make sure to use Employee::with('position') when you need to show the position name, so that the position model is fetched in a single query.
If the position name is something that you need in all your Employee queries, then you can set the Employee to always eager load the position by defining the following inside your Employee model:
/**
* The relationships that should always be loaded.
*
* #var array
*/
protected $with = ['position'];
I think you can just create a model with position names and reference it to the position id in the other mode by using eloquent relationships.

error when attempting to seed pivot table using Laravel

I have just created a many-to-many relationship between the models Project and Features using Laravel however I receive the following error when attempting to run the seed script.
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'table.feature_projects' doesn't exist
The table in use is named features_project which is the default name given.
Inserting the seed data manually does return the relational data to the view as expected.
SEED
class FeaturesProjectTableSeeder extends Seeder
{
public function run()
{
$features_project = new \App\FeatureProject ([
'project_id' => '1',
'features_id' => '1'
]);
$features_project->save();
}
}
Project
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Project extends Model {
public function features() {
return $this->belongsToMany('App\Features')->withTimestamps();
}
}
Features
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Features extends Model
{
public function projects() {
return $this->belongsToMany('App\Project')->withTimestamps();
}
}
CONTROLLER
class ProjectController extends Controller
{
public function getProject($id)
{
$project = Project::where('id', $id)->get();
return view('other.project', ['project' => $project]);
}
}
ROUTE
Route::get('project/{id}', [
'uses' => 'ProjectController#getProject',
'as' => 'other.project'
]);
VIEWS
#foreach($project->features as $feature)
<dd class="col-sm-8">{{ $feature->name }}</dd>
#endforeach
Firstly some misunderstanding in naming, your table name should be feature_project, in many to many relationships the models are in alphabetical order. Secondly models are not plural, so your Features.php model should be named Feature.php. Which will resolve in Laravel using the table feature_project for the pivot and features for the model.
For your own sake, learn how Laravel name models and tables, else relationships are gonna be tricky. Which is described in the documentation.
You should not create pivot models, this is handled by assigning features to projects or vice versa. Therefor your seeder should look something like this, it could be you should assign some attributes to the projects and features before it will work.
class FeaturesProjectTableSeeder extends Seeder
{
public function run()
{
$features = factory(Feature::class)->create();
$projects = factory(Project::class)->create();
$projects->each(function (Project $project) {
$project->features()->saveMany($features);
});
}
}

Model:create used once but two rows created (laravel)

I was coding in my app and suddenly I realized that every create in my app makes two rows!
whenever I run model:create it makes two rows! it doesn't matter how or when I use a create method.
For example:
Route::get('test', function () {
\App\City::create([
'name' => 123,
'province_id' => 1
]);
});
obviously such code should create one row. but it creates two! I am stuck and don't know what to do!!
Update:
the city model is simple, but it doesn't matter what model I use.
But, running same code during interactive php artisan tinker session creates one row.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class City extends Model
{
public $timestamps = false;
protected $fillable = ['name' , 'province_id'];
public function province()
{
return $this->belongsTo('App\Province');
}
}

Many to Many Relationship Join Query between Two Table in Laravel 5.1

First User table have four columns: id ,first_name, last_name,password
my Address Table have four colmnns id , company_name,email , phone
Common Address_user Table:
My User Model Look Like This http://pastebin.com/ntuvJ8Lj and my Address Model Look Like This
use Illuminate\Database\Eloquent\Model;
class Address extends Model
{
protected $fillable = [
'created_by',
'company_name',
'phone',
'email', 'address'
];
public function users()
{
return $this->belongsToMany('App\Models\User');
}
public function getAddressListAttribute()
{
return $this->users->lists('id');
}
}
now I need the all of address which login user is involved or connected
1:
in User.php
Add your relation with 'address' model:
public function addresses() {
return $this->belongsToMany( Address::class, 'address_id', 'user_id' )->withTimestamps();
}
You wrote right relation in your Address.php with users therefore, I'm not going to retype it here.
and please note that you don't need to write address_id and user_id because simply eloquent will predict it if you are following the convention, which you do!
But I can tell that you are not following the convention of naming your tables, if you want Eloquent to predict and relation between your model and your table in DB then you have to make the name of your model the singular of your table name, or vice versa, table: users model: User.
The Gist:
$user = auth()->user(); // get logged in user
$addresses = $user->addresses()->get(); // get this user addresses. or use $user->addresses only
// now you may loop through it and have each of your addresses.
foreach($addresses as $address){
var_dump($address->company_name); // or perhabs ->email
}

Resources