How to verify if the user is soft deleted or destroyed - php

So I'm starting my path on the front end development. I have a table with user description and a button that changes the state of the user. Everything except a validation works fine, the state is being changed and the page is refreshed correctly. Here is my code...
public function changeState(Request $request)
{
if($request->ajax()){
$usernames = Input::get('usernameSend');
if(isset($usernames)){
$user = User::Where('username', '=', $usernames);
if ( !$user->get() ){
Log::warning("User not found.");
} else {
if(!$user->get()->isEmpty()) { // verify if the user is active
$user->delete(); //soft delete the given user
}else{
$user->restore(); //removes the soft delete for the given user
}
}
}else{
Log::warning("Username doesn't exist on database.");
}
}
}
I'll explain what I find important on my logic
if(isset($usernames)) -> verify if the username sent through the AJAX request is valid
if ( !$user->get() ) -> verify if the user is on the database
(!$user->get()->isEmpty()) -> verify if the user is soft deleted
I eventually want to add a function where one administrator can destroy a entry and although this works fine this way, the page is refresh and the user is vanished I think I should warn the user that the state wasn't changed and the user wasn't found in the database. But the if ( !$user->get() ) is ignored even if I delete the user from the database manually and then run the script...been searching on the Database API but found nothing. What am I doing wrong?
TIA
Edit: To clarify a bit more here are some images to exemplify
The user is in the dabatase(working as intended)
I removed the user from the database(database is ordered by ID)
Still the same result(not working as intended)
When I refresh the page the entry is gone(what shows that I'm actually removing the entry from the database)

From Laravel soft deleting
In addition to actually removing records from your database, Eloquent can also "soft delete" models. When models are soft deleted, they are not actually removed from your database. Instead, a deleted_at attribute is set on the model and inserted into the database. If a model has a non-null deleted_at value, the model has been soft deleted. To enable soft deletes for a model, use the Illuminate\Database\Eloquent\SoftDeletes trait on the model.
Your user model must contain the SoftDeletes trait, such as:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
// ...
To check whether a user is soft deleted, use the trashed method:
<?php
$users = App\User::withTrashed()->get();
foreach ($users as $user) {
if ($user->trashed()) {
// this user is soft deleted
} else {
// this user is not deleted
}
}
Anything not in $users has been hard deleted.
You can restore any soft deleted record by doing:
$user->restore();

You need to use withTrashed if you want to restore from deleted records(soft).
Use this in
User::withTrashed()->Where('username', '=', $usernames)->restore();

Related

Laravel 5.5 - Prevent additional attribute to be used during model update

The users table, besides others, have these fields: username, first_name, last_name. Each user can decide whether to show the username or the full name (first + last). This choice is stored inside a "settings" table.
To not perform repeated queries and calls to a function any time I need to show the name, I add the name to display to the user object as it is created, like $user->display_name = ... according to the user's choice.
The problem is that when the user updates the profile, Laravel tries to save this name inside a display_name field into the users' table, which doesn't exist and returns a 500 error. That also happens when the user tries to logout.
Is it possible to avoid that Laravel tries to store that value inside the database?
As suggested in other discussions I have already tried to give a default value to the attribute inside the User model, I've tried to set the attribute as protected, but nothing did work.
This is where the get{...}Attribute() function of a Model comes in handy. Say you want to access $user->full_name without actually saving full_name to the database. Since you have first_name and last_name, you can declare on your User model:
public function getFullNameAttribute(){
return $this->first_name." ".$this->last_name;
}
Laravel will parse what's between get and Attribute into a property available on the model, in this case either $user->full_name or $user->fullName.
To translate this to your use case, you can use something like:
In your User.php model:
public function getDisplayNameAttribute(){
if($this->settings == "use_full_name"){
return $this->first_name." ".$this->last_name;
} else if($this->settings == "use_username"){
return $this->username;
}
return "Not Configured...";
}
Note: You'll have to configure your if statements to determine what to return based on your settings.
Somewhere in a controller or view, you can call $user->display_name to have one of 3 things (determined by the logic/return statements above) displayed:
public function example(){
$user = User::first();
dd($user->display_name);
// $user->first_name." "$user->last_name, $user->username or "Not Configured..."
}
By doing this, when you access your $user, it will have a display_name property available that doesn't actually exist on the model, so you won't run into issues should you call $user->save();

Laravel Model Restore Event

So I have 2 Models Users & Staff. They have one to one relationship with one another.
User.php 'hasOne' Staff
AND
Staff.php 'belongsTo' User
When I Soft Delete a User I want to soft delete Staff entry as well, I have achieved this using(Works Perfectly):
static::deleting(function ($user) {
$user->staff()->delete();
});
Now I want to restore the staff when I restore the User for that I have tried using this(Not working):
static::restoring(function ($user) {
$user->staff()->restore();
});
But this is not working. The User Entry is deleted but the Staff entry still remains soft deleted.
Can someone help me understand what I am doing wrong here?
Also, Is this the best way to get this done? Or is there some other way this should be done?
PS: I'm using Laravel 5.5
It isn't working because $user->staff() doesn't fetch deleted staff. That's how relationships work by default.
Just replace it with this:
static::restoring(function ($user) {
$user->staff()->withTrashed()->restore();
});
"static::restoring" event is never triggered when restoring a batch of models.
If you're doing something like:
Yourmodel::whereIn('id', [1,2,3])->restore();
It will restore your models but "static::restoring or restored" will never be triggered, instead you could do something like this:
$models = Yourmodel::whereIn('id', [1,2,3])->get();
foreach($models as $model) {
$model->restore();
}

Relationship condition if user is logged in

I want to create a relationship that checks if a user has liked a post. In order to do this, the relationship needs to check if the user is logged in, and then use their user_id to get the like record. Something like:
public function userLike() {
if (Auth::check()) return $this->hasOne('App\Like')->where('user_id', Auth::user()->id);
}
However, this doesn't work. Additionally, if the user is not logged in and this relationship is called (which it is by default), it will return an error.
What is the proper way of doing this?
If you want to conditionally load a relation then you can do so by lazy eager loading. In your example you could define the relation as
public function userLike() {
return $this->hasOne('App\Like', 'user_id');
}
Then in your controller (or wherever else) you can do the check for if the user is question is currently logged in user or not
$loggedInUser = auth()->user();
if($loggedInUser){
$loggedInUser->load('userLike');
}
Then you can continue with whatever you want to do with the loggedInUser and the userLike.
Say you have multiple users at a point (in your code) and you want to load the likes for only the currently logged in user then you can
//$users is a collection of multiple users - assumed
foreach($users as $user){
if($user->email === auth()->user()->email){
$user->load('userLike');
}
}
Hope this helps
This is how I would do that:
1) “likes” table
I would first create a table to store all the “likes” with columns for a “post_id” and a “user_id”
2) create the relationships
User Model
public function likes()
{
    return $this->belongsToMany('App\Post', 'likes', 'user_id', 'post_id');
}
Post Model
public function likes()
{
return $this->belongsToMany('App\User', 'likes');
}
3) Post Controller - the method
I would do the followings:
check if user is logged in, otherwise throw an error
make sure post exists, otherwise throw an error
create a new entry in like table with user_id and post_id
(you can also check if the user is logged in directly on your route using a middleware)
4) In the view
I would call the controller method using an ajax call.
Not sure if I forgot something, but hopefully that can help you a little bit.
If you need to “like” more things than only post, check the polymorphic relationships.

