error when attempting to seed pivot table using Laravel - 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);
});
}
}

Related

Cannot establish relationship between two tables in Laravel

I want to create a relation between lising and attribute table in laravel for that i have used following code to establish relationship between them but the data in my view is not coming from both the tables. I'm getting following error:
Call to undefined relationship [adListAttributes] on model
[App\Models\AdListing].
Here listing can have as many attribute associated with and attributes
can be associated to many listings
ad_listings:
id
title
name
date
ad_list_attributes table :
id
listing_id
name
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Model;
class AdListAttribute extends Model
{
protected $table = "ad_list_attributes";
public function Listings()
{
return $this->belongsToMany('AdListing', 'id', 'listing_id');
}
}
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Model;
class AdListing extends Model
{
protected $table = "ad_listings";
public function Attributes()
{
return $this->belongsToMany('AdListAttribute', 'listing_id', 'id');
}
}
Problem is that you are using belongsToMany in both the models.This will cause a problem.
In AdListAttribute model,
public function listing_information()
{
return $this->belongsTo('App\AdListing', 'id', 'listing_id');
}
In AdListing model,
public function adlisting_attributes()
{
return $this->hasMany('App\AdListAttribute', 'listing_id', 'id');
}
You can get the results using,
$response = AdListing::get();
if($response->adlisting_attributes)
{
foreach($response->adlisting_attributes as $attribute)
{
echo $attribute->name;
}
}
Problem is that ur not calling the relationship with the right name i assume
$listings = AdListing::with('Attributes')->get();
Update :
Try this :
use App\Models\AdListAttribute;
//
return $this->belongsToMany(AdListAttribute::class, 'listing_id', 'id');
Same for other model, then try

Where is the create method of BelongsTo class?

I have a general class for uploads.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class File extends Model
{
protected $guarded = ['id'];
}
An ID of File model will be specified on each person to serve as the avatar:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
public function avatar()
{
return $this->belongsTo('App\File');
}
public function putAvatar($file)
{
$path = $file->store('avatars');
// This would work if `avatar()` was a `hasMany()` relation
$this->avatar()->create([
'path' => $path,
]);
}
}
This doesn't work exactly as intended, but it creates the File model in database. Why?
The $this->avatar() is an instance of BelongsTo and there is no create method. I checked the class, the included traits and the Relation class that it extends. Reference here.
So what's going on, where is the code that creates the new model?
I tried using a ReflectionMethod but while $this->avatar()->create() works, new ReflectionMethod($this->avatar(), 'create') returns a ReflectionException with message Method Illuminate\Database\Eloquent\Relations\BelongsTo::create() does not exist.
There is no method for saving entities on belongsTo relationships. Once the entity is created, you can associate it with the model.
$avatar = File::create([...]);
$this->avatar()->associate($avatar)->save();
To allow querying of relationships, undefined method calls are passed to an Eloquent Builder instance which does have a create method.
All relationships extend the Relation class which defines:
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}
$result = $this->query->{$method}(...$parameters);
if ($result === $this->query) {
return $this;
}
return $result;
}
The method used for belongsTo() should be save(), not created(). Make sure to pass as an argument your File class:
$this->avatar()->save(new File([
'path' => $path,
]));

In laravel how to get the join table data in same array without where condition

I have created both employes and employes_detail tabel with the data
i have created model for both of the table that is given below:
emloye model:
<?php
namespace App\Http\Model;
use Illuminate\Database\Eloquent\Model;
use App\Http\Model\EmployeDetail;
class Employe extends Model
{
public function employes_detail()
{
return $this->hasOne(EmployeDetail::class);
}
}
and eployedetail model:
<?php
namespace App\Http\Model;
use Illuminate\Database\Eloquent\Model;
class EmployeDetail extends Model
{
public function employe()
{
public function employe()
{
return $this->belongsTo(Employe::class);
}
}
}
and in controller i used like :
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\Http\Model\Employe;
use App\Http\Model\EmployeDetail;
class EmployeController extends Controller
{
public function index(Request $request)
{
$Employe=Employe::all();
$convert=$Employe->toArray();
echo "<pre>";print_r($convert);exit;
//return view('employe.employe');
}
}
it showing only employe table data how can i show the data for the
employes_detail as well as .still i am not able to understand it on
laravel documentation can anyone please help me related this.
how can i get the all data from employes and employes_details table for all the records
but when i used this code in controller:
public function index(Request $request)
{
$Employe=Employe::where('id',1)->first();
//$convert=$Employe->toArray();
echo "<pre>";print_r($Employe->employes_detail);exit;
//return view('employe.employe');
}
its shows me the employe_detail table data
but i want both of the table data in a same array and i dont want to use where condition here.
the function employes_detail and employe in your models only declares the relationships between the models but if you want to load the relationship, you can try this :
Employe::with('employes_detail')->get();
or
$employees = Employe::all(); $employees->load('employes_detail');
Then you can access for each employees the relation attribute like that :
foreach($employees as $employe) {
$employe->employes_detail->id;
}
Hopes it helps you.

