How to delete user without posts in Laravel? - php

I'm working on L5.5 and I need to delete user but not his/her posts. So I basically need to assign his/her posts to another user which has to be Non-removable.
What I need:
Create a user which can't be deleted at least not from front-end even by owner of website but can be edited. (mostly is like bot for this application)
If I delete a user and that user had post(s) those post(s) remain and assign to this user (bot). It means this bot will become author of those posts.
Check for number 2 that only if user with post that happens if user has no post just delete him/her.
This is my usecontroller destroy method currently:
public function destroy($id)
{
$user = User::findOrFail($id);
Storage::delete($user->image);
$user->delete();
return redirect()->route('users.index')->with('flash_message', 'User successfully deleted');
}
Thanks.

According to your needs, you will require softDeletes in your User model and their respective tables in the database, now this solves your 1st problem where your not deleting the user from table simply adding deleted_at column.
Edit: As you are using Zizaco\Entrust\Traits\EntrustUserTrait you need to have your user model look something like this:
class User extends Model implements AuthenticatableInterface
{
use Authenticatable;
use EntrustUserTrait { restore as private restoreA; }
use SoftDeletes { restore as private restoreB; }
public function restore()
{
$this->restoreA();
$this->restoreB();
}
}
For more information about this error you need to look: https://github.com/Zizaco/entrust/issues/742
so now coming to the 2nd point, retrieving the post with deleted model can be used withTrashed() something like:
$user = User::withTrashed()->all();
$user = User::withTrashed()->where('id', 1);
$posts = $user->posts()->get();
// Or do your relational things
Even if you want to assign it to different user then you need to create a new user and apply update methods to all the relational model while deleting the user which seems a bad idea.
Edit:
So in this case you can have:
$oldUser = User::find($id);
$user = User::find($botID); // Find the bot user
$oldFoods = $oldUser->food()->get();
foreach($oldFoods as $food)
{
$food->user_id = $user->id;
$food->save();
}
Now for your 3rd point if the user has no post then you can do a small check something like this:
$user = User::find($request->id);
$posts = $user->posts()->get()->first();
if(isset($posts))
{
$user->delete();
}
else
{
$user->forceDelete();
}
Hope this justifies all your needs.
Conclusion So fnally you can have your destroy method in userController as:
public function destroy($id)
{
$user = User::findOrFail($id);
$foods = $user->food()->get();
if(isset($foods))
{
$botUser = User::where('username', '=', 'bot'); // Find the bot user
foreach($foods as $food)
{
$food->user_id = $botUser->id;
$food->save();
}
$user->delete();
}
else
{
$user->forceDelete();
}
Storage::delete($user->image);
return redirect()->route('users.index')->with('flash_message', 'User successfully deleted');
}

Edit your database with
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('restrict')
->onUpdate('restrict');

Related

Laravel incrementing the db value by 2 times

