I'm passing two parameters to my ShopController. one is a lang parameter that is in a route group as a prefix for all routes and the second one is a slug passed through a link.
Here's my controller:
function show($lang, $slug)
{
$product = Product::where('slug', $slug)->first();
return view('shop_show')->with(['product' => $product]);
}
If I pass only one parameter the function takes it as the prefix of the route group, aka the {lang} parameter and returns this error:
Attempt to read property "name" on null. so I have to pass two.
I die and dumped both $lang and $slug parameters and they are showing the correct values. $lang is "en" and $slug is "laptop-1" or any other slug I pass in. however after going through the function, it returns an error:
Missing required parameter for [Route: shopShow] [URI: {lang}/shop/{product}] [Missing parameter: product].
This is the route:
Route::group(['prefix' => '{lang}'], function () {
Route::get('/shop/{product}', [ShopController::class, 'show'])->name('shopShow');
});
this is the URL of the page:
http://127.0.0.1:8000/en/shop/laptop-9
Any ideas?
UPDATE: Here's my shop_show.blade.php view file:
<x-layout :title="$product->name">
<section class="navbar py-2 border-bottom border-2" style="background-color: #eee; font-weight: 500">
<div class="container w-75">
<ul class="breadcrumb">
<li class="breadcrumb-item">
<a class="text-decoration-none" href="{{ route('landingPage', App::getLocale()) }}">Home</a>
</li>
<li class="breadcrumb-item">
<a class="text-decoration-none" href="{{ route('shopIndex', App::getLocale()) }}">Shop</a>
</li>
<li class="breadcrumb-item">
<a class="text-muted text-decoration-none" href="{{ route('shopShow', ['product' => $product->slug, 'lang' => App::getLocale()]) }}">{{$product->name}}</a>
</li>
</ul>
</div>
</section>
<section class="my-5">
<div class="container w-75 d-flex justify-content-between align-items-start">
<div class="w-50">
<div>
<div>
<img id="currentImage" class="active border border-2 rounded-0 p-5 w-75" src='{{ $product->image && file_exists('storage/' . $product->image) ? asset('storage/' . $product->image) : asset('images/not-found.jpg') }}' alt="">
</div>
<div class="product-images">
<div class="product-thumbnails selected">
<img class="w-75" src='{{ $product->image && file_exists('storage/' . $product->image) ? asset('storage/' . $product->image) : asset('images/not-found.jpg') }}' alt="">
</div>
#if ($product->images)
#foreach (json_decode($product->images, true) as $image)
<div class="d-flex align-items-center product-thumbnails">
<img class="w-75" src="{{ file_exists('storage/' . $image) ? asset('storage/' . $image) : asset('images/not-found.jpg') }}" alt="">
</div>
#endforeach
#endif
</div>
</div>
</div>
<div class="card border-0 w-50">
<div>
<h3 class="mb-5">
{{$product->name}}
</h3>
<span class="text-muted" style="font-weight: 500">
{{ $product->details }}
</span>
<div class="h3" style="font-weight: 700">
${{$product->price / 100}}
</div>
<p class="my-3">
{!! $product->description !!}
</p>
<form action="{{ route('cartStore', App::getLocale()) }}" method="POST">
#csrf
<input type="hidden" name="name" value="{{$product->name}}">
<input type="hidden" name="price" value="{{$product->price}}">
<input type="hidden" name="id" value="{{$product->id}}">
<button class="btn py-2 px-3 border border-2 rounded-0 border-secondary" type="submit">Add to Cart</button>
</form>
</div>
</div>
</div>
</section>
#include('partials/might_also_like')
<script>
const currentImage = document.querySelector('#currentImage');
const images = document.querySelectorAll('.product-thumbnails');
images.forEach((element) => element.addEventListener('click', thumbnailClick));
function thumbnailClick(e) {
currentImage.classList.remove('active');
currentImage.addEventListener('transitionend', () => {
currentImage.src = this.querySelector('img').src;
currentImage.classList.add('active');
})
thumbnails.forEach((element) => element.classList.remove('selected'));
this.classList.add('selected');
}
</script>
SOLVED: There was a link in a component within a component within my layout component (3 times nested) that passed only one param, I fixed it by adding another param.
It's always a better idea to do localization before defining your routes so that you notice an error immediately instead of having to spend hours going through all your view files.
Related
I have this issue:
Illuminate\Routing\Exceptions\UrlGenerationException
Missing required parameter for [Route: admin.percent.edit] [URI: {locale}/admin/percent/edit/{id}] [Missing parameter: id]. (View: C:\Users\kawed\OneDrive\Desktop\flooss\resources\views\admin\includes\top.blade.php)
index page code:
#extends('admin.layouts.app')
#section('headSection')
<!-- form Uploads -->
<link href="{{ asset('back/assets/plugins/datatable/dataTables.bootstrap4.min.css') }}" rel="stylesheet" type="text/css" />
#endsection
#section('content')
<div class="page-header mt-0 shadow p-3">
<ol class="breadcrumb mb-sm-0">
<li class="breadcrumb-item">
{{ __('val.home') }}
</li>
<li class="breadcrumb-item active" aria-current="page">
{{ __('val.dashboard_percent') }}
</li>
</ol>
<a href="/{{ app()->getLocale() }}/admin/percent/create">
<button type="button" class="btn btn-success btn-pill mt-1 mb-1">{{ __('val.create_percent') }}</button>
</a>
</div>
<div class="row">
<div class="col-md-12">
<div class="card shadow">
<div class="card-header">
<h2 class="mb-0">Data Table</h2>
</div>
<div class="card-body">
<div class="table-responsive">
<table id="example" class="table table-striped table-bordered w-100 text-nowrap">
<thead>
<tr>
<th class="wd-15p">id</th>
<th class="wd-15p">{{ __('session.percent') }}</th>
<th class="wd-20p">{{ __('session.edit') }}</th>
<th class="wd-15p">{{ __('session.delete') }}</th>
</tr>
</thead>
<tbody>
#foreach($percents as $item)
<tr>
<td>
{{ $item->id }}
</td>
<td>
{{ $item->pname }}
</td>
<td>
{{ __('session.edit') }}
</td>
<td>
{{ __('session.delete') }}
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
#endsection
#section('footerSection')
<!-- file uploads js -->
<script src="{{ asset('back/assets/plugins/datatable/jquery.dataTables.min.js') }}"></script>
<script src="{{ asset('back/assets/plugins/datatable/dataTables.bootstrap4.min.js') }}"></script>
<script>
$(function(e) {
$('#example').DataTable();
var table = $('#example1').DataTable();
$('button').click(function() {
var data = table.$('input, select').serialize();
alert(
"The following data would have been submitted to the server: \n\n" +
data.substr(0, 120) + '...'
);
return false;
});
$('#example2').DataTable({
"scrollY": "200px",
"scrollCollapse": true,
"paging": false
});
});
</script>
#endsection
Edited page code:
#extends('admin.layouts.app')
#section('headSection')
<!-- form Uploads -->
<link href="{{ asset('back/assets/plugins/fileuploads/css/dropify.css') }}" rel="stylesheet" type="text/css" />
#endsection
#section('content')
<div class="page-header mt-0 shadow p-3">
<ol class="breadcrumb mb-sm-0">
<li class="breadcrumb-item">
{{ __('val.home') }}
</li>
<li class="breadcrumb-item active" aria-current="page">
{{ __('val.dashboard_percent') }}
</li>
</ol>
</div>
<div class="row">
<div class="col-md-12">
<form action="{{ route('admin.percent.edit', ['id' => $category->id, 'locale' => app()->getLocale()]) }}" method ="post" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="card shadow">
<div class="card-header">
<h2 class="mb-0">{{ __('val.edit_percent') }}</h2>
#include('admin.includes.messages')
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" name="categoryarabicname" value="{{ $category->categoryarabicname }}">
</div>
<div class="form-group">
<input type="text" class="form-control" name="categoryengname" value="{{ $category->categoryengname }}">
</div>
<div class="form-group">
<textarea class="form-control"name="categoryarabicdesc" id="exampleFormControlTextarea1" rows="3">{{ $category->categoryarabicdesc }}</textarea>
</div>
<div class="form-group">
<textarea class="form-control"name="categoryengdesc" id="exampleFormControlTextarea1" rows="3">{{ $category->categoryengdesc }}</textarea>
</div>
</div>
<div class="col-md-6">
<div class="card shadow">
<div class="card-header">
<h2 class="mb-0">Upload Image</h2>
</div>
<div class="card-body">
<input type="file" name="catimage" class="dropify" data-height="300" />
</div>
<input type="hidden" name="image2" class="form-control" id="exampleInputEmail1">
</div>
<div class="card shadow overflow-hidden">
<img alt="Image placeholder" width=250px height=250px class="big" src="/uploads/{{ $category->categoryimage }}">
</div>
</div>
<div class="col-lg-9"></div>
<div class="col-lg-3">
<button type="submit" class="btn btn-success btn-square mt-1 mb-1">Update</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
#endsection
#section('footerSection')
<!-- file uploads js -->
<script src="{{ asset('back/assets/plugins/fileuploads/js/dropify.min.js') }}"></script>
<script>
$('.dropify').dropify({
messages: {
'default': 'Drag and drop a file here or click',
'replace': 'Drag and drop or click to replace',
'remove': 'Remove',
'error': 'Ooops, something wrong appended.'
},
error: {
'fileSize': 'The file size is too big (2M max).'
}
});
</script>
#endsection
Controller code:
namespace App\Http\Controllers;
use App\Http\Requests\PercentEditRequest;
use App\Http\Requests\PercentRequest;
use App\Models\Percent;
use Illuminate\Http\Request;
class PercentController extends Controller
{
public function index()
{
$percents = Percent::orderBy('created_at', 'desc')->get();
return view('admin.percent.index', compact('percents'));
}
public function create()
{
return view('admin.percent.create');
}
public function store(PercentRequest $request)
{
$validated = $request->validated();
$category = new Percent();
$category->pname = strip_tags($request->pname);
$category->save();
return redirect()->route('admin.percent', ['locale' => app()->getLocale()])
->with('success', trans('session.success'));
}
public function edit(Request $request, $id) {
$id = $request->id;
$locale = $request->locale;
$category = Percent::find($id);
return view('admin/percent/edit', compact('category'));
}
public function update(PercentEditRequest $request, $id) {
$validated = $request->validated();
$category = Percent::find($id);
$category->categoryengname = strip_tags($request->categoryengname);
$category->categoryarabicname = strip_tags($request->categoryarabicname);
$category->categoryengdesc = strip_tags($request->categoryengdesc);
$category->categoryarabicdesc = strip_tags($request->categoryarabicdesc);
if (!empty($request->hasFile('catimage'))) {
$imagePath = $request->file('catimage');
$imageName = time() . '.' . $imagePath->getClientOriginalExtension();
$imagePath->move('uploads', $imageName);
$category->categoryimage= $imageName;
}
$category->save();
return redirect('/admin/percent')->with('success', 'percent Updated Successfuly');
}
public function destroy($id)
{
$category = Percent::find($id);
$category->delete();
return redirect('/admin/percent')->with('success','percent Deleted Successfuly');
}
}
you have 2 parameters in url as define (locale & id)
but in your function have only one id so add locale parameter
public function edit(Request $request, $locale, $id) {
or remove parameter from url and use it from request
I have this application where I am trying to get the the author of a question to be able to mark an answer as the best answer.
I have an AcceptAnswerController created which has been registered in the routes/web.php file as below:
AcceptAnswerController.php
class AcceptAnswerController extends Controller
{
public function __invoke(Answer $answer)
{
$this->authorize('accept', $answer);
$answer->question->acceptBestAnswer($answer);
return back();
}
}
web.php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('questions', 'QuestionsController')->except('show');
Route::resource('questions.answers', 'AnswersController')->only(['store', 'edit', 'update', 'destroy']);
Route::get('questions/{slug}', 'QuestionsController#show')->name('questions.show');
Route::post('answers/{answer}/accept', 'AcceptAnswerController')->name('answers.accept');
In my Answers view, i have the following:
<div class="row mt-4">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<div class="card-title">
<h2>{{ $answersCount . " " . str_plural('Answer', $answersCount) }}</h2>
</div>
<hr>
#include ('layouts._messages')
#foreach ($answers as $answer)
<div class="media">
<div class="d-fex flex-column vote-controls">
<a title="This answer is useful" class="vote-up">
<i class="fas fa-caret-up fa-3x"></i>
</a>
<span class="votes-count">1230</span>
<a title="This answer is not useful" class="vote-down off">
<i class="fas fa-caret-down fa-3x"></i>
</a>
#can ('accept', $answer)
<a title="Mark this answer as best answer"
class="{{ $answer->status }} mt-2"
onclick="event.preventDefault(); document.getElementById('answer-{{ $answer->id }}').submit();"
>
<i class="fas fa-check fa-2x"></i>
</a>
<form id="answer-{{ $answer->id }}" action="{{ route('answers.accept', ['answer' => $answer->id]) }}" method="POST" style="display:none;">
#csrf
</form>
#else
#if ($answer->is_best)
<a title="The question owner accepted this answer as best answer"
class="{{ $answer->status }} mt-2"
>
<i class="fas fa-check fa-2x"></i>
</a>
#endif
#endcan
</div>
<div class="media-body">
{!! $answer->body_html !!}
<div class="row">
<div class="col-4">
<div class="ml-auto">
#can ('update', $answer)
Edit
#endcan
#can ('delete', $answer)
<form class="form-delete" method="post" action="{{ route('questions.answers.destroy', [$question->id, $answer->id]) }}">
#method('DELETE')
#csrf
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('Are you sure?')">Delete</button>
</form>
#endcan
</div>
</div>
<div class="col-4"></div>
<div class="col-4">
<span class="text-muted">Answered {{ $answer->created_date }}</span>
<div class="media mt-2">
<a href="{{ $answer->user->url }}" class="pr-2">
<img src="{{ $answer->user->avatar }}">
</a>
<div class="media-body mt-1">
{{ $answer->user->name }}
</div>
</div>
</div>
</div>
</div>
</div>
<hr>
#endforeach
</div>
</div>
</div>
</div>
Once the author of the question clicks on the check icon, it should mark the answer as the best answer but i get the following error:
Sorry, the page you are looking for could not be found
I see that the answer id is missing in the url as follows:
http://localhost:8000/answers//accept
when it should actually be something like this:
http://localhost:8000/answers/1/accept
I can't seem to figure out why as i passed it as a route parameter in the form action. Same thing happens if a user is trying to edit his answer.
Can I suggest tweaking your strategy a little bit here and bypassing the need for a form submission?
If you swap out the POST for a GET request, this is actually pretty straight forward.
Answers.blade.php
#foreach( $answers as $answer )
#can('accept', $answer)
<a href="answers/{{ $answer->id }}/accept" title="Mark this answer as best answer" class="{{ $answer->status }} mt-2">
<i class="fas fa-check fa-2x"></i>
</a>
#else
<p>Do your thing</p>
#endcan
#endforeach
routes.web.php
Route::get('answers/{answer}/accept', 'AcceptAnswerController');
So, after scrutinizing my code a bit more carefully everything else seemed okay the controller, routes, views. I was able to isolate the problem down to this region
#can ('accept', $answer)
<a title="Mark this answer as best answer"
class="{{ $answer->status }} mt-2"
onclick="event.preventDefault(); document.getElementById('answer-{{ $answer->id }}').submit();"
>
<i class="fas fa-check fa-2x"></i>
</a>
<form id="answer-{{ $answer->id }}" action="{{ route('answers.accept', ['answer' => $answer->id]) }}" method="POST" style="display:none;">
#csrf
</form>
#endcan
I was certian the $answer->id was supposed to return the correct id but i wasn't too sure about the $answer->status so I decided to check its accessor defined in the Answer model.
public function getStatusAttribute()
{
return $this->isBest() ? 'vote-accepted' : '';
}
public function isBest()
{
return $this->id = $this->question->best_answer_id; /** here is the problem **/
}
There the problem was staring right back at me. The isBest method above was supposed to return a boolean value but i was mistakingly assigning. This was the simple fix.
public function isBest()
{
return $this->id === $this->question->best_answer_id; /** here is the problem **/
}
I am trying to create a blog, when trying to bring the previous record and the next record in sight this returns the "post" but not the full path that should be / single / {slug}
CONTROLLER
public function single($slug)
{
$post = Post::where('slug', $slug)->first();
$previous = Post::where('id', '<', $post->id)->orderBy('id', 'asc')->where('status', 'PUBLISHED')->first();
$next = Post::where('id', '>', $post->id)->orderBy('id')->where('status', 'PUBLISHED')->first();
return view('web.single')->with(compact('post', 'previous', 'next'));
}
view
#if (isset($previous))
<div class="alert alert-success">
<a href="{{ url($previous->slug) }}">
<div class="btn-content">
<div class="btn-content-title"><i class="fa fa-arrow-left"></i> Previous Post</div>
<p class="btn-content-subtitle">{{ $previous->title }}</p>
</div>
</a>
</div>
#endif
</div>
<div class="col-md-6">
#if (isset($next))
<div class="alert alert-success">
<a href="{{ url($next->slug) }}">
<div class="btn-content">
<div class="btn-content-title">Next Post <i class="fa fa-arrow-right"></i></div>
<p class="btn-content-subtitle">{{ $next->title }}</p>
</div>
</a>
</div>
#endif
Route
Route::get('/single/{slug}', 'Web\WorkController#single')->name('single');
When clicking on previous or next, the route shown by the browser is http://127.0.0.1:8000/et-autem-tempora
and should be
http://127.0.0.1:8000/single/et-autem-tempora
You are creating your url doing this:
<a href="{{ url($next->slug) }}">
...
</a>
The url('path') helper returns something like this: http://{base_url}/{path}.
Try to use your named route instead:
<a href="{{ route('single', ['slug' => $next->slug]) }}">
...
</a>
I think this should also work:
<a href="{{ route('single', $next->slug) }}">
...
</a>
I am trying to create a blog using Laravel 5.5 but I have received this error.
"Missing required parameters for [Route: posts.show] [URI: posts/{post}]. (View: /home/vagrant/Code/dialhousesetup.test/resources/views/posts/index.blade.php)"
On my postcontroller.php file. I did this so I can output all posts on my database:
public function index()
{
//Create a variable and store all the blog posts in it from the data base
$posts = Post::all();
//Return a view and pass in the above variable
return view('posts.index', array('posts' => $posts));
}
This is the loop I wrote on the /posts page to display all the blog posts.
<div class="events mb-100">
<div class="container">
<div class="row">
#foreach ($posts as $post)
<div class="col-md-6">
<a href="{{ route('posts.show'), $post->id }}">
<div class="single-event text-center">
<img src="http://www.dialhousehotel.com/wp-content/uploads/2018/01/CC_1419-The-Dial-House-website-01-18-04.jpg" alt="" style="border:2px solid #bb9b50;">
<h2>{{$post->title}}</h2>
<p>{{$post->main_body}}</p>
<div class="separator"></div>
<button type="submit" class="button button-simple mt-30">Read More</button>
</div>
</a>
</div>
#endforeach
</div>
</div>
</div>
I honestly don't know what I did wrong.
Update:
People have noticed there was a syntax issue and I have replaced {{ route('posts.show'), $post->id }} with {{ route('posts.show', $post->id) }}
#foreach($posts as $post)
<div class="col-md-6">
<a href="{{ route('posts.show', $post->id) }}">
<div class="single-event text-center">
<img src="http://www.dialhousehotel.com/wp-content/uploads/2018/01/CC_1419-The-Dial-House-website-01-18-04.jpg" alt="" style="border:2px solid #bb9b50;">
<h2>{{$post->title}}</h2>
<p>{{$post->main_body}}</p>
<div class="separator"></div>
<button type="submit" class="button button-simple mt-30">Read More</button>
</div>
</a>
</div>
#endforeach
However, I am now getting an "Invalid argument supplied for foreach() (View: /home/vagrant/Code/dialhousesetup.test/resources/views/posts/index.blade.php)"
<?php $__currentLoopData = $posts; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $post): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div class="col-md-6">
<a href="<?php echo e(route('posts.show', $post->id)); ?>">
<div class="single-event text-center">
<img src="http://www.dialhousehotel.com/wp-content/uploads/2018/01/CC_1419-The-Dial-House-website-01-18-04.jpg" alt="" style="border:2px solid #bb9b50;">
<h2><?php echo e($post->title); ?></h2>
<p><?php echo e($post->main_body); ?></p>
<div class="separator"></div>
<button type="submit" class="button button-simple mt-30">Read More</button>
</div>
</a>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
You're using the wrong syntax. Change it to:
{{ route('posts.show', $post->id) }}
The error is here.
<a href="{{ route('posts.show'), $post->id }}">
It needs the ID to be part of the route. So it would be
<a href="{{ route('posts.show', $post->id) }}">
I have this blade in my view. Right now, I have 6 blocks of them in my view because I'm not sure how to refactor it.
<div class="row filemanager">
<div class="col-sm-12">
#foreach ($devices as $device)
#if( $device->vlan_id == 100 AND $device->device_activity == 'ACTIVE' )
<div class="col-xs-6 col-sm-4 col-md-2 text-center">
<div class="thmb">
<div class="btn-group fm-group" style="display: none;">
<button type="button" class="btn btn-default dropdown-toggle fm-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu fm-menu" role="menu">
<li id="device-menu">
<a class="changeDeviceNameBtn" href="#"><i class="fa fa-pencil"></i> Change Device Name </a>
</li>
</ul>
</div>
<div class="thmb-prev">
<a href="/{{$cpe_mac}}/device/{{$device->device_mac}}">
#if(isset($device->device_name))
{{-- Show base on device name --}}
<img src="/images/photos/devices/{{img($device->device_name)}}.jpg" class="draggable img-responsive" alt="">
#else
{{-- No Device Name Set --}}
#if($device->hostname != '')
{{-- Show base on hostname --}}
<img src="/images/photos/devices/{{img($device->hostname)}}.jpg" class="draggable img-responsive" alt="">
#else
{{-- Show default --}}
<img src="/images/photos/devices/no-img.jpg" class="draggable img-responsive" alt="">
#endif
#endif
</a>
</div>
<h5 class="fm-title device_name">
<a href="/{{$cpe_mac}}/device/{{$device->device_mac}}">
#if($device->hostname == '')
No Devicename
#else
{{ $device->hostname}}
#endif
</a>
</h5>
<h5 class="text-muted device_ip">{{$device->ip_address}}</h5>
<h5 class="text-muted device_mac">{{$device->device_mac}}</h5>
<?php
$status = ucfirst(strtolower($device->device_activity));
if ($status == 'Active'){
$color = '#1CAF9A';
}else{
$color = '#D9534F';
}
?>
<h5>{{ $status }}
<i class="fa fa-circle" style="color:{{$color}}; margin-left: 7px;"></i>
</h5>
</div>
</div>
#endif
#endforeach
</div>
</div>
I want to make a function containing that blade, and only replace my
$device->vlan_id, and my $device->device_activity.
Example,
public static deviceRow(100,ACTIVE){
... my blade ...
}
Now, I just that function 6 times, rather than duplicate that block of code 6 times.
Is it even possible ?
Any hints / suggestions on this will be much appreciated !
You can make a partial with your blade and send a variable as a parameter:
In your parent view do something like this:
#foreach($somelist as $item)
#include('view.partial', ['name' => $item->name])
#endforeach
And in a file called partial.blade.php, do something like this:
{{ $device->$name }}
It's the main idea. Tell me if it helps...
You could create a new view and send some parameters with it while including:
#include('my.view', ['device' => $myDevice, 'activity' => 'ACTIVE'])
The keys of the array will be available as variables in your view.
The variable $myDevice would be available as $device in the view my.view