Why extended class does not have the relationship in Laravel with Modules? - php

I have a Person class (App\Models\Person) and an Organization class (App\Models\Organization) which have a polymorphic relationship with User (App\Models\User). I am using Modules (nwidart/laravel-modules).
In my App\Providers\AppServiceProvider in the boot method I have this relationship:
Relation::morphMap(
[
'organizations' => 'App\Models\Organization',
'persons' => 'App\Models\Person',
]
);
Now, I have a module called Contracts, that module has a Person model (Modules\Contracts\Entities\Person) which extends from App\Models\Person. I also have a User model (Modules\Contracts\Entities\User) which extends from App\Models\User.
I added the following code to the ContractsServiceProvider boot method:
Relation::morphMap(
[
'persons' => 'Modules\Contracts\Entities\Person',
]
);
Now, if I go to any controller and I load a Person like this:
$person = \App\Models\Person::find( 1 );
The relationship with User doesn't exist, so I can't do $person->users()->first();
But if I load a Person like this:
$person = \Modules\Contracts\Entities\Person::find( 1 );
The relationship works like a charm.
The fun part is that all the relationship methods with users are inside the files User.php and Person.php in the app\Models directory.
In app\Models\User.php I have:
class User extends Authenticatable implements MustVerifyEmail {
public function usable()
{
return $this->morphTo();
}
}
In my app\Models\Person.php
class Person extends Model {
public function users()
{
return $this->morphMany( User::class, 'usable', 'usable_type', 'usable_id' );
}
}
Also, when I create an \App\Models\Userfrom an \App\Models\Person like this:
$person = \App\Models\Person::find( 1 );
$person->users()->create( [ ... ] );
The record in the database in the users table is like this:
+------------------------------------------------------------------------+
| id | email | usable_id | usable_type |
+------------------------------------------------------------------------+
| 1 | some#email.com | 3 | App\Models\Person |
+------------------------------------------------------------------------+
But if I create the user from a \Modules\Contracts\Entities\Person like this:
$person = \Modules\Contracts\Entities\Person::find( 1 );
$person->users()->create( [ ... ] );
The record in the database in the users table is like this:
+------------------------------------------------------------------------+
| id | email | usable_id | usable_type |
+------------------------------------------------------------------------+
| 1 | some#email.com | 3 | persons |
+------------------------------------------------------------------------+
I wonder if the ContractsServiceProvider is somehow overriding the AppServiceProvider and causing my relationship to fail. Any help would be appreciated.
Thanks

Related

Laravel Eloquent returns an empty collection on belongsToMany relationship

UPDATE: The issue mentioned here has caused by the use of MariaDB instead of MySQL by XAMPP. I have followed the answer here to switch it to MySQL and it works like a charm.
This is regarding an e-commerce platform.
I have 2 data tables with 1 joining table for a many-to-many join. The idea is for Products to have many Special Offers running at any given time.
Tables
products
+-------+-------------------------------+
| id | name |
+-------+-------------------------------+
| 10001 | Apple iPhone 11 |
| 10002 | Samsung Galaxy S11 |
+-------+-------------------------------+
special_offers
+----+-------------------------------+
| id | name |
+----+-------------------------------+
| 1 | Awesome Offer |
| 2 | Year End Offer |
+----+-------------------------------+
product_special_offer
+------------+------------------+----------+
| product_id | special_offer_id | discount |
+------------+------------------+----------+
| 10001 | 1 | 10.0 |
| 10002 | 2 | 12.5 |
+------------+------------------+----------+
Models
Since the requirement is for a many-to-many relationship, I am using belongToMany method in my models.
Product
class Product extends Model
{
public function specialOffers()
{
return $this->belongsToMany(SpecialOffer::class)->withPivot('discount');
}
}
SpecialOffer
class SpecialOffer extends Model
{
public function products()
{
return $this->belongsToMany(Product::class)->withPivot('discount');
}
}
Controller
The following is the controller snippet.
ProductController
class ProductController extends Controller
{
public function index()
{
$product = Product::find(10001);
dd($product->specialOffers);
}
}
Results
The following is what Laravel returns.
Collection {#610 ▼
#items: []
}
The query it runs is mentioned below.
select `special_offers`.*, `product_special_offer`.`product_id` as `pivot_product_id`, `product_special_offer`.`special_offer_id` as `pivot_special_offer_id`, `product_special_offer`.`discount` as `pivot_discount` from `special_offers` inner join `product_special_offer` on `special_offers`.`id` = `product_special_offer`.`special_offer_id` where `product_special_offer`.`product_id` = 10001
This could work
class SpecialOffer extends Model
{
public function products()
{
return $this->belongsToMany(Product::class, 'product_special_offer','special_offer_id','product_id');
}
}
Make a third model to the connection table, and add the two relation. And it's will work.
class ProductSpecialOffer extends Model
{
public function products() {
return $this->belongsTo(Product::class);
}
public function specialOffers() {
return $this->belongsTo(SpecialOffer::class);
}
}

How can I do a belongsTo() relation in Laravel?

Here is my model User.php
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password', 'cell_phone', 'province_id', 'city_id', 'job'
];
protected $hidden = [
'password', 'remember_token',
];
public function city()
{
return $this->belongsTo('City');
}
}
And here is a part of my controller:
$user_info = User::find(Auth::user()->id);
dd($user_info->city);
And it throws this:
"Undefined class constant 'city'"
How can I fix the problem?
Tables structure:
// users
+----+--------+---------+----------
| id | name | city_id | ...
+----+--------+---------+----------
| 1 | Jack | 5 | ...
// city
+----+--------+
| id | name |
+----+--------+
| 1 | Tehran |
You need to pass full class name:
return $this->belongsTo('App\City');
Or:
return $this->belongsTo(City::class);
Also, you don't need to do that:
$user_info = User::find(Auth::user()->id);
Because Auth::user() already has user instance loaded, you can just get city instance with:
Auth::user()->city
Basically , you don't provide full path of your class name of city that's why you belongs To relation not working properly.
for example your code must be
return $this->belongs To('App/City');
Because your in app folder you have city class module and others.

