How to relate two tables in Laravel 5.0 - laravel

In a little example, I have 3 tables (2 of them are important).
My tables are PRODUCT, TRANSFER, WAREHOUSE
I want to transfer the PRODUCT from 1 WAREHOUSE to another and obviously this transfer has to be in the TRANSFER TABLE, My example model could be the next.
HERE THE ENTITY - RELATION - MODEL
Now I'm Using Laravel 5.0
And when I create the models im doing this, with TRANSFER model:
<?php namespace Sicem;
use Illuminate\Database\Eloquent\Model;
class TRANSFER extends Model{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'TRANSFER';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['id','ware_ori_id','ware_end_id','product_id'];
public function product(){
return $this->belongsTo('Sicem\Product');
}//THIS IS OK!
public function sourceware(){
return $this->belongsTo('Sicem\Warehouse\ware_ori_id');
}//I THINK THIS IS OK!
public function endware(){
return $this->belongsTo('Sicem\Warehouse\ware_end_id');
}//I THINK THIS IS OK!
}
Now, My question is here in my WAREHOUSE model, I don't what can I put:
<?php namespace Sicem;
use Illuminate\Database\Eloquent\Model;
class WAREHOUSE extends Model{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'WAREHOUSE';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['id','name'];
public function transfer(){
return $this->hasMany('Sicem\TRANSFER');
}//I supose this.
//But is or not necesary to have 2(two) functions for the relation in my TRANSFER model???????????
}
SICEM: is my project name
Please Help me.

class Product {
protected $table = 'PRODUCT';
protected $fillable = ['name'];
public function transfers()
{
return $this->hasMany(Transfer::class);
}
public function transfer($warehouse_from_id, $warehouse_to_id)
{
return Transfer::create([
'product_id' => $this->id,
]);
}
}
class Transfer {
protected $table = 'TRANSFER';
protected $filalble = ['ware_ori_id', 'ware_end_id', 'product_id'];
public function warehouse_from()
{
retrun $this->belongsTo(Warehouse::class);
}
public function warehouse_to()
{
return $this->belongsTo(Warehouse::class);
}
public function product()
{
return $this->belongsTo(Product::class);
}
}
class Warehouse {
protected $table = 'WAREHOUSE';
protected $fillable = ['name'];
}
So you need to do something like this:
$warehouseFrom = Warehouse::find(1);
$warehouseTo = Warehouse::find(2);
$product = Product::find(23);
$product->transfer($warehouseFrom->id, $warehouseTo->id);

Related

Lazy eager loaded relationship missing in toArray()

