BadMethodCallException with eager loading in Laravel 4 - php

I have two models User.php and Blog.php and the content,
Model User.php
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $softDelete = true;
protected $table = 'users';
protected $hidden = array('password');
//-----
public function blogs()
{
return $this->has_many('Blog');
}
//----
Model Blog.php
<?php
class Blog extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function author()
{
return $this->belongs_to('User', 'author_id');
}
}
The Controller, BlogsController.php
<?php
class BlogsController extends BaseController {
public function index()
{
$posts = Blog::with('author')->get();
return Response::json(array(
'status' => 'success',
'message' => 'Posts successfully loaded!',
'posts' => $posts->toArray()),
200
);
}
//-----
The blogs schema,
Schema::create('blogs', function(Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->integer('author_id');
$table->timestamps();
$table->softDeletes();
});
And the users schema,
Schema::create('users', function(Blueprint $table) {
$table->integer('id', true);
$table->string('name');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
$table->softDeletes();
});
When I call Blog::with('author')->get(); from BlogsController, I am getting this error:-
"type":"BadMethodCallException","message":"Call to undefined method Illuminate\\Database\\Query\\Builder::belongs_to()"
And when I change Blog::with('author')->get(); to Blog::with('author')->all();, the error become:-
"type":"BadMethodCallException","message":"Call to undefined method Illuminate\\Database\\Query\\Builder::all()"
I am using latest update for Laravel 4. What is the wrong with my code?

Your going to love and hate this answer, change belongs_to to belongsTo. Same goes for has_many to hasMany and has_one to hasOne.
Laravel 4 moved to using camel case for methods. Your method not being found on the eloquent model, it falls back to calling it on the query builder, laravel does this to allow short cutting to methods like select() and where().
The second error you were getting, when using all(), is because all() is a static method defined on eloquent and does not work with eager loading. get() is effectively the same thing as all().

Related

Why does hasOne and BelongTo relationships load only ids but not the models

I've got a problem with relations in Laravel 9.14 Eloquent.
I have two models File and Project with coresponding tables in MySql database files and projects.
Project migration
Schema::create('projects', static function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('code');
$table->string('theme');
$table->foreignId('discipline_id')->constrained('disciplines');
$table->foreignId('user_id')->constrained('users');
$table->string('external_id');
$table->foreignId('preview')->nullable()->constrained('files');
$table->date('publish_date');
$table->timestamps();
});
File migration
Schema::create('files', static function (Blueprint $table) {
$table->id();
$table->string('original_name');
$table->string('extension');
$table->string('mime_type');
$table->integer('size')->unsigned();
$table->timestamps();
});
Project has field which is related to the File model called 'preview'. Project, basically can have only one preview file. So I did these relatioins in models:
class Project extends Model
public function preview(): BelongsTo
{
return $this->belongsTo(File::class, 'preview', 'id');
}
class File extends Model
public function previewProject(): HasOne
{
return $this->hasOne(Project::class, 'preview', 'id');
}
When i try to get preview of a project this way (controller method):
public function index(): Factory|View|Application
{
$userId = auth()->user()->id;
$projects = User::find($userId)->projects()->with(['user', 'preview'])->get();
//dd($projects->first()->user);
ddd($projects->first()->preview);
return view('user.index', [
'projects' => $projects
]);
}
Instead of File model object I get only integer id of File. Queries, however, look right:
queries image
What is the problem here?
There is no error, the integer your are getting is the value of the attribute but by "chance" both your attribute and relation have the same name.
Either change the relation name:
class Project extends Model
public function previewFile(): BelongsTo
{
return $this->belongsTo(File::class, 'preview', 'id');
}
public function index(): Factory|View|Application
{
$projects = auth()->user()->projects()->with(['user', 'previewFile'])->get();
//dd($projects->first()->user);
ddd($projects->first()->previewFile);
return view('user.index', [
'projects' => $projects
]);
}
Or change the attribute name
Schema::create('projects', static function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('code');
$table->string('theme');
$table->foreignId('discipline_id')->constrained('disciplines');
$table->foreignId('user_id')->constrained('users');
$table->string('external_id');
$table->foreignId('preview_id')->nullable()->constrained('files');
$table->date('publish_date');
$table->timestamps();
});
class Project extends Model
public function preview(): BelongsTo
{
return $this->belongsTo(File::class, 'preview_id', 'id');
}

Laravel 7 One To Many Relations?

Below are all of the models, migrations and controller.
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class);
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(Donaition::class);
}
}
Donation Items Migration:
public function up()
{
Schema::create('donation_items', function (Blueprint $table) {
$table->id();
$table->string('category');
$table->timestamps();
});
}
Donation Migration:
public function up()
{
Schema::create('donations', function (Blueprint $table) {
$table->id();
$table->string('item');
$table->unsignedInteger('user_id');
$table->unsignedInteger('donation_item_id');
$table->timestamps();
});
}
In my controller I want to access the items as follows:
$don = Donation::all();
$don->items;
But I'm unable to achieve this.
Its not working because laravel follows one rule for relationships:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
So you can try by supplying local and foreign id
So it would look something like this
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class, 'donation_item_id', 'id');
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(DonationItems::class, 'id', 'donation_item_id');
}
}
I am writing from my head you might need to swap local and foreign ID's