laravel how to get all the users i talked to

i am now working on a messaging system with laravel. Now i want to have a list of users the current user send message to / receive from. suppose i have a message table like
id | sender_id | receiver_id | msg
1 | 1 | 2 | smadksamdksa
2 | 3 | 4 | hi
3 | 1 | 2 | www
4 | 2 | 1 | ssse
5 | 3 | 1 | hi
i find get a list of id of user i talked to, the result for the user 1 will be
id
2
3
model of message
namespace App;
use Illuminate\Database\Eloquent\Model;
class msg extends Model
{
protected $table = 'msgs';
public function user()
{
return $this->belongsTo('App\user');
}
}
the query i made
$senders = msg::select('sender_id')->where('receiver_id', '=', Auth::id())->distinct()->get();
$peopleUserTalkedTo = msg::select('receiver_id')->where('sender_id', '=', Auth::id())->distinct()->union($senders)->get();
but it doesn't work with an error
Undefined property: Illuminate\Database\Eloquent\Collection::$bindings
what's wrong with it, and can i SELECT sender id and receiver AS id, can i get the user id from it later on?
I think the problem is about the union method.
You should define your models like this:
namespace App;
use Illuminate\Database\Eloquent\Model;
class msg extends Model
{
protected $table = 'msgs';
public function sender()
{
return $this->belongsTo('App\user','sender_id');
}
public function receiver()
{
return $this->belongsTo('App\user','receiver_id');
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class user extends Model
{
public function talkedTo()
{
return $this->hasMany('App\msg','sender_id');
}
public function relatedTo()
{
return $this->hasMany('App\msg','receiver_id');
}
}
Now try to fetch people you talked to like this:
Auth::user()->talkedTo()->get();
Auth::user()->relatedTo()->get();
Updated
For getting only ids of the people you talked to or related to follow the code:
Auth::user()->talkedTo->pluck('id');
Auth::user()->relatedTo->pluck('id');
didnt realy get what u want but Try this after being sure to add this to ur user model
class user extends Model
{
public function msgs()
{
return $this->hasMany('App\msg');
}
}
then
$mymsgs = Auth::user()->msgs->get(); //collection of all msgs
and then you can use a foreach loop

Laravel - model modifications

I need to refactor project and I have problem. Below is old, working model, where 'active' column is in "people" table. I need to move 'active' column into "people_translations" table.
Do you have any Idea to modify scopeActive method?
Thanks a lot!
Old working model:
class BaseModel extends Eloquent
{
public function scopeActive($query)
{
return $query->where($this->table . '.active', '=', 1);
}
}
class People extends BaseModel
{
protected $table = 'peoples';
protected $translationModel = 'PeopleTranslation';
}
class PeopleTranslation extends Eloquent
{
public $timestamps = false;
protected $table = 'peoples_translations';
}
Old tables structure:
Table: peoples
id | type | date | active
-------------------------
7 | .... | ... | 1
Table: peoples_translations
id | people_id | language_id | name
-----------------------------------
1 | 7 | 1 | Ann
Old query:
$peoples = \People::active()->get();
New tables structure:
Table: peoples
id | type | date
----------------
7 | .... | ...
Table: peoples_translations
id | people_id | language_id | name | active
--------------------------------------------
1 | 7 | 1 | Ann | 1
Create a relation for translations inside People Model
public function translations()
{
return $this->hasMany('PeopleTranslation', 'people_id');
}
Create active scope in People model
public function scopeActive($query)
{
return $query->whereHas('translations', function($query) {
$query->where('active', 1);
});
}
It will make subquery for this table and as a result it will get where (count of translations with active = 1) > 0.
If you have one-to-one relation - look for hasOne relation method instead of hasMany.

Undefined eloquent methods find($id)/all()

I try create simple model with Laravel and Eloquent.
Here my code example:
composer.json
"laravel/framework": "4.1.*"
routes.php
Route::controller('items', 'ItemsController');
Route::get('item/{item}', array('as'=>'item', 'uses'=> 'ItemsController#getView'));
php artisan route:
| | GET item/{item} | item | ItemsController#getView | | |
| | GET items | | ItemsController#getIndex | | |
controllers/ItemsController.php
<?php
class ItemsController extends BaseController {
public function getIndex()
{
$items = Item::all();
return View::make('items.index')
->with('title', 'Index show')
->with('items', $items);
}
public function getView($id)
{
return View::make('items.view')
->with('title', 'View show')
->with('items', Item::find($id));
}
}
models/Item.php
<?php
class Item extends Eloquent {
protected $table = 'items';
}
DB: I have MySQL table "items" with 6 rows, for example:
+----+-----------+---------------------+
| id | name | created_at |
+----+-----------+---------------------+
| 4 | ironman | 2012-04-03 10:02:44 |
| 5 | robot | 2012-04-13 10:02:44 |
+----+-----------+---------------------+
When I try to GET mydomain/item/2
Laravel say:
Call to undefined method Item::find()
And GET mydomain/items/
Call to undefined method Item::all()
What I'm missed?
It sometimes happens to me when I am changing model and table names "on the fly", and when I do a lot of migration rollback. Try to rename you model name, it works for me in most cases.

Categories