This is function that is returning the view
// show individual post
public function showPost($id){
$targetPost = Post::findorFail($id);
$targetPost->increment('post_view_count');
$post = [
'post' => $targetPost,
'related_posts' => Post::all()->sortByDesc("id")->take(2)// load some related posts too
];
return view('post_single', $post);
}
What I am wanting here is to update the value by 1 when someone visits the page, the posts are in a list view to some other page, user are supposed to click that link.
Everything is working, but instead of incrementing the value by 1, it is incrementing by 2 even if I hit the reload button.
What I can assume is that the page is requested twice or loading via some kinda middleware first. That's why the request is being sent twice. How do I fix this?
Such a basic counter will not suit your needs. What you can do is create a migration for your Post Views:
Schema::create("post_views", function(Blueprint $table)
{
$table->unsignedInteger("id");
$table->unsignedInteger("id_post");
$table->string("session_id");
$table->string("user_id");
$table->string("ip");
$table->string("agent");
$table->timestamps();
});
Next create a model that will handle the views for you
class PostsViews extends \Eloquent {
protected $table = 'posts_views';
public static function createViewLog($post) {
$postsViews= new PostsViews();
$postsViews->id_post = $post->id;
$postsViews->titleslug = $post->titleslug;
$postsViews->url = \Request::url();
$postsViews->session_id = \Request::getSession()->getId();
$postsViews->user_id = \Auth::user()->id;
$postsViews->ip = \Request::getClientIp();
$postsViews->agent = \Request::header('User-Agent');
$postsViews->save();
}
Now use this in your showPost function():
public function showPost($id){
$targetPost = Post::findorFail($id);
PostsViews::createViewLog($targetPost);
$post = [
'post' => $targetPost,
'related_posts' => Post::all()->sortByDesc("id")->take(2)
];
return view('post_single', $post);
}
Now it will log all views but you can filter it out when you need it on User agent, IP address or session. You can also use that kind of filter when logging a view to just log 1 view per post per viewer.

Get and updating JSON arrays

In a Laravel application, I store details about a user in another table called profiles and I decided it would be a good idea to store one column as a simple JSON array.
This column is called socialProfiles
Here is my index method of ProfilesController
public function index()
{
$user = auth()->user();
if($user)
{
$profile = $user->profile;
if(!$profile)
{
// Define the social profiles array
$socialProfiles = [
'Facebook' => '',
'Twitter' => ''
];
$profile = new Profile();
$profile->user_username = $user->username;
$profile->mangedByUsername = $user->managedByUsername;
$profile->socialProfiles = json_encode($socialProfiles);
$profile->save();
}
$socialProfiles = json_decode($user->profile->socialProfiles, true);
return view('editable.people.profile', compact('user', 'socialProfiles'));
}
}
I set default values of nothing for both Facebook and Twitter and encode them as a JSON string, I then return the user and the profiles to the view.
In the view I have individual forms (within modals) that update different parts of a user profile, and they all go to the same method, because of this, my update function looks like this:
public function update(Request $request)
{
// TODO: Add validation before updating or adding the profile
$this->validate(request(), [
'background' => 'min:1',
'skills' => 'min:1',
]);
$user = auth()->user();
if($user)
{
// Only proceed if there is a logged in user
$profile = $user->profile;
// If there is no profile, create one for this user as they'll need one.
if (!empty(request()->get('background')))
{
$profile->background = $request->get('background');
}
if (!empty(request()->get('skills')))
{
$profile->skills = $request->get('skills');
}
if (!empty(request()->get('filepath')))
{
$profile->displayPicture = $request->get('filepath');
}
$profile->user_username = $user->username;
$profile->save();
return redirect()->back()->withSuccess('Your profile has been successfully updated');;
}
}
If I'm going to be updating the social profile JSON array would i need to recreate the array, encode it and then save it?
The reason for the separate modals is because the design looks like this:
Should I have many separate update methods?
What is your DBMS system, are you using Postgres JSON column?
If you are saving it like this $profile->socialProfiles = json_encode($socialProfiles);
You are saving it as JSON, which is fine. But if you need to update it, you have two choices, modify the original JSON column with some additions, or a create a new column socialProfileUpdates create a new JSON entry on this with the updated profile links. I won't recommend modifying the original JSON entry each time the user updates the record because this way your system would be really buggy.

Is it possible to load a view that requires a user id, without determining it in the URI in Laravel 5.1

I'm continuing my adventure with Laravel 5.1. I have a small project I'm working on and I'm looking to find a nice way to load a User's gecko ideally without having the user id in the URI.
This is my current URI which works as it is:
Route::get('gecko/{user_id}/{name}', 'GeckoController#show');
As you can see i'm holding the user id in the URI and then i'm querying it to find the right gecko. As shown below:
public function show($user_id, $name)
{
$name = str_replace('-', ' ', $name);
$gecko = Gecko::where(compact('user_id', 'name'))->first();
return view('gecko.show', compact('gecko'));
}
So to get this to work, I would do project.dev/gecko/1/Zilly - It works, but having the User ID in there kind of sucks. I decided that having the User ID was important in case there were multiple users who have geckos with the same name.
Any help on this is greatly appreciated, and if you need any extra code let me know :)
Andy
If you would like to use username instead of user_id:
Routes:
Route::get('gecko/{username}/{geckoname}', 'GeckoController#show');
Controller:
public function show($username, $geckoname) {
$user_id = User::where('username', $username)->first()->id;
$geckoname = str_replace('-', ' ', $geckoname);
$gecko = Gecko::where(compact('user_id', 'geckoname'))->first();
return view('gecko.show', compact('gecko'));
}
If the user authenticated you can use Auth::user()->id and you should add only the gecko id.
For example:
Routes:
Route::get('gecko/{gecko_id}', 'GeckoController#show');
Controller:
public function show($id) {
$gecko = Gecko::find($id)->where('user_id', Auth::user()->id)->first();
return view('gecko.show', compact('gecko'));
}
If you would like to use geckoname:
Routes:
Route::get('gecko/{geckoname}', 'GeckoController#show');
Controller:
public function show($geckoname) {
$gecko_id= Gecko::where('geckoname',$geckoname)->first()->id;
$gecko = Gecko::find($gecko_id)->where('user_id', Auth::user()->id)->first();
return view('gecko.show', compact('gecko'));
}

