Inheritance in Laravel framework - php

Is possibile to use inheritance in laravel model? I explain:
is possible to exend a model, which extends eloquent class?
class A extends Eloquent
{
}
class B extends A
{
}
A e B are also 2 different tables and B has A_id as foreignkey and other fields.
How could be the constructor of class B?
is it a ragionable solution or better use hasOne relationship?
no every A object are also B object. Es. user and teacher
Thank you

I’m having difficulty understanding your supplementary details, but in answer to the actual question: yes, it is possible to extend Eloquent models.
<?php
class User extends \Eloquent {
protected $table = 'users';
}
class Student extends User {
protected $table = 'students';
}
Be warned though, that any methods (such as relations, scopes etc) will propagate to the extending class. If this is not desired, then create a base class that has the minimum of what you need, and then sub-class it with your specific types, i.e. Student, Administrator etc.
Another approach is to use interfaces. So if you know models need the same attributes but will say, have different relations; then you can create an interface to add those constraints:
<?php
interface UserInterface {
public function getName();
}
class User extends \Eloquent implements UserInterface {
protected $table = 'users';
public function getName()
{
return $this->name;
}
}
class Student extends \Eloquent implements UserInterface {
protected $table = 'students';
public function getName()
{
return $this->name;
}
public function courses()
{
return $this->belongsToMany('Course');
}
public function grades()
{
return $this->hasMany('Grade');
}
}

I resolve with
class A extends Eloquent
{
protected $table = 'a';
}
class B extends A
{
protected $table = 'b';
protected $primaryKey = 'a_id';
}
but in the main function:
$f = B::find(1);
$f->method();
where the method() is a method of A class,
the system gives to me an mysql error:
select * from `C` where `C`.`B_id` = 1
the error is B_id. It should be A_id cause the method should be applied from subobject of the class, not from the class

Related

How to select foreign key value in Laravel

I've two tables one is car_category having the fields - id,type.
Another table named vehicle having field - c_id(FK Refers car - id).
Now I want to display the FK(c_id) value which is car-type.
I've below code in models,
class Car extends Model
{
protected $guarded = [];
protected $table = 'car_category';
public function vehicles()
{
return $this->hasMany('Vehicle');
}
}
vehicle model,
class Vehicle extends Model
{
protected $guarded = [];
protected $table = 'vehicles';
public function cars()
{
return $this->belongsTo('Car');
}
}
What 'll be my query for this? I've tried this code, results error.
$vehicles = "SELECT cars.cartype,vehicles.model FROM cars,vehicles
WHERE cars.id = vehicles.c_id";
How can I achieve this? Can anybody help me?
Try this
class Car extends Model
{
protected $guarded = [];
protected $table = 'car_category';
public function vehicles()
{
return $this->hasMany(Vehicle::class, 'c_id');
}
}
The vehicle model
class Vehicle extends Model
{
protected $guarded = [];
protected $table = 'vehicles';
public function cars()
{
return $this->belongsTo(Car::class, 'c_id');
}
}
Eloquent determines the foreign key of the relationship based on the model name. In this case, the Car model is automatically assumed to have a car_id foreign key. If you wish to override this convention, you may pass a second argument to the method
https://laravel.com/docs/5.5/eloquent-relationships#one-to-one
To get the Car along with their Vehicle information you can do a query using Eager Loading
$result = Car::with('vehicles')->get();
To get the Car along with their Vehicle information you can do a query using Eager Loading
$result = Car::with('vehicles')->get();
One more correction you have specified class name as string literals without specifying FQN, relationships in models should be defined using fully qualified name
Car Model
class Car extends Model
{
protected $guarded = [];
protected $table = 'car_category';
public function vehicles()
{
return $this->hasMany(\App\Models\Vehicle::class);
}
}
Vehicle Model
class Vehicle extends Model
{
protected $guarded = [];
protected $table = 'vehicles';
public function cars()
{
return $this->belongsTo(\App\Models\Car::class);
}
}
Change from class car to class Car
After that you can select with Car::first(), the related table data can be found in Car::first()->vehicles
You can also add a where() method on models, if you have more than one record, use a foreach()
In Model,
class Vehicle extends Model
{
protected $guarded = [];
protected $table = 'vehicles';
public function cars()
{
return $this->belongsTo(Car::class, 'c_id');
}
}
In controller,
$vehicles = Vehicle::all();
return view('vehicles.vehicle',['vehicles'=>$vehicles]);