Laravel get relation from softdelete

I've got 2 tables,
user
intern
A user belongsTo a intern, and a inter hasOne user. My problem is that when I've softdelete a user record and the related intern record. And I want to restore it i can't find the related intern anymore.
So when I find the user like this:
$user = user::onlyTrashed()->find($userId);
And then say $user->intern result is null because it cannot find intern
Trying to get property of non-object
How could I fix this?
Check whether the user exists. If does, do whatever you want to do.
Here's the code
$user = user::onlyTrashed()->find($userId);
if(!is_null($user)) {
echo $user->intern;
} else {
echo 'User does not exist!';
}
To get the soft deleted intern object from your user object, try the following:
$user->intern()->withTrashed()->get()->first()

Saving one to one relation in Laravel

A User has one (or zero) Company, and a Company belongs to one and only one User. I try to save a company for a user but it adds a new entry in database every time I re-trigger the save method. It's a one to one relation, so I though save method on User.
So Company has one method user():
public function user() {
return $this->belongsTo(User::class, 'user_id');
}
And User has one method company():
public function company() {
return $this->hasOne(Company::class, 'user_id');
}
I'm trying to save (so create or update) a user's company like this (in a Controller):
$company = new Company();
$company->name = 'Test';
User::findOrFail(1)->company()->save($company);
First time I run this code it creates the entry in database (OK), but second time it adds a new entry for the same user (Not OK). I thought it will only update the database entry.
Is it a glitch (or something I don't understand in one to one relation) in Laravel or am I doing something wrong? (I think and hope it's the second purpose)
Creating and updating need to treat differently. So check the existence of company attribute first.
$user = User::with('company')->findOrFail(1);
if ($user->company === null)
{
$company = new Company(['name' => 'Test']);
$user->company()->save($company);
}
else
{
$user->company->update(['name' => 'Test']);
}
Note that hasOne() does not guarantee that you will have one-to-one relationship, it just telling Eloquent how to create query. It works even you have multiple Company refer to same User, in such case when you call $user->company you will get first Company in the result data set from database.
$user = User::findOrFail(1);
$company = $user->company ?: new Company;
$company->name = 'Test';
$user->company()->save($company);
I'm trying to save (so create or update) a user's company
You can do exactly that with the updateOrCreate method:
User::findOrFail(1)->company()->updateOrCreate([],['name' => 'xyz']);
The first parameter of updateOrCreate is an empty array, because the companies id is determined by the hasOne relationship $user->company().
And by the way, I would recommend not using an auto-increment id field in a hasOne relationship. If you set user_id as primary in your company table, its technically not possible to create duplicate company rows for one user.

Categories