Laravel Eloquent validation insert exception?

I've created a form which adds a category of product in a Categories table (for example Sugar Products or Beer), and each user has their own category names.
The Categories table has the columns id, category_name, userId, created_At, updated_At.
I've made the validation and every thing is okay. But now I want every user to have a unique category_name. I've created this in phpMyAdmin and made a unique index on (category_name and userId).
So my question is this: when completing the form and let us say that you forgot and enter a category twice... this category exist in the database, and eloquent throws me an error. I want just like in the validation when there is error to redirect me to in my case /dash/warehouse and says dude you are trying to enter one category twice ... please consider it again ... or whatever. I am new in laravel and php, sorry for my language but is important to me to know why is this happens and how i solve this. Look at my controller if you need something more i will give it to you.
class ErpController extends Controller{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('pages.erp.dash');
}
public function getWarehouse()
{
$welcome = Auth::user()->fName . ' ' . Auth::user()->lName;
$groups = Group::where('userId',Auth::user()->id)->get();
return view('pages.erp.warehouse', compact('welcome','groups'));
}
public function postWarehouse(Request $request)
{
$input = \Input::all();
$rules = array(
'masterCategory' => 'required|min:3|max:80'
);
$v = \Validator::make($input, $rules);
if ($v->passes()) {
$group = new Group;
$group->group = $input['masterCategory'];
$group->userId = Auth::user()->id;
$group->save();
return redirect('dash/warehouse');
} else {
return redirect('dash/warehouse')->withInput()->withErrors($v);
}
}
}
You can make a rule like this:
$rules = array(
'category_name' => 'unique:categories,category_name'
);

How to implement user permissions in Laravel 4?

What I basically want is user permissions.
I've got an table called 'accounts' in my database. There is a column called 'group_id'.
I want to set it when the 'group_id' = 3, then the user is admin. Then he can view special sites, buttons, and things like that. I've tried to implement something like that:
public function ($roleName) {
$role = $this->roles;
if ($role->name == $roleName) {
return true;
}
return false;
}
Also, I don't know what and how the model is needed, do I need an new one and things like that.
Old post, but maybe someone will find this useful
Add a method to your User model that returns true if the user is an admin. In our case here, it's simply "is our group_id equal to 3?"
// models/User.php
class User extends Eloquent
{
...
public function isAdmin()
{
return $this->group_id == 3;
}
}
Next add a filter that can be used to protect routes
// filters.php
Route::filter('admin', function($route, $request)
{
if ( ! Auth::user()->isAdmin())
{
return App::abort(401, 'You are not authorized.');
}
});
Finally use the filter to protect a group of routes. I this simplified case, only an admin user could access /admin
// routes.php
Route::group(array('before' => array('auth|admin')), function()
{
Route::get('/admin', function()
{
return Response::make("You're an admin!");
}
});
Based on this post:
http://laravelsnippets.com/snippets/admin-route-filter
I suggest Authority for Laravel 4
I personally use Verify package for user management.

Categories