Laravel 5.8
I am lazy loading an user with the related customer which has a one-to-one-relation with a crmaccount-object
The models are working so that when i retrieve the eager-loaded entity it shows all of the nested relationships.
One row later i use the "toArray()" method on that object and the output is missing the third-level-relations.
The only thing which maybe some kind of special regarding the "crmaccount"-model is that it holds a column which is json an has to be casted.
Any idea what is going on here?
All of these happens in a middleware. No difference if i use with or load.
public function handle($request, Closure $next)
{
$UserData = \Auth::user();
if($UserData){
$User = \App\Login::with(['role','customer','customer.crmaccount'])->find($UserData->id);
dump($User);
dd($User->toArray());
$UserData['isAdmin'] = false;
if($UserData['role']['name'] === 'Admin'){
$UserData['isAdmin'] = true;
}
$request->request->add(['UserData' => $UserData]);
}
return $next($request);
}
Login
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Login extends Authenticatable{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','customer_id','role_id'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/* */
public function Role(){
return $this->belongsTo('App\Role');
}
public function Customer(){
return $this->belongsTo('App\Customer');
}
/**
* [hasOpportunities Ruft alle Opportunities des Users ab. Da diese lediglich zwei Entitäten weiter sind, kann anstatt von dot-notated Lazy-Load auch die hasManyThrough-ORM-Methode genutzt werden]
* #return [hasManyThrough-Relation] [Die hasManyThrough-ORM-Beziehung]
*/
public function hasOpportunities(){
return $this->hasManyThrough(
'App\Opportunity',
'App\Customer',
'id',
'customer_id',
'customer_id'
);
}
/**
* [hasSalesreps Ruft alle SalesReps des Users ab. Da diese lediglich zwei Entitäten weiter sind, kann anstatt von dot-notated Lazy-Load auch die hasManyThrough-ORM-Methode genutzt werden]
* #return [hasManyThrough-Relation] [Die hasManyThrough-ORM-Beziehung]
*/
public function hasSalesreps(){
return $this->hasManyThrough(
'App\Salesrep',
'App\Customer',
'id',
'customer_id',
'customer_id'
);
}
}
Customer
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model{
public $timestamps = false;
protected $visible = ['id','name'];
protected $fillable = ['name'];
public function crmaccount(){
return $this->hasOne('App\Crmaccount');
}
public function Salesreps()
{
return $this->hasMany('App\Salesrep');
}
public function Prospects()
{
return $this->hasMany('App\Prospect');
}
public function Trees()
{
return $this->hasMany('App\Salesreptrees');
}
public function Opportunities()
{
return $this->hasMany('App\Opportunity');
}
public function User()
{
return $this->hasMany('App\Login');
}
}
Crmaccount
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Crmaccount extends Model{
public $timestamps = false;
protected $visible = ['id','name','crm_system','customer_id','crm_api_config'];
protected $fillable = [
'name','crm_system','customer_id','crm_api_config'
];
protected $casts = [
'crm_api_config' => 'array'
];
public function customer(){
return $this->belongsTo('App\Customer');
}
}
On every model, there is a protected $visible = []; and protected $hidden = [] attribute. These control the attributes that are available when the model is converted to an object, array or json. This includes relationships, as Laravel internally converts them to attributes, so omitting them from visible, or including them in hidden will cause them to not be available.
In Customer.php:
protected $visible = ['id','name'];
Since crmaccount is not in that array, only id and name will be available. Simply add crmaccount to the array to handle:
protected $visible = ['id','name', 'crmaccount'];
Alternatively, use hidden to explicitly set the attributes you don't want to show, and relationship, if loaded via ->with() will show by default.

define an alias name for primary key in a model that is extended in laravel

I have a Stuff Model like this :
class Stuff extends Model
{
protected $primaryKey = 'stuff_id';
protected $fillable = ['stuff_id' , 'title' , 'desc'];
protected $dates = ['deleted_at'];
}
In the other hand there is a Product model that extended from Stuff Model like this :
class Product extends Stuff
{
protected $fillable = ['quantity' , 'picture'];
}
As you can see beacause Product is extended from Stuff and primary key of Stuff is stuff_id , Anywhere that I want to call a Product instances and needs to print it's id should use a $product->stuff_id while I want use a clearer name for that like $product->product_id.
Is there any way that can define a alias primary key in child model that interpreted to stuff_id in back-end when running queries on database.
To turn product_id into an alias of stuff_id:
...
$product->product_id // resolves to $product->stuff_id
...
public function getProductIdAttribute(): int
{
return $this->stuff_id;
}
...
Instead of using $primaryKey, you can override the function that reads from that variable.
In your Stuff model, try adding something along the lines of:
/**
* Get the primary key for the model.
*
* #return string
*/
public function getKeyName(): string
{
return [
Stuff::class => 'stuff_id',
Product::class => 'product_id',
][get_class($this)];
}
And for reference, the default behavior: (Illuminate/Database/Eloquent/Model.php)
/**
* Get the primary key for the model.
*
* #return string
*/
public function getKeyName()
{
return $this->primaryKey;
}
Using Global Scope:
//Say ProductScope.php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Schema;
class ProductScope implements Scope
{
protected $model_name;
public function __construct($model_name)
{
$this->model_name = $model_name;
}
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$attr = Schema::getColumnListing($this->model_name);
$attr_ = array_map(function ($item){
return $item === 'stuff_id' ? $item.' as product_id' : $item;
}, $attr);
$builder->select($attr_);
}
}
Then in the Product Model:
use App\Scopes\ProductScope;
class Product extends Stuff
{
protected $table = 'stuffs';
protected $primaryKey = 'stuff_id';
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new ProductScope('stuffs'));
}
}
This will replace the stuff_id with product_id

Defining many-to-many bidirectional relations more eloquently

