Inheritance in Laravel - php

I have two classes. A and B. The class A extends Laravel, the class B extends A.
They rappresent two tables. The table associated with the class B doesn't have a primary key, also a foreign key (A_id). The situation is this:
class A extends Eloquent
{
protected $table = 'a';
}
class B extends A
{
protected $table = 'b';
protected $primaryKey = 'a_id';
}
I need to specify the primary key in class B cause laravel tries to build the B object with
SELECT * FROM B where id = ?
but the field id doesn't exists.
The problem is when i try to access to an A method from B object es
$b = B::find(1);
$b->method_in_a_class();
the method called execute a query in a C table (also another class), linked with A table, not with B table, so the framework do this query:
SELECT * FROM C WHERE B_id = ?
but it would be
SELECT * FROM C WHERE A_id = ?
Why??
Thank you

probably the easiest way to solve the problem is to use the one-to-one relationship, so that you have:
class A extends Eloquent
{
protected $table = 'a';
public function b()
{
return $this->hasOne('B');
}
}
class B extends Eloquent
{
protected $table = 'b';
public function a()
{
return $this->belongsTo('A');
}
}
Hope this could solve your problem!

If you do not have a primary key in the second table, you should consider merging the tables. Without the primary id, you are not able to use it as a Eloquent model anyway. You have this problems probably because of a bad database design.