Laravel 5.4 call a model function on an instance returned by another laravel model function

I have 3 tables and the corresponding models which are connected as shown below:
Telephones.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Telephones extends Model {
protected $table = 'telephones';
protected $primaryKey = 'telephone_id';
public function UserTelephone() {
return $this->hasOne('App\Models\Users','user_id','user_id');
}
}
Addresses.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Addresses extends Model {
protected $table = 'addresses';
protected $primaryKey = 'address_id';
public function UserAddress() {
return $this ->hasOne('App\Models\Users','address_id','address_id');
}
}
Users.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Users extends Model {
protected $table = 'users';
protected $primaryKey = 'user_id';
}
In my view I want to connect user's telephone with user's address so I do the following:
<?php $user_telephone = $telephone->UserTelephone()->first();
$address = $user_telephone->UserAddress()->first();
?>
but it fails with error:
BadMethodCallException in Builder.php line xxxx:
Call to undefined method
Illuminate\Database\Query\Builder::UserAddress()
Any ideas how I could solve it?
On your telephones and address model, I would say to use Belongs to instead of Has One.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Users;
class Addresses extends Model {
protected $table = 'addresses';
protected $primaryKey = 'address_id';
public function UserAddress() {
return $this->belongsTo(Users::class);
}
}
class Telephones extends Model {
protected $table = 'telephones';
protected $primaryKey = 'telephone_id';
public function UserTelephone() {
return $this->belongsTo(Users::class);
}
}
From https://laravel.com/docs/5.4/eloquent-relationships#one-to-one
Defining The Inverse Of The Relationship
The reason your case doesn't work on user address is because you may not have the address_id field on your user model.
return $this->hasOne('App\Models\Users','id','user_id');
You are creating a relationship so therefore you need to let it know how they're connected. I would suggest read more about relationships: https://laravel.com/docs/5.4/eloquent-relationships
Try to call your model functions like this :
$user_telephone = $telephone->UserTelephone;
$address = $user_telephone->UserAddress;
this will be okay only if $telephone its a Telephone model
EDIT
Your error is in the place you declare you model relationship
change this:
return $this->hasOne('App\Models\Users','user_id','user_id');
to this
return $this->hasOne(Users::class,'user_id','user_id');
and the same with your other function
*make sure what is your models name.. most of the times is User
Telephone Model :
public function UserTelephone() {
return $this->belongsTo('App\Models\Users','user_id','user_id');
}
Address Model :
public function UserAddress() {
return $this->belongsTo('App\Models\Users','address_id','address_id');
}
Controller :
$telephone =Telephone::find(1); //get first telephone
$user_telephone = $telephone->UserTelephone; // get User
$address = $user_telephoneObject->UserAddress; //get Address Of the user
Finally I managed to solve it, the issue was that I was trying to call a model's function on the wrong object.
My goal was to get the address when user was known. To be more specific I had the following relationship: telephone->user->address. As you could see to the initial posted code, I declared 2 functions, UserTelephone and UserAddress. Then I called UserTelephone on a telephone object and UserAddress on a recipient object. This was the reason that my code failed. Had to create a new function on Users model to be able to get the address when user was know. Working code posted below:
Telephones.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Telephones extends Model {
protected $table = 'telephones';
protected $primaryKey = 'telephone_id';
public function UserTelephone() {
return $this->belongsTo('App\Models\Users','user_id','user_id');
}
}
Addresses.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Addresses extends Model {
protected $table = 'addresses';
protected $primaryKey = 'address_id';
public function UserAddress() {
return $this ->belongsTo('App\Models\Users','address_id','address_id');
}
}
Users.php:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Users extends Model {
protected $table = 'users';
protected $primaryKey = 'user_id';
public function Address() {
return $this->hasOne('App\Models\Addresses','address_id','address_id');
}
}
In my view:
<?php $address = $telephone->UserTelephone->Address()->first();?>

Laravel's Eloquent's 'with' array is breaking