Laravel model: instance or relationship?

I'm not a professional programmer, so I don't know that I'm describing this very well.
Eloquent relationships are established in the model, using syntax and functions such as ... - >belongsTo.. etc.
Behind these models, are tables in my database.
In my (laravel) application, I have a logged in user who needs certain information about other users. At the end of the day, they're all just users, persisting in the user's table.
So when I use a relationship to another object, (e.g. car) all is good. When I try use a relationship to another user I get errors like Cannot redeclare class App\Models\User.
I think I'm misunderstanding something here.
I get the feeling maybe I should be 'instantiating' another version of my User (as 'manager') ... But do I really need to? It's more of a lookup than anything else. I'm not sure I would even know how to do that.
Some pointers please?
It sounds like you created two distinct "User" models:
// /app/User.php:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// ...
public function user() {
return $this->hasOne('App\Models\User');
}
}
// /app/models/User.php:
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// ...
public function user() {
return $this->belongsTo('App\User');
}
}
Instead you want to have a single class which belongs to itself:
// /app/User.php:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// ...
public function parent() {
return $this->belongsTo('App\User');
}
public function children() {
return $this->hasMany('App\User');
}
}
Then in your database make sure that the users table has a user_id property (edit database/migrations/2014_10_12_000000_create_users_table.php):
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
Now you can attach users to one another:
<?php
$manager = new User();
$employeeOne = new User();
$employeeTwo = new User();
$manager->children()->saveMany([
$employeeOne,
$employeeTwo
]);
dd( $employeeTwo->parent->name ); // Manager's name

Polymorphic relations in upgraded Laravel app from 4.2 to 5

Short: some related models are returning instances correctly, but some aren't (the polymorphic ones).
I have those three models:
app/Models/User.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function company()
{
return $this->hasOne('App\Company');
}
}
app/Models/Company.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Company extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
public function address()
{
// Also tested with morphMany, without success
return $this->morphOne('App\Address', 'addressable');
}
}
app/Models/Address.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Address extends Model {
public function addressable()
{
return $this->morphTo();
}
}
And the controller:
app/Http/Controllers/MyController.php
<?php namespace App\Http\Controllers;
// ... many "use" clauses not relevant to the question
use Auth;
// ...
use App\Address;
use App\Company;
use App\User;
class MyController extends Controller {
// Ok here
$user = Auth::user();
// Ok here, too
$company = $user->company()->first();
// Here is the problem; $address is null
$address = $company->address()->first();
}
The line $company->address()->first(); is always returning null to $address in Laravel 5, but it worked well in Laravel 4.2
In L4 models were not namespaced by default, so they were saved as ModelName in your table, while now in L5 they are rather Namespace\ModelName and are retrieved the same way.
That said, your data saved in L4 needs to be adjusted so it matches your current models, or you can use protected $morphClass on the models.
However take this into consideration for the latter solution.
If you open your database - you'll see the relationship in your old L4 data stored as: User or Company
You need to run a script that updates the columns to the new namespace names - such as App\User or App\Company
This is because you are now namespacing your models - so Laravel needs to know which namespace to call.
Along with #The Shift Exchange's answer and following my question's example, you can follow this approach:
Instead of adding the namespace in addressable_type column values from address table (and this is a valid solution), you can use $morphClass:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Company extends Model {
protected $morphClass = 'Company';
public function user()
{
return $this->belongsTo('App\User');
}
public function address()
{
// Also tested with morphMany, without success
return $this->morphOne('App\Address', 'addressable');
}

Resources