First off, to answer your question: Eloquent uses B name for foreign key, because you didn't tell it not to.
Imagine this scenario (not entirely like yours, but it's a real one): Post model, Category model, RootCategory model:
class Category extends \Eloquent {
public function posts()
{
return $this->hasMany('Post');
}
}
// categories are hierarchical, self referencing table
class RootCategory extends Category {
// global scope and stuff
protected $table = 'categories';
}
class Post extends \Eloquent {
public function category()
{
return $this->belongsTo('Category');
}
}
Now, with above setup, calling simple dynamic property will throw - column not found 'posts.root_category_id' which is probably what happened in your case.
The reasons for this are:
You didn't specify the foreign key to look for...
...so Eloquent calls generic getForeignKey() method to guess it
getForeignKey() uses $this, which is RootCategory object, so the foreign key will be root_category_id.
So there are 2 ways of solving this issue:
1 better
// RootCategory model
public function getForeignKey()
{
return 'category_id';
}
2 also working, however requires editing parent class.
// Category model
public function posts()
{
return $this->hasMany('Post', 'category_id');
}

Related

Polymorphic relationshoip in Laravel

I'm trying to understand polymorphic relationship in Laravel. I know how it works in principle, but the choice of wording in Laravel is not intuitive in this part. Given the exanple,
namespace App;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
/**
* Get all of the owning likeable models.
*/
public function likeable()
{
return $this->morphTo();
}
}
class Post extends Model
{
/**
* Get all of the product's likes.
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
}
class Comment extends Model
{
/**
* Get all of the comment's likes.
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
}
How do yo put in plain English sentence morphTo for instance? It is "belongsto"? and morphmany, hasMany? going further,
$post = App\Post::find(1);
foreach ($post->likes as $like) {
//
}
$likeable = $like->likeable;
morphToMany and morphByMany
How do you describe in plain english?
A polymorphic relationship means an object can have a relationship to more than one type of object. This is determined by two fields in the database rather the typical one foreign key field you would normally see.
Using the code you included in your question any type of object extending the Model class can have a relationship with a Like object. So you could have Comments and Posts that can have Likes associated to them. In your likes table you may have rows where 'likable_type' = 'post' and 'likable_id' = 1 or 'likable_type' = 'comment' and 'likable_id' = 4 for example.

How to return one property of a belongsTo model with the child model in Laravel resource controller

I'm using Laravel as a REST API for a SPA. I have a relationship where families have multiple contributions. The contributions table has a foreign key reference to family's id. I can call on the contributions route with the hasMany/belongsTo set up, and every contribution gets the entire family model it belongs to. But I don't need all that data, I just need a single field from the family table (not the id, but a different field) with each contribution.
Here are my models and resource controller:
class Family extends Eloquent {
protected $table = 'families';
// relationships
public function contributions() {
return $this->hasMany('Contribution');
}
}
class Contribution extends Eloquent {
protected $table = 'contributions';
// relationships
public function family() {
return $this->belongsTo('Family');
}
public function other_field() {
return $this->belongsTo('Family')->select('other_field');
}
}
class ContributionController extends BaseController {
public function index()
{
// works - but returns the entire family with every contribution
$contributions = Contribution::with('family')->get();
// returns other_field == null with every contribution
$contributions = Contribution::with('other_field')->get();
return Response::json($contributions->toArray(),
200);
}
Where am I going wrong with selecting this single field from the belongsTo relationship?
You can use query constraints on the relationship if you use eager loading.
Family::with(['contributions', function($query)
{
$query->select('column');
}])->get();

Laravel belongsTo & hasMany relation not working

I have a table called champ_sales which contains champions that belong to table champions. I've set up my models properly, and I'm trying to query in the exact same way the documentation here: http://laravel.com/docs/eloquent#querying-relations states, but it's not working.
class ChampSales extends Eloquent {
protected $table = 'champ_sales';
public function champ(){
return $this->belongsTo('Champion');
}
}
class Champion extends Eloquent {
protected $table = 'champions';
public function skins(){
return $this->hasMany('Skin');
}
//relevent relation here:
public function championOnSale(){
return $this->hasMany('ChampSales');
}
public function skinOnSale(){
return $this->hasMany('SkinSales');
}
}
My query: Find start_date in table champions for id=2
$champsales = ChampSales::find(2);
echo $champsales->champ->start_date;
Running this gives me a vague error that says "Trying to get property of non-object". I'm not really sure what I've done wrong, followed the documentation to the dot.
I just fixed it. I defined the local key and foreign key in champ(). I thought the laravel naming convention would pick that up fine, but I guess not.
class ChampSales extends Eloquent {
protected $table = 'champ_sales';
public function champ(){
return $this->belongsTo('Champion', 'champion_id', 'id');
}
}

Laravel Eloquent Joins

I have below query in core php:
SELECT DISTINCT device_tocken FROM push_details JOIN users ON users.id=push_details.user_id
I have to integrate it in laravel 4
Application already have User extends Eloquent class
I created Push_details class as below
class Push_details extends Eloquent {
public $table = 'push_details';
public function User() {
return $this->hasMany('\User','id');
}
}
Table : users
Primary key : id
Table: push_details
Primary key: id
Foreign key: user_id belongsTo('users.id');
But i m not able to get expected result.
One more thing i didn't write anything in User's model yet.
Only way to join table is.. to join it, as Eloquent relations don't work using joins but separate queries with WHERE IN clauses. So this will do:
DB::table('push_details')
->select('device_tocken')
->distinct()
->join('users','users.id','=','push_details.user_id')
->get();
Above will return array of stdObject's so or if you need Eloquent Collection with Eloquent models as a result replace DB::table('push_details')->select... with PushDetails::select...
Now, correct your relations, as they are wrong:
// PushDetails model (as previously stated, I suggest renaming it to StudlyCase)
public function user() {
return $this->belongsTo('\User','user_id'); // user_id is may be omitted here
}
// User model
public function pushDetails() {
return $this->hasMany('\PushDetails','user_id'); // user_id is may be omitted here as well
}
In your User model, you need to link back to the PushDetails model, like so
class User extends Eloquent {
public function push_details() {
return $this->belongsTo('PushDetails');
}
}
Use CamelCase for Class names, because laravel has several functions, in which CamelCase are changed to snake_case
Change
public function User() {
return $this->hasMany('\User','id');
}
to
public function users() {
return $this->hasMany('User');
}
See the docs 'Eloquent ORM' for more...

Laravel Eloquent Relationship

I have a sales model defined and when I call Quote::find('1'); it is not returning my sales object. Have I done something wrong with my relationship? Here is the table structure:
Quote: id, companyName, stage, saleId
Sale: id, name, phoneNumber
Class Quote extends Eloquent
{
protected $with = ['sale'];
public function sale()
{
return $this->hasOne('Sale', 'id');
}
}
In my Sale model I have defined:
public function quote()
{
return $this->belongsTo('Quote');
}
I figured it out. Had my relationship backwards.
Class Quote extends Eloquent
{
protected $with = ['sale'];
public function sale()
{
return $this->belongsTo('Sale', 'saleId');
}
}
To understand it better I think you can say that in a belongs_to relationship, the foreign key resides in the table of the model you are trying to create the relationship from. So the above function could be read like "saleID belongsTo Sale model".
The foreign key resides in the other model's table when using has_one.
Try this:
$quote = Quote::with('sale')->find(1);
You should be able to then go something like this $quote->sale->name

Categories