Newbie question here,
I'm having an employee/profile model, where I have a boot function to create a user on the creation of the employee model.
public static function boot()
{
parent::boot();
static::created(function($model)
{
$User = new \App\Models\User;
$User->id = $model->id;
$User->name = $model->first_name.' '.$model->last_name;
$User->email = $model->work_email;
$User->save();
});
while checking the DB i notice it's not picking the employee ID (UUID) and saving the same id as user ID
$User->id = $model->id;
what I'm doing wrong here ?
i have found that i can update it after saving
by adding
public static function boot()
{
parent::boot();
static::created(function($model)
{
$User = new \App\Models\User;
$User->id = $model->id;
$User->name = $model->first_name.' '.$model->last_name;
$User->email = $model->work_email;
$User->save();
$User->id = $model->id;
$User->save();
});
}
is there is way to do it without saving two times?
You are fundamentally misunderstanding how database relations should be created. You do not indicate that two entries are related by giving them the same ID.
You do it by creating a foreign key between the two tables in your migration:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->foreignId('employee_id')->constrained('employees');
$table->string('name');
$table->string('email');
});
}
And then creating a relationship in your ORM.
class User extends Authenticatable {
public function employee() {
return $this->belongsTo(Employee::class);
}
}
class Employee extends Model {
public function user() {
return $this->hasOne(User::class);
}
}
And then your event handler looks like this:
public static function boot()
{
parent::boot();
static::created(function ($model) {
$u = User::make([
'name' => $model->first_name . ' ' . $model->last_name,
'email' => $model->work_email,
]);
$u->employee = $model;
$u->save();
});
}
Now you have related user to employee, such that you can do things like this:
$user = User::find(123);
echo $user->employee->first_name;
Try using forceCreate(...) instead.
Save a new model and return the instance. Allow mass-assignment.
\App\Models\User::forceCreate([
"id" => $model->id,
"name" => $model->first_name . ' ' . $model->last_name,
"email" => $model->work_email,
]);
Addendum
Alternatively, you may use forceFill(...)
Fill the model with an array of attributes. Force mass assignment.
(new \App\Models\User)->forceFill([
"id" => $model->id,
"name" => $model->first_name . ' ' . $model->last_name,
"email" => $model->work_email,
])->save();
If you create a new user, you shouldn't add id. If you want to update an existing user, you should use for example find instead of creating a new model object
Related
I have a simple relationship in laravel eroquent
Here is the bidders table creation
public function up()
{
Schema::create('bidders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('params_name');
$table->string('params_value');
$table->string('bidder_name');
$table->timestamps();
});
}
Here is bidder_parameter table creation
public function up()
{
Schema::create('bidder_parameters', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('bidder_id');
$table->foreign('bidder_id')->references('id')->on('bidders')->onDelete('cascade');
$table->timestamps();
});
}
Here is a bidder model
class Bidder extends Model
{
protected $table = 'bidders';
protected $fillable = [
"params_name",
"params_value",
"bidder_name"
];
public function page()
{
return $this->hasMany('App\Page');
}
public function parameters()
{
return $this->hasMany('App\BidderParameter');
}
}
and here is BidderParameter model
class BidderParameter extends Model
{
public function parameters()
{
return $this->belongsTo('App\Bidder');
}
}
Here is parameter controller for inserting data to database
public function store(Request $request){
// dd($request);
if($request->ajax())
{
$rules = array(
'params_name.*' => 'required',
'params_value.*' => 'required',
'bidders_name.*' => 'required'
);
$error = Validator::make($request->all(), $rules);
if($error->fails())
{
return response()->json([
'error' => $error->errors()->all()
]);
}
$params_name = $request->params_name;
$params_value =$request->params_value;
$bidders_name =$request->bidders_name;
for($count = 0; $count < count($params_name); $count++)
{
$data = array(
'params_name' => $params_name[$count],
'params_value' => $params_value[$count],
'bidders_name' => $bidders_name[$count],
);
$insert_data[] = $data;
// dd($insert_data);
}
Bidders:insert($insert_data);
return response()->json([
'success' => 'Data Added successfully.'
]);
}
}
Now when I submit data to the database 'bidders tablehave data saved into it butbidder_parameter` is empty
What is wrong with my code?
Many to many relationship contains 3 tables. 2 tables are main and 3rd table is combination of those 2 tables' primary keys.
For example
User can have many roles
and
Role can belong to many users
so that requires many to many relationship
So we need a database schema like this:
Users table -> (id, name ,...) e.g. Jonn Doe with id 1
Roles table -> (id, name, ...) e.g. SUPER_ADMIN with 1
role_user table (id, user_id, role_id) role_id is foreign key of roles table and user_id is foreign key of users table
Now in Model classes:
In User Model
public function roles(){
return $this->belongsToMany(Role::class,'role_user','user_id','role_id');
}
Now in Roles class
public function users(){
return $this->belongsToMany(User::class,'role_user','role_id','user_id');
//note keys are in opposite order as in roles() method
}
Now you can call function from User instance and Role instance where you want
$user->roles // as collection
$user->roles() // as eloquent instance
Also
$role->users // as collection
$role->users() // as eloquent instance
You can read more here
I am building a system to support referral programs. It allows you to track links, programs and for how long will cookie last. Also allows you to easily decide how will user benefit after referring other user to for example sign up.
This' for generating unique referral code on creating a referral link. I am able to use this code to track the link and and relate it to original user who shared it. Factory method getReferral is creating single referral link for each user for a given program.
// ReferralLink Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Ramsey\Uuid\Uuid;
class ReferralLink extends Model
{
protected $fillable = ['user_id', 'referral_program_id'];
protected static function boot()
{
static::creating(function (ReferralLink $model) {
$model->generateCode();
});
parent::boot();
}
private function generateCode()
{
$this->code = (string)Uuid::uuid1();
}
public static function getReferral($user, $program)
{
return static::firstOrCreate([
'user_id' => $user->id,
'referral_program_id' => $program->id
]);
}
public function getLinkAttribute()
{
return url($this->program->uri) . '?ref=' . $this->code;
}
public function user()
{
return $this->belongsTo(User::class);
}
public function program()
{
return $this->belongsTo(ReferralProgram::class, 'referral_program_id');
}
public function relationships()
{
return $this->hasMany(ReferralRelationship::class);
}
}
StoreReferralCode middleware
use App\ReferralLink;
// ...
public function handle($request, Closure $next)
{
$response = $next($request);
if ($request->has('ref')){
$referral = ReferralLink::whereCode($request->get('ref'))->first();
$response->cookie('ref', $referral->id, $referral->lifetime_minutes);
}
return $response;
}
UserReferred Event handler
class UserReferred
{
use SerializesModels;
public $referralId;
public $user;
public function __construct($referralId, $user)
{
$this->referralId = $referralId;
$this->user = $user;
}
public function broadcastOn()
{
return [];
}
}
And of course this' how I am broadcasting the event on RegistrationController
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
event(new \App\Events\UserReferred(request()->cookie('ref'), $user));
return $user;
}
I am not able to create a relationship in the DB on grounds of who shared a link with who. What could be wrong with my code ?
//referral_relationships schema
Schema::create('referral_relationships', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('referral_link_id');
$table->integer('user_id');
$table->timestamps();
});
User model:
public function userable()
{
return $this->morphTo();
}
Mentor model:
public function user()
{
return $this->morphOne('App\Models\User', 'userable');
}
The student model looks the same as the mentor model.
The tables for Students and Mentors contain a custom PK called user_id which references the primary key on the users table.
So what I'm trying to do is the following:
$user = new User();
$user->first_name = 'Trajce';
$user->last_name = 'Petkoski';
$user->nickname = 'ads';
$user->administrator = '0';
$user->email = 'asd';
$user->password = Hash::make('test');
$user->save();
$mentor = new Mentor();
$mentor->user_id = $user->id;
$mentor->save();
$user->userable_id = $mentor->user_id;
$mentor->user()->save($user);
However, on the Users table, userable_id is being set to 0 while userable_type value is set to the corret value. The issue here is that save() sets it to a predefined 0. Any idea what's going on behind the scenes?
Try this to add data to Polymorphic relation (morphOne):
Migrations:
// User
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('first_name');
$table->string('last_name');
$table->string('nickname');
$table->integer('administrator');
$table->string('email');
// add these two for the relation to work
$table->integer('userable_id')->unsigned();
$table->string('userable_type');
//
$table->rememberToken();
$table->timestamps();
});
// Mentor
Schema::create('mentors', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
User Model
public function userable()
{
return $this->morphTo();
}
Mentor Model
public function user()
{
return $this->morphOne('App\Models\User', 'userable');
}
Association Code:
$mentor = new Mentor();
// this is important: first save mentor
$mentor->save();
$userdata = [
'first_name' => 'Trajce',
'last_name' => 'Petkoski',
'nickname' => 'ads',
'administrator' => 0,
'email' => 'asd',
'password' => Hash::make('test')
];
$mentor->user()->create($userdata);
This works like a charm in my Laravel 5.4 test installation
Try this
public function users() {
return $this->morphMany('App\Models\User', 'userable');
}
Having first steps in laravel, and just hit the wall.
I Have two entities:
Schema::create('company', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->increments('id');
$table->string('name')->unique();
$table->integer('addressid')->unsigned()->nullable();
});
and
Schema::create('addresses', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->increments('id');
$table->string('street');
(...)
});
Schema::table('company', function($table) {
$table->foreign('addressid')
->references('id')->on('addresses')
->onDelete('cascade');
});
Models are
class Address extends Model {
public function shipyard() {
return $this->belongsTo('App\Company', 'addressid');
}
}
class Company extends Model {
public function address() {
return $this->hasOne('App\Address', 'id', 'addressid');
}
}
When I want to create these entities in DB I use one form in HTML to gather all data. Then I post request and do:
Route::post('/company', function (Request $request) {
(...validation...)
$company = new Company();
$company->name = $request->name;
$address = new Address();
$address->street = $request->street;
(...)
$company->address()->save($address);
$company->save();
return redirect('/');
});
As a result I have two entities in DB, but the "addressid" field is null. Why?
Change relation in company (relation in address you can delete):
class Company extends Model {
public function address() {
return $this->belongsTo('App\Address', 'addressid');
} }
Saving code:
Route::post('/company', function (Request $request) {
(...validation...)
$company = new Company();
$company->name = $request->name;
$address = new Address();
$address->street = $request->street;
(...)
$address->save();
$company->address()->associate($address);
$company->save();
return redirect('/');
});
class Address extends Model {
// Added fillable array for mass assigment
protected $fillable = ['street'];
public function shipyard() {
return $this->belongsTo('App\Company', 'addressid');
}
}
class Company extends Model {
// Added fillable for mass assignment
protected $fillable = ['name','addressid'];
// The second argument for the hasOne takes a foreign key not a primary key
public function address() {
return $this->hasOne('App\Address', 'addressid');
}
}
$company = new Company();
$company->name = $request->name;
$company->save();
$company->address()->create($request->street)
Hi all i am trying to create a campaign. In the process of campaign i will assign certain products to that campaign. So i have to insert details after post campaign creation into two tables one is campaigns and another one is campaignsproducts. So i created two models for each of them on the same names.
I am trying to insert records into both tables on post action using save method. I am able to insert into campaigns but when it comes to campaignsproducts it says campaigns_products table not exists.
In my db my table name was CampaignsProducts. Please help where i am going wrong. Please find my migration, model and post action code below.
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCamapignproductsTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('campaignproducts', function(Blueprint $table)
{
$table->increments('id');
$table->integer('campaign_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->decimal('product_sell_cost', 10, 2);
$table->timestamps();
});
Schema::table('campaignproducts', function($table) {
$table->foreign('campaign_id')->references('id')->on('campaigns');
$table->foreign('product_id')->references('id')->on('products');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('campaignproducts');
}
}
Model CampaignProducts.php
<?php
class CampaignProducts extends Eloquent {
public function camapigns(){
return $this->hasMany('Campaign');
}
public function products(){
return $this->hasMany('Product');
}
}
Post action in controller
public function postCampaign()
{
//validation rules for create product
$rules = array(
'campaign_name' => 'required|min:2',
'campaign_description' => 'required|min:2',
'campaign_startdate' => 'required|date_format:"Y-m-d"',
'campaign_enddate' => 'required|date_format:"Y-m-d"',
'campaign_urlname' => 'required|between:4,20',
'campaign_target' => 'required|integer|min:1',
'user_id' => 'required|integer|min:1'
);
$validator = Validator::make(Input::all(), $rules);
//procee the validation rules
if($validator->fails()) {
return Redirect::to('products/newcampaign')
->withErrors($validator)
->withInput();
} else {
echo "<pre>";
print_r(Input::all());
//store category data
$campaign = new Campaign;
$campaign->campaign_name = Input::get('campaign_name');
$campaign->campaign_description = Input::get('campaign_description');
$campaign->campaign_startdate = Input::get('campaign_startdate');
$campaign->campaign_enddate = Input::get('campaign_enddate');
$campaign->campaign_urlname = Input::get('campaign_urlname');
$campaign->campaign_target = Input::get('campaign_target');
$campaign->user_id = Input::get('user_id');
$campaign_id = $campaign->save();
$campaign_products = Input::get('productid');
$campaignproducts = new CampaignProducts;
foreach($campaign_products as $key => $id)
{
$campaignproducts->product_id = $key;
$$campaignproducts->product_sell_cost = $id;
$campaignproducts->campaign_id = $campaign_id;
$campaignproducts->save();
}
//redirect
Session::flash('message', 'Successfully created campaign!');
return Redirect::to('campaigns');
}
}
Add this to your CampaignProducts model:
class CampaignProducts extends Eloquent {
protected $table = 'campaignsproducts';
...
Or the other option is to change your table name when you create it instead:
Schema::create('campaign_products', function(Blueprint $table)