I am trying to abstract my models using a single base class. I have three models that inherit from the same base:
Repair
Inspection
Purchase
I am able to successfully create and persist the models to the DB, but when fetching I get a blank screen, no errors are thrown. When I remove the $with attribute everything seems to work.
Heres the code:
abstract class ItemType extends Model
{
public $timestamps = false;
protected $with = ['details'];
public function details()
{
return $this->morphOne(Item::class, 'type', 'item_details_type', 'item_details_id', 'id');
}
}
class Repair extends ItemType
{
protected $table = 'repairs';
protected $guarded = ['id', 'created_at', 'updated_at'];
protected $morphClass = self::class;
}
class Inspection extends ItemType {}
class Purchase extends ItemType {}
In the end I decided to use morphTo relationships without the abstract class to solve the issue.

Globally Hiding Attributes From Array Or JSON Conversion in laravel?

Sometimes you may wish to limit the attributes that are included in your model's array or JSON form, such as passwords. To do so, add a hidden property definition to your model:
class User extends Model {
protected $hidden = ['password'];
}
This is model specific.
Is there any method to hide globally?
ie,I want to hide deleted_at and created_by from all model json result.
The easiest way to do that is by creating a base model. Like this:
class BaseModel extends Model {
protected $hidden = ['deleted_at', 'created_by'];
}
And then all your models extend from that:
class User extends BaseModel {
}
Note that this way if you wanted to add some hidden fields for a specific model you would have to as well specify those two global hidden attributes:
class User extends BaseModel {
protected $hidden = ['deleted_at', 'created_by', 'password'];
}
If that bothers you, you could merge the global attributes in from the contructor:
class BaseModel extends Model {
private $globalHidden = ['deleted_at', 'created_by'];
public function __construct(array $attributes = array()){
$this->hidden = array_merge($this->globalHidden, $this->hidden);
parent::__construct($attributes);
}
}

hasManyThroughrelationship return wrong SQL sentence

I would like to get some data for tables that dont have a directly relation. The context is the following:
//** account_table **// Normal user, who can buy any book
account_id
account_info
//** book_table **// Books
book_id
account_id
author_id
//** author_table **// Author, who can write a lot of books (they will have more functions, this is the why i choose to create other table)
author_id
book_id
author_desc
The models that im using are:
class Account extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'account_table';
protected $primaryKey = 'account_id';
public function Book()
{
return $this->hasMany('Book', 'account_id');
}
public function Author()
{
return $this->hasManyThrough('Author', 'Book','account_id','book_id');
}
}
class Book extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'book_table';
protected $primaryKey = 'book_id';
public function Account()
{
return $this->belongsTo('Account','account_id');
}
public function Author()
{
return $this->hasOne('Author', 'author_id', 'author_id');
}
}
class Author extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'author_table';
protected $primaryKey = 'author_id';
public function Book()
{
return $this->belongsToMany('Book', 'author_id');
}
}
So to get this information i use the following code:
$user = Account::find(166); //user
dd($user->Author);
The ouput throw an error like this:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'book.id' in 'on clause' (SQL: select `author_table`.*, `book_table`.`account_id` from `author_table` inner join `book_table` on `book_table`.`id` = `author_table`.`book_id` where `book_table`.`account_id` = 166)
Seems that it is looking for a field (id) that does not exist in my database, however i have defined all primaryKeys in the models. What should i do to get author_desc information in this context ?
EDIT (other example):
When i use the following code it retrieve the same error:
$user = Account::find(166);
echo Book::find(3);
You've defined a one-to-one relationship of Book to Author with the hasOne() method and a many-to-many relationship between Author and Book with the belongsToMany() method. These should be inverse relationships, instead. Try replacing the belongsToMany()method with the belongsTo() method. Something like this:
class Account extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'account_table';
protected $primaryKey = 'account_id';
public function Book()
{
return $this->hasMany('Book', 'account_id');
}
public function Author()
{
return $this->hasManyThrough('Author', 'Book','account_id','book_id');
}
}
class Book extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'book_table';
protected $primaryKey = 'book_id';
public function Account()
{
return $this->belongsTo('Account','account_id');
}
public function Author()
{
return $this->hasOne('Author', 'author_id', 'author_id');
}
}
class Author extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'author_table';
protected $primaryKey = 'author_id';
public function Book()
{
return $this->belongsTo('Book', 'author_id');
}
}

Categories