Laravel PHP: how to join each element of collection after update? - php

I have Clients collection in Laravel. $clients = Client::all();
I need to update it with a user's name for each item inside a collection.
This is my code:
$clients = Client::all();
$clients->each(function ($item, $key) {
if ($item->user()->first())
{
$user = $item->user()->first();
$name = $user->name;
} else $name = '';
$client = collect($item);
$client = $client->union(['user' => $name]);
});
The question is what is a proper way to form $clients Collection with $client updated.
So I need to return $clients whith user name included.
Models:
// Client Model
public function user()
{
return $this->belongsTo('App\User');
}
// User Model
public function clients()
{
return $this->hasMany('App\Client');
}
Migration:
Schema::create('clients', function (Blueprint $table) {
$table->bigIncrements('id');
$table->char('name', 200)->nullable();
$table->char('city', 100)->nullable();
$table->char('type', 20)->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->unsignedBigInteger('user_id')->nullable();
$table->timestamps();
$table->softDeletes();

You can do something like below:
$clients = Client::all();
$clients->each(function ($item, $key) {
$name = $item->user ? $item->user->name : "";
return $name; // will append name in this client collection
});
return $clients
To read more about each method visit
Hope it helps.
Thanks

Related

live-chat application message and user model

I'm developing a live chat application and i don't know which is the proper db structure. I thought that the best solution is to have a Message model that belongs to a Sender and to a Receiver. In this way things should work, but when i seed i have a lot of problems, like only the first user got the relations accessible. I share my code below.
Message Migration
public function up()
{
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->text('content');
$table->foreignUuid('from_id')->references('uuid')->on('users');
$table->foreignUuid('to_id')->references('uuid')->on('users');
});
}
User migration
$table->id();
$table->uuid('uuid')->unique();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('profile')->default(public_path('images/default_profile.jpg'));
$table->rememberToken();
$table->timestamps();
Message Model
class Message extends Model
{
use HasFactory;
protected $table = "messages";
public function sender()
{
return $this->belongsTo(User::class, 'from_id');
}
public function receiver()
{
return $this->belongsTo(User::class, 'to_id');
}
}
User model
public function sent()
{
return $this->hasMany(Message::class, 'from_id');
}
public function received()
{
return $this->hasMany(Message::class, 'to_id');
}
public function contacts()
{
DatabaseSeeder
User::factory()->create([
'name' => 'username',
'email' => 'admin#admin.com',
'password' => bcrypt('password')
]);
Message::factory()
->count(200)
->create();
User::factory()->count(10)->create();
$users = User::all();
$messages = Message::all();
User::all()->each(function ($user) use ($users) {
do {
$idsToAttach = $users->random(rand(1, 3))->pluck('id')->toArray();
$idsToAttach = array_diff($idsToAttach, array($user->id));
} while (count($idsToAttach) <= 0);
$user->contacts()->attach(
$idsToAttach
);
});
$messages->each(function ($message) use ($users) {
do {
$sender = $users->random(1)->pluck('uuid');
$receiver = $users->random(1)->pluck('uuid');
} while ($sender[0] == $receiver[0]);
$message->receiver()->associate(
$receiver[0]
);
$message->sender()->associate(
$sender[0]
);
$message->save();
});
}
your seeder can be way easier,
maybe in your user factory, you can override configure() method as below, and register an afterCreating callback as below:
public function configure(): UserFactory
{
return $this->afterCreating(Closure::fromCallable([$this, 'attachRelations']));
}
where attachRelations is a method that will be called after every user creation, you can do many things in there, things like :
function attachRelations(User $user)
{
// Assign a random amount of languages to a user
$languages = Language::all();
$user->languages()->sync($languages->random(rand(1, $languages->count())));
// Assign a fake avatar to a user, just a record no file
$avatar = Avatar::factory()->make();
$user->avatar()->save($avatar);
}
this way, I will attach a random amount of languages to each user, and also assign an avatar record, I hope you got the idea
laravel doc: Here
let me know if you need help

How to Build an api to follow and unfollow user in laravel with postman