I have implemented the relationship without Eloquent but I was wondering is there was a way to define this relationship in Eloquent so that my application can have more consistency.
table User
-id
-other user attributes
table friend_requests:
-id
-sender_id
-reciever_id
table friends
-id
-first
-second
The friendRequest relation has been easily implemented in the Eloquent but the problem lies in Friends.
If I do this in the User model class:
public function friends(){
return $this->belongsToMany(User::class,'friends','first','second');
}
This wouldn't work as you would have noticed. Let me explain with example:
Table: friends
id | first | second
1 | 1 | 2
2 | 3 | 1
you see that user_1 is friends with user_2 as well as user_3 as the relationship is bi-directional. But Eloquent will naturally return that user_1 is friends with user_2 only. After thinking for a while I tweaked the statement but made little progress'
public function friends(){
return $this->belongsToMany(User::class,'friends','first','second')
->orWhere('second',$this->id);
}
That is because now it selects both rows but the Users it returns are those whose id = second which means that in the second case it will return the user itself.
I implemented the relations with my own methods in User model class which use DB::table('friends')-> to addFriend(User $user), removeFriend(user $user) and returns list of friends(), but I'm disappointed that this isn't as eloquent as Eloquent relationships.
Perhaps some more experienced developers here would have come across this kind of problem and would have dealt better than I did. How do you propose I deal with this problem. Should I stick with my approach or is there a better way to deal with it?
A more manageable way to implement bidirectional relations would be to create two entries for each confirmed friendship.
So a user would make a friend request to another user. When the second user confirms the friend request, two friendships are created.
Example Controller
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use App\FriendRequest;
use App\Friendship;
class FriendshipController extends Controller
{
public function friendRequest(Request $request)
{
$receiver_id = $request->input('receiver_id');
$request->user()->friend_offers()->create([
'receiver_id' => $receiver_id
]);
}
public function friendshipConfirmation(Request $request)
{
$friend_request_id = $request->input('friend_request_id');
$friend_request = FriendRequest::find($friend_request_id);
$friend_request->receiver->friendships()->create([
'user_2_id' => $friend_request->sender->id
]);
$friend_request->sender->friendships()->create([
'user_2_id' => $friend_request->receiver->id
]);
}
}
Database Tables
(Note the proper spelling of receiver and plural users table)
table users
- id
- other user attributes
table friend_requests:
- id
- sender_id
- receiver_id
table friendships
- id
- user_1_id
- user_2_id
User Model
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable
{
use SoftDeletes;
public $timestamps = true;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
//
];
/**
* Return friend requests from other users
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function friend_requests()
{
return $this->hasMany(FriendRequest::class, 'receiver_id');
}
/**
* Return friend requests sent to other users
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function friend_offers()
{
return $this->hasMany(FriendRequest::class, 'sender_id');
}
/**
* Return friendships with other users
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function friendships()
{
return $this->hasMany(Friendship::class, 'user_1_id');
}
}
FriendRequest Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class FriendRequest extends Model
{
use SoftDeletes;
public $timestamps = true;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'sender_id',
'receiver_id'
];
/**
* Return the requesting user
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function sender()
{
return $this->belongsTo(User::class, 'sender_id');
}
/**
* Return the receiving user
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function receiver()
{
return $this->belongsTo(User::class, 'receiver_id');
}
}
Friendship Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Friendship extends Model
{
use SoftDeletes;
public $timestamps = true;
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that aren't mass assignable.
*
* #var array
*/
protected $guarded = ['id'];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_1_id',
'user_2_id'
];
/**
* Return user_1
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function first()
{
return $this->belongsTo(User::class, 'user_1_id');
}
/**
* Return user_2
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function second()
{
return $this->belongsTo(User::class, 'user_2_id');
}
}

Laravel Modeling join three Table in single line

i have 3 table/Model such as Users, CurrentCurrency and CurrencyType, in CurrentCurrency 2 column are relation with CurrencyType and Users, as user_id and currency_id
i can use this code to fetch CurrentCurrency user :
$all_records = CurrentCurrency::with('user')->orderBy('id', 'DESC')->paginate(50);
this code return all records with users, now i want to create simple related with CurrencyType by Modeling, unfortunately for this table i get null
CurrentCurrency :
class CurrentCurrency extends Model
{
protected $table = 'current_currency';
protected $fillable = ['currency_id', 'current_money', 'user_id'];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('App\User');
}
public function currency_type()
{
return $this->belongsTo('App\CurrencyType');
}
}
CurrencyType:
class CurrencyType extends Model
{
protected $table = 'currency_type';
protected $fillable = ['currency_type', 'currency_symbol', 'user_id'];
public function user()
{
return $this->belongsTo('App\User');
}
public function currency()
{
return $this->hasMany('App\current_currency');
}
}
User:
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* #param $value
*/
public function setPasswordAttribute($value)
{
$this->attributes['password'] = Hash::make($value);
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function currentCurrency()
{
return $this->belongsToMany('User', 'CurrentCurrency', 'user_id', 'currency_id');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function currencyType()
{
return $this->hasMany('App\CurrencyType');
}
}
By this code i can get user information:
$all_records = CurrentCurrency::with(['user', 'currency_type'])->orderBy('id', 'DESC')->paginate(50);
foreach ($all_records as $key => $contents) {
echo $contents->user;
}
But i can not get currency_type, thats return null
RESULT:
{"id":3,"current_money":"333","user_id":1,
"created_at":"\u0622\u0630\u0631 20\u060c 1394",
"updated_at":"\u0622\u0630\u0631 20\u060c 1394",
"currency_id":1,"user":{"id":1,"name":"\u0645\u0647\u062f\u06cc",
"family":"\u067e\u06cc\u0634\u06af\u0648\u06cc","username":"mahdi","token":"",
"email":"pishguy#gmail.com",
"image_file_name":"","mobile_number":"09373036569",
"status":1,"created_at":"\u0622\u0630\u0631 20\u060c 1394",
"updated_at":"\u0622\u0630\u0631 20\u060c 1394"},
"currency_type":null}
You have to update the relation in CurrentCurrency as below:
return $this->belongsTo('App\CurrencyType','currency_id', 'id');
// where currency_id is foreign_key and id is otherKey referring to id of currency_type table
Also update your query to select user with CurrencyType as below :
$all_records = CurrentCurrency::with(array('user','currencyType'))->orderBy('id', 'DESC')->paginate(50);
http://laravel.com/docs/5.1/eloquent-relationships#updating-belongs-to-relationships
In file CurrencyType
return $this->hasMany('App\current_currency');
should be
return $this->hasMany('App\CurrentCurrency');

pivot table in laravel 4 insertion

hey guys im new in laravel and i was trying to insert into my pivot table. i have this structure in my database
the departments table belongs to many categories and same as category so i have this models
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Departments extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'departments';
protected $fillable = ['department_name'];
public $timestamps = false;
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
public function categories()
{
return $this->belongsToMany('Categories');
}
}
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Categories extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'categories';
protected $fillable = ['name'];
public $timestamps = false;
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
public function department()
{
return $this->belongsToMany('Departments');
}
}
then i have a query in my controller like this
$messages = array(
'required' => 'Please Fill the required field',
'unique' => 'Name Already exist'
);
$catName = Input::get('categoryName');
$deptId = Input::get('deptId');
$validation = Validator::make(Input::all(),[
'categoryName' => 'required|unique:categories,name' ], $messages);
if($validation->fails()){
return array('error' =>$validation->messages()->all() );
}else{
$findDepartment = Departments::find($deptId);
$saveCat = $findDepartment->categories()->insert(array('name' => $catName));
}
but then when i checked the tables it adds up on the categories table but nothing is added in the category_department. do i miss any codes? and also i had an error last time I was trying to migrate my pivot table the error was this.
can you help me guys on what i am missing? tnx for the help in advanced.
First, you should name your model classes as singular: Category, Department.
Then try to declare your relationships with the pivot table name:
public function categories()
{
return $this->belongsToMany('Category', 'category_department');
}
and
public function departments()
{
return $this->belongsToMany('Departments', 'category_department');
}
now, to insert new data, try attach:
$findDepartment = Department::find($deptId);
$category = Category::where('name', '=', $catName)->first();
$saveCat = $findDepartment->categories()->attach($category->id);

Resources