Question
Why my variable in ProfileController is not loaded in my blade(index2.blade.php)?
Error Message
Undefined variable: plus (View: /work/resources/views/stories/index2.blade.php)
My Codes
routes/web.php
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('login');
Route::match(['get','post','middleweare'=>'auth'], '/',
'StoriesController#index',
'StoriesController#store',
'ProfileController#index',
'ProfileController#store'
);
Route::match(['get','post','middleweare'=>'auth'], 'stories/create',
'StoriesController#add',
'StoriesController#upload'
);
Route::match(['get','post','middleweare'=>'auth'], 'profile/create',
'ProfileController#add',
'ProfileController#upload'
);
Route::group(['middleweare' => 'auth','name'=>'profile'], function () {
Route::get('/profile/edit', 'ProfileController#edit');
});
Route::get('/home', 'HomeController#index')->name('home');
Auth::routes();
app/Http/Controllers/ProfileController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\stories;
use App\History;
use App\Posts;
use Carbon\Carbon;
use Storage;
class ProfileController extends Controller
{
public function index(Request $request)
{
$plus = Posts::all();
return view('stories.index2', compact('plus'));
}
public function upload(Request $request)
{
$this->validate($request, [
'file' => [
'required',
'file',
'image',
'mimes:jpeg,png',
]
]);
if ($request->file('file')->isValid([])) {
$path = $request->file->store('public');
return view('stories.index2')->with('filename', basename($path));
} else {
return redirect()
->back()
->withInput()
->withErrors();
}
}
public function store(Request $request)
{
$d = new \DateTime();
$d->setTimeZone(new \DateTimeZone('Asia/Tokyo'));
$dir = $d->format('Y/m');
$path = sprintf('public/posts/%s', $dir);
$data = $request->except('_token');
foreach ($data['plus'] as $k => $v) {
$filename = '';
$posts = Posts::take(1)->orderBy('id', 'desc')->get();
foreach ($posts as $post) {
$filename = $post->id + 1 . '_' . $v->getClientOriginalName();
}
unset($post);
if ($filename == false) {
$filename = 1 . '_' . $v->getClientOriginalName();
}
$v->storeAs($path, $filename);
$post_data = [
'path' => sprintf('posts/%s/', $dir),
'name' => $filename
];
$a = new Posts();
$a->fill($post_data)->save();
}
unset($k, $v);
return redirect('/');
}
public function create(Request $request)
{
$this->validate($request, Profile::$rules);
$profile = new Profile;
$form = $request->all();
unset($form['_token']);
$profile->fill($form);
$profile->save();
return redirect('/');
}
public function add()
{
return view('profile.create2');
}
public function edit()
{
return view('profile.edit');
}
}
resources/views/stories/index2.blade.php
#extends('layouts.front2')
#section('title','mainpage')
#section('content')
<div class="profile">
<div class="profileimg">
#foreach ($plus as $pplus)
<img src="/storage/{{ $pplus->path . $pplus->name }}" style="height: 210px; width: 210px; border-radius: 50%;">
#endforeach
</div>
<div class="name">
#guest
<a class="nav-link2" href="{{ route('register')}}">{{ __('Create Accout!')}}</a>
#else
<a id="navbarDropdown" class="nav-link2" href="#" role="button">
{{Auth::user()->name}}<span class="caret"></span></a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
#csrf
</form>
</div>
#endguest
<div class="aboutme">
You can write your profile here!You can write your profile here!You can write your profile here!
You can write your profile here!You can write your profile here!You can write your profile here!
You can write your profile here!You can write your profile here!You can write your profile here!
You can write your profile here!You can write your profile here!You can write your profile here!
You can write your profile here!You can write your profile here!You can write your profile here!
</div>
</div>
<div class="new">
<div class="newtitle">
<h1>New</h1>
</div>
<div class="container1">
#foreach ($plus as $pplus)
<img src="/storage/{{ $pplus->path . $pplus->name }}" class="images" style="height: 150px; width: 150px; border-radius: 50%;">
#endforeach
<div class="more">
more...
</div>
</div>
</div>
<div class="stories">
<div class="titlestories">
<h1>Stories</h1>
</div>
<div class="container2">
<div class="titleclose">
<h2>#CloseFriends</h2>
</div>
<div class="titlefollow">
<h2>#Follows</h2>
</div>
</div>
</div>
{{ csrf_field() }}
#endsection
In your upload method, you're missing the $plus variable
Change it to this
public function upload(Request $request)
{
$this->validate($request, [
'file' => [
'required',
'file',
'image',
'mimes:jpeg,png',
]
]);
if ($request->file('file')->isValid([])) {
$path = $request->file->store('public');
$filename = basename($path);
$plus = Posts::all();
return view('stories.index2', compact('filename','plus'));
} else {
return redirect()
->back()
->withInput()
->withErrors();
}
}
return view('stories.index2, [ 'plus' => Posts::all() ]); should work.
Related
I am running Laravel 7 and have a list of tasks (would be posts if it were a blog) and I need to make sure that when the task is deleted, that all subsequent images are deleted in both the database and in the disc. When I click the delete button, the page throws an error: Invalid argument supplied for foreach().
Unfortunately, this is a vague error and can be caused by a variety of causes. My hopes are that someone can take a look at my code and see if I am missing something. I am relatively new to Laravel so tracking down this issue has been more than a challenge. Than you in advance for helping my work out this issue.
In my Task.php model, I have:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Image;
use Illuminate\Support\Facades\Storage;
class Task extends Model
{
protected $fillable = [
'task_name', 'task_priority', 'task_assigned_to', 'task_assigned_by', 'task_description', 'task_to_be_completed_date', 'task_status',
'task_notes'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function image()
{
// return $this->hasMany('App\Image');
return $this->hasMany(Image::class);
}
public static function boot()
{
parent::boot();
self::deleting(function ($task) {
foreach ($task->images as $image) {
$image->delete();
}
});
}
}
In my Image.php model, I have
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use App\Task;
class Image extends Model
{
protected $fillable = [
'task_id',
'name',
];
protected $uploads = '/task-images/';
public function getFileAttribute($image)
{
return $this->uploads . $image;
}
public function task()
{
// return $this->belongsTo('App\Task', 'task_id');
return $this->belongsTo(Task::class);
}
public static function boot()
{
parent::boot();
self::deleting(function ($image) {
Storage::delete(Storage::path($image->name));
});
}
}
In my TasksController.php, (all code in case something is causing a conflict here) here is what I have:
<?php
namespace App\Http\Controllers;
use App\Task;
use App\Image;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class TasksController extends Controller
{
public function index()
{
$tasks = Task::orderBy('created_at', 'desc')->paginate(10);
return view('/tasks')->with('tasks', $tasks);
}
public function create()
{
return view('tasks.create');
}
public function store(Request $request)
{
$this->validate($request, [
'task_name' => 'required',
'task_description' => 'required',
]);
// Create Task
$user = Auth::user();
$task = new Task();
$data = $request->all();
$task->user_id = $user->id;
$task = $user->task()->create($data);
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach ($files as $file) {
$name = time() . '-' . $file->getClientOriginalName();
$name = str_replace(' ', '-', $name);
$file->move('task-images', $name);
$task->image()->create(['name' => $name]);
$images = new Image;
$images->name = $name;
}
}
$task->task_name = $request->input('task_name');
$task->task_description = $request->input('task_description');
$task->task_priority = $request->input('task_priority');
$task->task_assigned_by = $request->input('task_assigned_by');
$task->task_assigned_to = $request->input('task_assigned_to');
$task->task_to_be_completed_date = $request->input('task_to_be_completed_date');
$task->task_notes = $request->input('task_notes');
$task->task_status = $request->task_status;
$task->save();
return redirect('/home')->with('success', 'Task Created');
}
public function edit($id)
{
$task = Task::find($id);
return view('tasks.edit', ['task' => $task]);
}
public function update(Request $request, $id)
{
$this->validate($request, [
'task_name' => 'required',
'task_description' => 'required',
]);
$task = Task::find($id);
$task->task_name = $request->input('task_name');
$task->task_description = $request->input('task_description');
$task->task_priority = $request->input('task_priority');
$task->task_assigned_by = $request->input('task_assigned_by');
$task->task_assigned_to = $request->input('task_assigned_to');
$task->task_to_be_completed_date = $request->input('task_to_be_completed_date');
$task->task_notes = $request->input('task_notes');
$task->task_status = $request->input('task_status');
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach ($files as $file) {
$name = time() . '-' . $file->getClientOriginalName();
$name = str_replace(' ', '-', $name);
$file->move('task-images', $name);
$task->image()->create(['name' => $name]);
}
}
$task->update();
return redirect('/home')->with('success', 'Task Updated');
}
public function show($id)
{
$task = Task::find($id);
return view('tasks.show')->with('task', $task);
}
public function destroy($id)
{
$task = Task::findOrFail($id);
// dd($task);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
}
And in the home page where I am calling the delete function, `home.blade.php`, I have:
#extends('layouts.master')
#section('content')
<div class="custom-container">
<div class="row justify-content-center">
<div class="col-md-12">
#include('layouts.includes.messages')
<div class="card w-100">
<div class="card-header text-white" style="background-color: #605ca8;">
<h3 class="card-title">Tasks</h3>
<div class="card-tools">
<a href="tasks/create" class="btn btn-success">
<i class="fas fa-tasks"></i> Add New Task
</a>
</div>
</div>
<!-- /.card-header -->
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Ongoing Tasks</h3>
<div class="card-tools">
<div class="input-group input-group-sm" style="width: 150px;">
<input type="text" name="table_search" class="form-control float-right" placeholder="Search">
<div class="input-group-append">
<button type="submit" class="btn btn-default"><i class="fas fa-search"></i></button>
</div>
</div>
</div>
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0">
<table class="table table-hover text-nowrap">
<thead>
<tr>
<th>Task</th>
<th>Priority</th>
<th>Assigned To</th>
<th>Test Environment Date</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#if($tasks->count() > 0)
#foreach($tasks as $task)
<tr>
<td>{{ $task->task_name }}</td>
<td>{{ $task->task_priority }}</td>
<td>{{ $task->task_assigned_to }}</td>
<td>{{$task->task_to_be_completed_date }}</td>
<td>{{ $task->task_status }}</td>
<td>
<a href="tasks/{{$task->id}}/edit" class="btn btn-primary btn-sm mr-2">
<i class="fa fa-edit"></i> Edit
</a>
<form action="tasks/{{$task->id}}" method="POST" style="display: inline" class="">
#csrf
#method('DELETE')
<button type="submit" class="btn btn-sm btn-danger ml-1 mr-1">
<i class="fa fa-trash"></i> Delete
</button>
</form>
</td>
</tr>
#endforeach
#else
<p class="ml-4 pt-2">No Tasks Found. Please Add one.</p>
#endif
</tbody>
</table>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
</div>
</div>
{{ $tasks->links() }}
</div>
</div>
#endsection
In my filesystem.php under the config folder, I have(just for storage):
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
// 'root' => public_path('task-images'),
],
If I missed anything or codes, please let me know so I can edit my question. Thank you again in advance for helping me with this issue.
You are trying to access a property named images on your instance of Task but there isn't an attribute named images and there isn't a relationship named images, so null is being returned: $task->images == null. You named your relationship image not images, though images would be more correct since this relationship can return many; plural. Change the name of the relationship to images:
public function images()
{
return $this->hasMany(Image::class);
}
Or reference it by its current name: $task->image
In Laravel 7, I am have a task management app. I can upload tasks (posts if it were a blog) and images. I have a multiple image upload working as expected. When it comes time to delete a task, the task deletes just fine but the images are left in the database and in the disk which is public into a folder called task-images. Being new to Laravel, I am struggling on how to go about this. I tried to change the settings in the filesystem.php (which I will post with the commented out code) but that didn't change the location as I had expected. In the end, I want to be able to delete the multiple images when I delete a post and also click delete on an individual image and delete that from both db and disk. I am using resource controller for all my task routes. I have no idea how to go about this and the tutorials that I have found don't really address my specific issue. Any help would be greatly appreciated. Thank you in advance.
Here is my task controller at TaskController.php
<?php
namespace App\Http\Controllers;
use App\Task;
use App\Image;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
class TasksController extends Controller
{
public function index()
{
$tasks = Task::orderBy('created_at', 'desc')->paginate(10);
return view('/tasks')->with('tasks', $tasks);
}
public function create()
{
return view('tasks.create');
}
public function store(Request $request)
{
$this->validate($request, [
'task_name' => 'required',
'task_description' => 'required',
]);
// Create Task
$user = Auth::user();
$task = new Task();
$data = $request->all();
$task->user_id = $user->id;
$task = $user->task()->create($data);
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach ($files as $file) {
$name = time() . '-' . $file->getClientOriginalName();
$name = str_replace(' ', '-', $name);
$file->move('task-images', $name);
$task->image()->create(['name' => $name]);
$images = new Image;
$images->name = $name;
}
}
$task->task_name = $request->input('task_name');
$task->task_description = $request->input('task_description');
$task->task_priority = $request->input('task_priority');
$task->task_assigned_by = $request->input('task_assigned_by');
$task->task_assigned_to = $request->input('task_assigned_to');
$task->task_to_be_completed_date = $request->input('task_to_be_completed_date');
$task->task_notes = $request->input('task_notes');
$task->task_status = $request->task_status;
$task->save();
return redirect('/home')->with('success', 'Task Created');
}
public function edit($id)
{
$task = Task::find($id);
return view('tasks.edit', ['task' => $task]);
}
public function update(Request $request, $id)
{
$this->validate($request, [
'task_name' => 'required',
'task_description' => 'required',
]);
$task = Task::find($id);
$task->task_name = $request->input('task_name');
$task->task_description = $request->input('task_description');
$task->task_priority = $request->input('task_priority');
$task->task_assigned_by = $request->input('task_assigned_by');
$task->task_assigned_to = $request->input('task_assigned_to');
$task->task_to_be_completed_date = $request->input('task_to_be_completed_date');
$task->task_notes = $request->input('task_notes');
$task->task_status = $request->input('task_status');
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach ($files as $file) {
$name = time() . '-' . $file->getClientOriginalName();
$name = str_replace(' ', '-', $name);
$file->move('task-images', $name);
$task->image()->create(['name' => $name]);
}
}
$task->update();
return redirect('/home')->with('success', 'Task Updated');
}
public function show($id)
{
$task = Task::find($id);
return view('tasks.show')->with('task', $task);
}
public function destroy($id)
{
$task = Task::findOrFail($id);
// $image = '/task-images/' . $task->image;
Storage::delete($task->image);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
}
filesystem.php (just the disks section)
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
// 'root' => public_path('task-images'),
],
...
in my individual show template, show.blade.php complete in case there is a code conflict.
#extends('layouts.master')
#section('content')
<div class="container">
Go Back
<div class="card p-3">
<div class="row">
<div class="col-md-4 col-sm-12">
<h3>Task</h3>
<p>{{ $task->task_name }}</p>
<h3>Assigned On:</h3>
<p>{{ $task->created_at->format('m/d/Y') }}</p>
<h3>Assigned To:</h3>
<p>{{ $task->task_assigned_to }}</p>
</div>
<div class="col-md-4 col-sm-12">
<h3>Task Description</h3>
<p>{{ $task->task_description }}</p>
<h3>Priority</h3>
<p>{{ $task->task_priority }}</p>
<h3>Status</h3>
<p>{{ $task->task_status }}</p>
</div>
<div class="col-md-4 col-sm-12">
<h3>Test Environment Date:</h3>
<p>{{ $task->task_to_be_completed_date }}</p>
<h3>Notes</h3>
<p>{{ $task->task_notes }}</p>
<h3>Action</h3>
<div style="display: inline;">
<a href="/tasks/{{$task->id}}/edit" class="btn btn-sm btn-primary mr-2">
<i class="fa fa-edit"></i> Edit
</a>
</div>
<form style="display: inline;" action="/tasks/{{ $task->id }}" method="POST" class="">
#csrf
#method('DELETE')
<button type="submit" class="btn btn-danger btn-sm ml-1 mr-1">
<i class="fa fa-trash"></i> Delete
</button>
</form>
</div>
<div class="col-md-12">
<h5>Images</h5>
<hr />
<div class="row">
#if($task->image->count()>0)
#for($i=0; $i < count($images = $task->image()->get()); $i++)
<div class="col-lg-4 col-md-6 col-sm-12">
<img class="w-50 mb-2" src="/task-images/{{ $images[$i]['name'] }}" alt="">
<form style="display: inline;" action="/tasks/{{ $task->name }}" method="POST" class="">
#csrf
#method('DELETE')
<button type="submit" class="btn btn-danger btn-sm ml-1 mr-1">
<i class="fa fa-trash"></i> Delete
</button>
</form>
</div>
#endfor
#else
<p>No images found</p>
#endif
</div>
<br />
</div>
</div>
</div>
</div>
<!--Modal Start-->
<div id="lightbox" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog">
<button type="button" class="close hidden" data-dismiss="modal" aria-hidden="true">×</button>
<div class="modal-content">
<div class="modal-body">
<img class="w-100" src="" alt="" />
</div>
</div>
</div>
</div>
<!--Modal End-->
#endsection
#section('scripts')
<script>
$(document).ready(function() {
var $lightbox = $('#lightbox');
$('[data-target="#lightbox"]').on('click', function(event) {
var $img = $(this).find('img'),
src = $img.attr('src'),
alt = $img.attr('alt'),
css = {
'maxWidth': $(window).width() - 100,
'maxHeight': $(window).height() - 100
};
$lightbox.find('.close').addClass('hidden');
$lightbox.find('img').attr('src', src);
$lightbox.find('img').attr('alt', alt);
$lightbox.find('img').css(css);
});
$lightbox.on('shown.bs.modal', function (e) {
var $img = $lightbox.find('img');
$lightbox.find('.modal-dialog').css({'width': $img.width()});
$lightbox.find('.close').removeClass('hidden');
});
});
</script>
#endsection
In my Task model, Task.php, I have:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Image;
class Task extends Model
{
protected $fillable = [
'task_name', 'task_priority', 'task_assigned_to', 'task_assigned_by', 'task_description', 'task_to_be_completed_date', 'task_status',
'task_notes'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function image()
{
// return $this->hasMany('App\Image');
return $this->hasMany(Image::class);
}
}
and finally my Image Model Image.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Task;
class Image extends Model
{
protected $fillable = [
'task_id',
'name',
];
protected $uploads = '/task-images/';
public function getFileAttribute($image)
{
return $this->uploads . $image;
}
public function task()
{
// return $this->belongsTo('App\Task', 'task_id');
return $this->belongsTo(Task::class);
}
}
If I am missing something, please let me know so I can edit my question. Again, thank you in advance for helping me with this issue. I have been scratching my head all week on this one. Cheers.
Edit
After implementing boot functions in my model as suggested below, I received an error that an invalid argument was used for foreach. I ran a dd($task); and the following image shows the result.
Final Edit
The answer below worked for my situation. I did have to edit some things to finalize the resolution:
in Task.php I changed the foreach to the following.
foreach($task->image ?: [] as $image)
I had declared image and not image in my model and that was causing a problem. Adding the ternary operator also helped the code not throw any errors.
In my TasksController.php I changed both the update and create functions with the same ternary operator as follows:
if ($request->hasFile('images')) {
$files = $request->file('images');
foreach ($files ?: [] as $file) {
$name = time() . '-' . $file->getClientOriginalName();
$name = str_replace(' ', '-', $name);
$file->move('task-images', $name);
$task->image()->create(['name' => $name]);
}
}
I hope this helps anyone else having the same issue. Thanks to #GrumpyCrouton and #lagbox for their help in resolving this as well as #user3563950
Without them, I would still by stratching my head for another couple of weeks.
on your App\Image class, implement to boot function with the following;
use Illuminate\Support\Facades\Storage;
public static function boot() {
parent::boot();
self::deleting(function($image) {
Storage::delete(Storage::path($image->name));
});
}
Also implement the boot method in App\Task class
use Illuminate\Support\Facades\Storage;
public static function boot() {
parent::boot();
self::deleting(function($task) {
foreach($task->images as $image) {
$image->delete();
}
});
}
Now on your TaskController implement the destroy method as follows;
public function destroy($id)
{
$task = Task::findOrFail($id);
$task->delete();
return redirect('home')->with('success', 'Task Deleted');
}
As a bonus, learn Laravel model binding to ease the pain of finding an instance using findOrFail()
After I send the variable that contains the comments to the view, I can only display the user id. This is why I need to somehow foreach through all the comments and based on their user_id to add a new key-pair value with username-username and send it to the view afterwards. Unfortunately, I'm having trouble figuring how to do that.
public function specificImage($id){
$similarImages = null;
$image = Image::with('comments.user')->find($id);
$subImages = Image::where('parent_id', $id)->get();
$views = $image->views;
$image->views = $views + 1;
$image->save();
$authorId = $image->user_id;
$author = User::find($authorId);
$comments = Comment::where('image_id', $id)->get();
$recentImages = Image::where('parent_id', NULL)->where('user_id', $authorId)->orderBy('created_at', 'desc')->limit(9)->get();
$tag = Tag::whereHas('images', function($q) use ($id) {
return $q->where('taggable_id', $id);
})->first();
if (!empty($tag)) {
$tagId = $tag->id;
}
if (!empty($tagId)) {
$similarImages = Image::where('parent_id', NULL)->whereHas('tags', function($q) use ($tagId) {
return $q->where('tag_id', $tagId);
})->orderBy('created_at', 'desc')->limit(9)->get();
}
return view('specificImage', ['image' => $image,'subImages' => $subImages, 'recentImages' => $recentImages, 'similarImages' => $similarImages, 'author' => $author, 'comments' => $comments]);
}
Table:
Table: Comments
Columns: id, user_id, image_id, comment
Image model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function tags(){
return $this->morphToMany('App\Tag', 'taggable');
}
public function votes(){
return $this->hasMany('App\Vote');
}
public function comments(){
return $this->hasMany('App\Comment');
}
public function updateVotes()
{
$this->upvotes = Vote::where('image_id', $this->id)->where('vote', true)->count();
$this->downvotes = Vote::where('image_id', $this->id)->where('vote', false)->count();
$this->save();
}
public function updateComments()
{
$this->comments = Comment::where('image_id', $this->id)->count();
$this->save();
}
}
Comment model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function image(){
return $this->belongsTo('App\Image');
}
public function user(){
return $this->belongsTo('App\User');
}
}
User model:
<?php
namespace App;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Authenticatable
{
use \Illuminate\Auth\Authenticatable;
public function images(){
return $this->hasMany('App\Image');
}
public function comments(){
return $this->hasMany('App\Comment');
}
public function votes(){
return $this->hasMany('App\Vote');
}
public function roles(){
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
}
public function hasAnyRole($roles) {
if (is_array($roles)) {
foreach ($roles as $role) {
if ($this->hasRole($role)){
return true;
}
}
} else {
if ($this->hasRole($roles)){
return true;
}
}
return false;
}
public function hasRole($role){
if ($this->roles()->where('name', $role)->first()){
return true;
}
return false;
}
}
Blade
#extends('layouts.app')
#section('content')
<div class="specific-image-flexbox">
<div class="specific-image-column">
<div class='specific-image-container'>
<img class='specific-image' src='{{url("storage/uploads/images/specificImages/".$image->file_name)}}' alt='Random image' />
#foreach($subImages as $subImage)
<img class='specific-image' src='{{url("storage/uploads/images/specificImages/".$subImage->file_name)}}' alt='Random image' />
#endforeach
</div>
</div>
<div class="artwork-info-column">
<div class="artwork-info-container">
<p class='title'>{{ $image->name }}<p>
<p class='author'>на<a href='{{url("profile/".$author->username )}}'><span class='usernameA artwork-info-username-span'>{{$author->username}}</span></a><img class='artwork-info-profile-picture' src='{{url("storage/uploads/profile_pictures/edited/".$author->profile_picture)}}'></p>
#if(Auth::user())
#if(Auth::id() === $image->user_id || Auth::user()->hasRole('Admin'))
<a class='placeholderDelete' href='{{ route('deleteImage', ['image_id' => $image->id]) }}'><i class="far fa-trash-alt"></i> Изтрий изображението</a>
#endif
#endif
<p class='description'>{{ $image->description }}</p>
<p class='description'>Техника: {{ $image->medium }}</p>
<p><i class="far fa-eye"></i> {{ $image->views }} Преглеждания</p>
<p><i class="far fa-thumbs-up"></i> {{ $image->upvotes }} Харесвания</p>
<p class='commentsCount'><i class="far fa-comments"></i> {{ $image->comments }} Коментари</p>
<a class='downloadImage' href="{{url("storage/uploads/images/specificImages/".$image->file_name)}}" download="{{ $image->name }}"><i class="fas fa-file-download"></i> Изтегли</a>
<!--<a class='placeholderDelete fas fa-expand' href='{{url("storage/uploads/images/specificImages/".$image->file_name)}}'></a>-->
<div class='social-container'>
<div class="addthis_inline_share_toolbox"
data-url="{{ url()->full() }}"
data-title="{{ $image->name }} by {{ $author->username }}"
data-description="{{ $image->description }}"
data-media="{{url("storage/uploads/images/specificImages/".$image->file_name)}}">
</div>
</div>
#if(!empty($recentImages))
#if(count($recentImages) >= 9)
<p class='author'>Още произведения на<a href='{{url("profile/".$author->username )}}'><span class='usernameA artwork-info-username-span'>{{$author->username}}</span></a><img class='artwork-info-profile-picture' src='{{url("storage/uploads/profile_pictures/edited/".$author->profile_picture)}}'></p>
<div class="more-images-container">
#foreach($recentImages as $recentImage)
<div class="more-images-container-element">
<a href='{{url("image/".$recentImage->id)}}'>
<img class='more-images' src='{{url("storage/uploads/images/miniImages/".$recentImage->file_name)}}' alt='Random image' />
</a>
</div>
#endforeach
</div>
#endif
#endif
#if(!empty($similarImages))
#if(count($similarImages) >= 9)
<p class='similar-images'>Подобни произведения</p>
<div class="similar-images-container">
#foreach($similarImages as $similarImage)
<div class="similar-images-container-element">
<a href='{{url("image/".$similarImage->id)}}'>
<img class='more-images' src='{{url("storage/uploads/images/miniImages/".$similarImage->file_name)}}' alt='Random image' />
</a>
</div>
#endforeach
</div>
#endif
#endif
#auth
<div class='postComments'>
<form method='POST' action=''>
<textarea class='comment-section' name='comment'></textarea>
<input type="hidden" name="user_id" value="{{ Auth::user()->id }}">
<input type="hidden" name="image_id" value="{{ $image->id }}">
<button class='postComment submit' type='submit' name='commentSubmit'>Изпрати</button>
</form>
</div>
#endauth
<div class='comments'>
#foreach($image->comments as $comment)
{{ $comment->user->username }}
#endforeach
</div>
</div>
</div>
</div>
<script>
var token = '{{ Session::token() }}';
var urlComment = '{{ route('comment') }}';
var urlLike = '{{ route('vote') }}';
</script>
#endsection
I would suggest adding the user relationship to your Comment model as well:
class Comment extends Model
{
public function image()
{
return $this->belongsTo('App\Image');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
You can then eager load the relationships and then access them in your blade file:
public function specificImage($id)
{
$image = Image::with('comments.user')->find($id);
return view('specificImage', ['image' => $image]);
}
Then in your blade file you would have something like:
#foreach($image->comments as $comment)
{{ $comment->user->username }}
#endforeach
I'm trying to add a delete functionality into my project where the user can delete their status but I get the following error :
Screenshot of error
This is my HomeCotroller class:
namespace App\Http\Controllers;
use App\Eloquent\Status;
use App\Friends;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Laracasts\Flash\Flash;
//use Request;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\DB;
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if (Input::has('like_status')) {
$status = Input::get('like_status');
$selectedStatus = Status::find($status);
$selectedStatus->likes()->create([
'user_id' => Auth::user()->id,
'status_id' => $status
]);
return redirect(route('home'));
}
if (Input::has('post_comment')) {
$status = Input::get('post_comment');
$commentBox = Input::get('comment-text');
$selectedStatus = Status::find($status);
$selectedStatus->comments()->create([
'comment_text' => $commentBox,
'user_id' => Auth::user()->id,
'status_id' => $status
]);
Flash::message('Your comment has been posted');
return redirect(route('home'));
}
if (Input::has('status-text')) {
$text = e(Input::get('status-text'));
$rules = [
'status-text' => 'required|string',
];
$vaildator = Validator::make($request->all(), $rules);
if (Input::hasFile('status_image_upload')) {
$file = Input::file('status_image_upload');
$mime = $file->getMimeType();
$image = $request->file('status_image_upload');
$imageName = str_random(8) . '_' . $image->getClientOriginalName();
//$imageFull = str_random(8).'_'.$image->getClientOriginalExtension();
$userStatus = new Status();
$userStatus->status_text = $text;
$userStatus->image_url = $imageName;
$userStatus->type = 1;
$userStatus->user_id = Auth::user()->id;
if ($mime == "video/x-flv" || $mime == "video/mp4" || $mime == "application/x-mpegURL" || $mime == "video/MP2T" || $mime == "video/3gpp" || $mime == "video/quicktime" || $mime == "video/x-msvideo" || $mime == "video/x-ms-wmv") {//process upload}
$vaildator = Validator::make($request->all(), $rules);
if (!$vaildator->fails()) {
$image->move('status_videos', $imageName);
$userStatus->type = 2;
$userStatus->save();
Flash::success('Your status has been posted');
return redirect(route('home'));
} else {
return back()->with('error', 'Validation failed:' . $vaildator->errors);
}
} else {
$rules['status_image_upload'] = 'image';
$vaildator = Validator::make($request->all(), $rules);
if (!$vaildator->fails()) {
$image->move('status_images', $imageName);
$userStatus->type = 1;
$userStatus->save();
Flash::success('Your status has been posted');
return redirect(route('home'));
} else {
return back()->with('error', 'Validation failed:' . $vaildator->errors);
}
}
} else {
}
if (!$vaildator->fails()) {
$userStatus = new Status();
$userStatus->status_text = $text;
$userStatus->user_id = Auth::user()->id;
$userStatus->save();
Flash::success('Your status has been posted');
return redirect(route('home'));
} else {
return back()->with('error', 'Validation failed:' . $vaildator->errors);
}
}
//Get top 15 post
$user_id = Auth::id();
$all_friends = Friends::where(['friend_id' => $user_id, 'status' => 1])
->orWhere(['user_id' => $user_id, 'status' => 1])
->get();
$friends = [];
foreach ($all_friends as $val) {
array_push($friends, $val->user_id, $val->friend_id);
}
$unique_friends = array_unique($friends);
if (!empty($unique_friends)) {
$top_15_posts = Status::whereIn('user_id', $unique_friends)
->orderBy('id', 'DESC')
->take(15)
->get();
} else {
$top_15_posts = Status::where('user_id', $user_id)
->orderBy('id', 'DESC')
->take(15)
->get();
}
//Get available friend request
$user_id = Auth::id();
$available_req_count = Friends::where(['friend_id' => $user_id, 'status' => 0])
->orderBy('id', 'desc')
->get()
->count();
return view('home', [
'top_15_posts' => $top_15_posts,
'available_req_count' => $available_req_count
]);
}
public function destroy($status_id)
{
$status =Status::where('id',$status_id)->first();
$status->delete();
return redirect()->route('home')->with(['message' => 'Successfully deleted!']);
}
}
This is user-status-layout.blade
<div class="panel panel-default">
<div class="panel-heading">{{$user->name}} - {{$status->created_at->diffForHumans()}} </div>
<div class="panel-body">
<div class="row">
<div class="col-md-1">
<img src="{{$user->getAvatar()}}" class="img-responsive">
</div>
<div class="col-md-11">
<p>{{$status->status_text}}</p>
#if($status->type == 1)
<img src="{{asset('status_images/'.$status->image_url)}}" class="img-responsive" style="width: 100%;">
#endif
</div>
<div class="col-md-12">
<hr>
<ul class="list-unstyled list-inline">
<li>
<button class="btn btn-xs btn-info" type="button" data-toggle="collapse" data-target="#view-comments-{{$status->id}}" aria-expanded="false" aria-controls="view-comments-{{$status->id}}">
<i class="fa fa-comments-o"></i>View & Comment</button>
</li>
<li>
#if(\App\Eloquent\StatusLikes::where(['status_id'=>$status->id,'user_id'=>Auth::user()->id])->first())
#else
{!! Form::open() !!}
{!! Form::hidden('like_status',$status->id)!!}
<button type="submit" class="btn btn-info btn-xs">
<i class="fa fa-thumbs-up"></i>Like status
</button>
{!! Form::close ()!!}
</li>
<button type="submit" class="btn btn-danger">
Delete
</button>
#endif
<li>
{{$comment_count}} comments
</li>
<li>
{{$like_count}} likes
</li>
</ul>
</div>
</div>
<div class="panel-footer clearfix">
{!! Form::open() !!}
{!! Form::hidden('post_comment',$status->id) !!}
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="comment-text" id="comment-text" placeholder="Post a comment...">
<span class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="fa fa-send"></i>Add</button>
</span>
</div>
</div>
{!! Form::close() !!}
<div class="collapse" id="view-comments-{{$status->id}}">
#if($comments->first())
#foreach($comments as $comment)
<div class="row">
<div class="col-md-1">
<img src="{{\App\Eloquent\User::find($comment->user_id)->getAvatar()}}" class="img-responsive">
</div>
<div class="col-md-11">
<ul class="list-inline list-unstyled">
<li>
{{\App\Eloquent\User::find($comment->user_id)->name}}
</li>
<li>
posted {{$comment->created_at->diffForHumans()}}
</li>
</ul>
<p> {{$comment->comment_text}}</p>
</div>
</div>
<hr>
#endforeach
#else
<p>This status contains no comments.</p>
#endif
</div>
</div>
</div>
</div>
web.php:
<?php
//use Illuminate\Http\Request;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::get('/test', function () {
return Auth::user()->test();
});
Auth::routes();
Route::any('/home', 'HomeController#index')->name('home');
Route::group(['as' => 'user.'], function () {
Route::get('/front', function () {
return view('front');
});
Route::get('/settings', ['as' => 'settings', 'uses' => 'ProfileController#viewSettings']);
Route::post('/settings', ['as' => 'settings', 'uses' => 'ProfileController#saveSettings']);
Route::any('/profile/{userId}', ['as' => 'profile', 'uses' => 'ProfileController#viewProfile']);
Route::get('/search/{query?}', ['as' => 'search', 'uses' => 'SearchController#search']);
Route::get('users', function () {
return User::find(1)->toJson();
});
Route::get('/chat', function () {
return view('chat');
});
Route::get('/calendar', function () {
return view('calendar');
});
Route::resource('events', 'EventsController', ['only' => ['index', 'store', 'update', 'destroy']]);
//Friends route
Route::post('/friends/request', ['as' => 'friends', 'uses' => 'FriendsController#sendRequest']);
Route::get('/friends/viewReq', ['as' => 'friends', 'uses' => 'FriendsController#viewFriendReq']);
Route::post('/friends/reqAction', ['as' => 'friends', 'uses' => 'FriendsController#requestAction']);
// Route::get('/status-delete/{status_id}',['uses' => 'HomeController#getDeleteStatus', 'as'=> 'user.status.delete',
// 'middleware' =>'auth'
// ]);
});
Also this what I get from php artisan route:list
Screenshot of routes
If you look at the name column in the route list, you'll see it is named user.status.delete not status.delete. This must mean your route group must have 'as' => 'user.' set which is going to prefix all routes in that group with user..
My route:
Route::get('/user/{username}', [
'uses' => '\MostWanted\Http\Controllers\ProfileController#getProfile',
'as' => 'profile.index',
]);`
My Controller:
use MostWanted\Models\User;
use Illuminate\Http\Request;
class ProfileController extends Controller{
public function getProfile($username){
$user = User::where('username', $username)->first();
if (!$user) {
abort(404);
}
return view('profile.index')
->with('user', $user);
}
}
The username field in the database exists and is filled in. When I go into search, the users pop up but the URL always misses out on the {username}. When I manually enter the {username} e.g. mostwanted.dev:8000/user/yes.man, it functions normally.
EDIT: This is the view that is hooked to (userblock.blade.php)
<div class="media">
<a class="pull-left" href="{{ route('profile.index', ['username' => $user->username]) }}">
<img class="media-object" alt="{{ $user->getNameOrUsername() }}" src="">
</a>
<div class="media-body">
<h4 class="media-heading">
{{ $user->getNameOrUsername() }}
</h4>
#if ($user->location)
<p>{{ $user->location }}</p>
#endif
</div>
Here is the User.php:
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $table = 'users';
protected $fillable = [
'username',
'first_name',
'last_name',
'email',
'password',
'location',
'gender',
'date_of_birth',
];
protected $hidden = [
'password',
'remember_token',
];
public function getName()
{
if ($this->first_name && $this->last_name) {
return "{$this->first_name} {$this->last_name}";
}
if ($this->first_name) {
return $this->first_name;
}
return null;
}
public function getUsername()
{
if ($this->first_name && $this->last_name) {
return "{$this->first_name}.{$this->last_name}";
}
if ($this->first_name) {
return $this->first_name;
}
return null;
}
public function getNameOrUsername()
{
return $this->getName() ?: $this->username;
}
public function getUsernameOrName()
{
return $this->getUsername() ?: $this->username;
}
public function getFirstNameOrUsername()
{
return $this->first_name ?: $this->username;
}
}
EDIT**: Search results view:
#extends('templates.default')
#section('content')
<h3>Your search for "{{ Request::input('query') }}"</h3>
#if (!$users->count())
<p>No results found.</p>
#else
<div class="row">
<div class="col-lg-12" style="padding: 50px;">
#foreach ($users as $user)
#include('user/partials/userblock')
#endforeach
</div>
</div>
#endif
#stop
SearchController:
use DB;
use MostWanted\Models\User;
use Illuminate\Http\Request;
class SearchController extends Controller
{
public function getResults(Request $request)
{
$query = $request->input('query');
if (!$query) {
return redirect()->route('home');
}
$users = User::where(DB::raw("CONCAT(first_name, ' ', last_name)"),
'LIKE', "%{$query}%")
->orWhere('username', 'LIKE', "%{query}%")
->get();
return view('search.results')->with('users', $users);
}
}
EDIT***:
ProfileController:
use MostWanted\Models\User;
use Illuminate\Http\Request;
class ProfileController extends Controller
{
public function getProfile($username)
{
$user = User::where('username', $username)->first();
if (!$user) {
abort(404);
}
return view('profile.index')
->with('user', $user);
}
}
Try to modify userblock.blade.php
<div class="media">
<a class="pull-left" href="{{ url('user/'.$user->username) }}">
<img class="media-object" alt="{{ $user->getNameOrUsername() }}" src="">
</a>
<div class="media-body">
<h4 class="media-heading">
{{ $user->getNameOrUsername() }}
</h4>
#if ($user->location)
<p>{{ $user->location }}</p>
#endif
</div>