How to define Multiple foreignKeys in Laravel?

In my Model class;
Currently I have defined like;
return $this->belongsTo(related: Site::class,
foreignKey:'SiteId', ownerKey:'SiteId');; ----->This works.
But I want to define a combination as Foreign key,
eg: CompanyCode+SiteId
My Current and Target model has both columns(ie:CompanyCode+SiteId). That combination will return a single entry.I want to retrieve that in my current model.
How can I do that?
My Site Model is like;
class Site extends Model
{
protected $table = 'vwSitesPortal';
protected $primaryKey = 'SiteId';
...
My Current model is like;
class Alarm extends Model
{
protected $table = 'vwAlarm';
protected $primaryKey = 'AlarmId';
...
public function Site()
{
return $this->belongsTo(**related**: Site::class,
**foreignKey**:'SiteId', **ownerKey:**'SiteId'
}
Schema::create('favorites', function (Blueprint $table) {
$table->integer('lecture_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
$table->primary(['lecture_id', 'user_id']);
$table->foreign('lecture_id')
->references('id')->on('lectures')
->onDelete('cascade');
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
});
see this example

laravel eloquent for hasMany relation does not work

I have these relations in my database
Schema::create('my_users', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('fullName');
$table->string('userName');
$table->string('password');
$table->string('photo');
$table->string('email');
});
and
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('photo');
$table->text('caption');
$table->integer('like');
$table->integer('my_user_id');
});
my models :
class myUser extends Model
{
public function post()
{
return $this->hasMany('App\post');
}
}
class post extends Model
{
public function user()
{
return $this->belongsTo('App\myUser');
}
}
now I'm trying to get a user's data using the following code :
$post = post::find(1);
$user = $post->user;
but it doesn't work and $user is NULL.
I'm sure that in posts table there is a record with id 1.
the weird part is this that I get no error when I change the method's name like this :
$post = post::find(1);
$user = $post->somethingBullshit;
I'm using laravel 5.3.
help please.
Confirm that you are naming your class files starting with upper case letters, and modify your class declarations accordingly, such as:
class MyUser extends Model
{
public function post()
{
return $this->hasMany('App\Post');
}
}
class Post extends Model
{
public function user()
{
return $this->belongsTo('App\MyUser');
}
}
You can then select the user when you obtain the post by utilizing eloquent's with() method, and obtain your $user variable from your $post variable, OR just use the user property of post as follows:
$post = Post::with('user')->find(1);
$user = $post->user;

laravel eloquent relationship hierarchy

I seem to be having a problem understanding this hierarchical relationship.
Farm > Fields > Shepherds > Sheep
It seems a pretty straightforward hierarchy - Farm hasMany fields, field hasMany shepherds, shepherd hasMany sheep.
Sheep belong to a shepherd, shepherds belongs to fields, fields belong to farms.
I have defined this model relationships thus:
class Sheep extends Model {
protected $fillable ['name'];
public function shepherd() {
return $this->belongsTo('App\Shepherd');
}
}
class Shepherd extends Model {
protected $fillable ['name'];
public function field() {
return $this->belongsTo('App\Field');
}
public function sheep() {
return $this->hasMany('App\Sheep');
}
}
class Field extends Model {
protected $fillable ['name'];
public function farm() {
return $this->belongsTo('App\Farm');
}
public function shepherd() {
return $this->hasMany('App\Shepperd');
}
}
class Farm extends Model {
protected $fillable ['name'];
public function field() {
return $this->hasMany('App\Field');
}
}
public function up()
{
Schema::create('farms', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
}
public function up()
{
Schema::create('fields', function (Blueprint $table) {
$table->increments('id');
$table->integer('farm_id');
$table->string('name');
});
}
public function up()
Schema::create('shepherds', function (Blueprint $table) {
$table->increments('id');
$table->integer('field_id');
$table->string('name');
});
}
public function up()
Schema::create('sheep', function (Blueprint $table) {
$table->increments('id');
$table->integer('shepherd_id');
$table->string('name');
});
}
I would expect to be able to save each model in the following manner.
$farm = new App\Farm;
$farm->name = 'West Farm';
$field = new App\Field;
$field->name = 'The orchard';
$shepherd = new App\Shepherd;
$shepherd->name = 'Jason';
$sheep = new App\Sheep;
$sheep->name = 'Sean';
$farm->save();
$farm->field()->save($farm);
$farm->field->shepherd()->save($shepherd);
$farm->field->shepherd->sheep()->save($sheep);
But it does not work. Once I get to $farm->field->shepherd()->save($shepherd); the process breaks down. I would appreciate some assistance in the correct manner of saving using the relationships between all the tables.
I'm pulling my hair out trying to understand this, so any help would be greatly appreciated.
thanks
Your code breaks here:
$farm->field->shepherd()->save($shepherd);
Farms have many fields, so when you reference $farm->field, you're getting a collection of Field object, not just a single Field object.
To make it work, you need to either reference $farm->field[0]
$farm->field[0]->shepherd()->save($shepherd);
or just use the $field object you created before:
$field->shepherd()->save($shepherd);
I'd also suggest to use plural names for your hasMany relations (fields, sheeps, etc.) - this way you'll always remember that the referenced fields refer to a collection, not a single object

Categories