How to create an Api in laravel to follow and unfollow user
public function follow(){
$id = Auth::id();
$result = User::where('id', '!=', $id)->get();
//return $result;
return response()->json(['data' => $result], 200,[],JSON_NUMERIC_CHECK);
}
public function followUser(user $user){
if (!Auth::user()->isFollowing($user_id)){
Auth::user()->follows()->create([
'target_id' =>$user_id,
]);
return response()->json(['sucess'=>'sucessfully followed']);
}else{
return response()->json(['oops'=>'u already followed ']);
}
}
public function unfollowUser(User $user)
{
if (Auth::user()->isFollowing($user->id)) {
$follow = Auth::user()->follows()->where('target_id', $user->id)->first();
$follow->delete();
return response()->json(['success', 'You are no longer friends with '. $user->name]);
} else {
return response()->json(['error', 'You are not following this person']);
}
}
here is my code and this is my route to use in postman
Route::post('/followUser/{user}','Api\FollowuserController#followUser');
Route::get('/unfollowUser/{user}','Api\FollowuserController#unfollowUser');
i am using the route to follow with sessionid on user id but getting nothing ...
how should i do this
I suggest you for route
Route::post('users/{id}/action', 'API\UserController#action');
and for body request:
{
"act":"follow" //or unfollow
}
table:
public function up()
{
Schema::create('action_logs', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('object_id')->unsigned();
$table->enum('object_type',['USER','PAGE','POST']);
$table->enum('act',['FOLLOW','UNFOLLOW','VISIT' ,'LIKE','DISLIKE']);
$table->timestamp('created_at');
$table->foreign('user_id')->references('id')->on('users')
->onDelete('restrict')
->onUpdate('restrict');
});
//Or to make it easier
Schema::create('follower_following', function (Blueprint $table) {
$table->integer('follower_id')->unsigned();
$table->integer('following_id')->unsigned();
$table->primary(array('follower_id', 'following_id'));
$table->foreign('follower_id')->references('id')->on('users')
->onDelete('restrict')
->onUpdate('restrict');
$table->foreign('following_id')->references('id')->on('users')
->onDelete('restrict')
->onUpdate('restrict');
});
in model (user.php)
public function followers()
{
return $this->belongsToMany('App\User', 'follower_following', 'following_id', 'follower_id')
->select('id', 'username', 'name','uid');
}
public function following()
{
return $this->belongsToMany('App\User', 'follower_following', 'follower_id', 'following_id')
->select('id', 'username', 'name','uid');
}
action method: (if you have page and other object ... It's better to have this method in an trait)
public function action($id, Request $request)
{
// $user
switch ($request->get('act')) {
case "follow":
$user->following()->attach($id);
//response {"status":true}
break;
case "unfollow":
$user->following()->detach($id);
//response {"status":true}
break;
default:
//response {"status":false, "error" : ['wrong act']}
}
}

Laravel 5.4: Cannot retrieve data from a relationship

I'm trying to display the name of the assignee (foreign key from Users table) of each ticket by storing each name in an array from two UNION'd tables (Accesses and Reports) but it gives me this error. ErrorException
Undefined property: stdClass::$assignee.
//HomeController
$accesses = DB::table('accesses')
->select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->where('state','=','Assigned');
$all = DB::table('reports')
->select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->union($accesses)
->where('state', '=', 'Assigned')
->get();
$names[] = array();
foreach ($all as $one)//store in array to display in a chart
{
$names[] = $one->assignee->name; //error here
}
//Report Model
public function assignee()
{
return $this->belongsTo(User::class, 'assigned_to');
}
//Access Model
public function assignee()
{
return $this->belongsTo(User::class, 'assigned_to');
}
//Report Migration
public function up()
{
Schema::create('reports', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->nullable();
$table->string('fullname');
$table->string('emp_id');
$table->string('shift');
$table->longText('report');
$table->string('status')->default('Pending'); //Pending, Approved
$table->string('state')->default('Open'); //Open, Assigned, Resolved, Closed
$table->date('resolved_at')->nullable();
$table->date('closed_at')->nullable();
$table->integer('assigned_to')->nullable();
$table->longText('action')->nullable();
$table->timestamps();
});
}
//Access Migration
public function up()
{
Schema::create('accesses', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->nullable();
$table->string('fullname');
$table->string('emp_id');
$table->string('shift');
$table->string('request');
$table->longText('note')->nullable();
$table->string('status')->default('Pending'); //Pending, Approved
$table->string('state')->default('Open'); //Open, Assigned, Resolved, Closed
$table->date('resolved_at')->nullable();
$table->date('closed_at')->nullable();
$table->integer('assigned_to')->nullable();
$table->longText('action')->nullable();
$table->timestamps();
});
}
It gives me this error
The results should be like this
You should use merge method of collection:
$accesses = Access::select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->where('state','=','Assigned')
->get();
$reports = Report::select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->where('state', '=', 'Assigned')
->get();
$all = $accesses->merge($reports);

laravel eloquent one-to-one save relation

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)

laravel eloquent eager loading nested condition

I have 2 tables that is using eager loading and then using nested condition in that eager loading:
//migration for lead table
public function up()
{
Schema::create('leads', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('first_name',255);
$table->string('surname',255);
});
Schema::table('leads', function($table)
{
$table->foreign('create_by')->references('id')->on('employees')->onDelete('cascade');
});
}
//lead for lead detail emails
public function up()
{
Schema::create('lead_detail_emails', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('lead_id')->unsigned();
$table->string('email',255);
});
Schema::table('lead_detail_emails',function($table)
{
$table->foreign('lead_id')->references('id')->on('leads')->onDelete('cascade');
});
}
//leads model
class LeadsModel extends Eloquent
{
protected $table = 'leads';
public function emails()
{
return $this->hasMany('LeadDetailEmailsModel','lead_id','id');
}
}
//lead detail emails
class LeadDetailEmail extends Eloquent
{
protected $table = 'lead_detail_email';
public function lead()
{
return $this->belongsTo('LeadsModel');
}
}
When I am trying to add nested condition to eager loading, lets say
$qry = LeadsModel::with(
array
(
'emails' => function($qr)
{
$qr->orWhere('email','like','%testname%');
}
));
$res = $qry->get();
dd($res);
It returns all the records in the lead, I have tried joining emails and $qry by using
->join('lead_detail_emails','lead_detail_emails.lead_id','=','leads.id');
but it does not work as well. may I know what is the problem in the code?
update question
how can i get the leads by doing nested condition on the emails?
$qry = LeadsModel::with(array('emails' => function ($q) use ($input) {
$q->where('email','like',"%{$input}%");
}))->whereHas('emails', function ($q) use ($input) {
$q->where('email','like',"%{$input}%");
});
$res = $qry->get();

Categories