Why can't I change the name of my edit function? - php

I have some posts on my index page, and each post has an edit button on it.
The problem is, I want the URL to be hungarian, but every time I change the function's name from edit to sth. else it gives me 404 error.
I show the posts with the following code:
#foreach($posts as $post)
<div class="card p-3">
<h3>{{$post->title}}</h3>
<small>Feltöltve: {{$post->created_at}}</small>
<h3>Szerkesztés</h3> I TRY TO CHANGE /EDIT TO STH. ELSE HERE
</div>
#endforeach
And here is my posts controller with the edit function:
public function edit($id) { I change edit here as well
$post = Post::find($id);
return view('elado.szerkeszt')->with('post', $post);
}
In web.php, I've
Route::resource('elado', 'PostsController');

Because you're using resource() method in your route declaration. Which will use by default there routes and control methods
[
'create',
'store',
'show',
'edit',
'update',
'destroy',
]
If you want to change the method name, declare the route on your own
Route::post('/change', 'PostsController#change');

you can exclude edit method from resource routes with except method like, then define new route with your custom edit method and put before resources routes:
Route::post('/elado/{id}', 'PostsController#sth');
Route::resource('elado', 'PostsController')->except([
'edit'
]);

Related

How to render a single post inside a section, from a function in the controller

I'm developing a personal blog but I can't get the browser to show me what I have in a function which has yet to show me a single post, however I can manage to view a list of all the posts, I can view just 5 (latest) which appear on the main, homepage.
Now I'm going for the part where you click on the title and everything about this post should be displayed. I inspected the code on the part where I'm having the issues and the part where the foreach is isn't being rendered to the browser, maybe I'm not doing something correct on the blade part?
PostsController.php
public function show(Post $slug)
{
$post = Post::find($slug);
return view('posts.show', ['posts' => $post]);
}
Posts/show.blade.php
#extends('layouts.app')
#section('showpost')
<div>
#foreach ($posts as $post)
<h1> {{ $post->title }} </h1>
<p> {{ $post->body }} </p>
#endforeach
</div>
#endsection
web.php
Route::get('/posts/{post}', 'PostsController#show');
Just to show you how I'm referencing the template that shows just one post.
#foreach ($posts as $post)
<li>
<a href="/posts/{{ $post->slug }}">
<h1> {{ $post->title }} </h1>
</a>
<p> {{ $post->slug }} </p>
</li>
#endforeach
Post::find is used to retrieve a model by its primary key which is in most cases named id. Heir in your case you are passing $slug as an argument, and as It's is supposed to render only a single item with a given slug you should use Post::where('slug', $slug)->first() this will only return one item and you won't have to use a foreach loop in the show.blade.php template.
Another problem is here
public function show(Post $slug) {
$post = Post::find($slug);
return view('posts.show', ['posts' => $post]);
}
You are using Route Model Binding which will automatically set the parameter $slug of the function show equal to the record in the posts table which has the id which is passed in the URL request. No need to perform Post::find($slug)
for example, if the request URL is http://localhost:8000/posts/1 here the id is 1 so the parameter $slug will be populated with the record which has id==1 unless you have Customizing The Key like this
Define in the App\Models\Post::class a method call
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug';
}
With this definition, the post item which will be retrieved when performing Route model biding will be based on the value of the slug column within a posts table.
You can learn more about at Route Model Biding
In order to implement the Route Model Binding completely, you need to specify it in 3 places, routes.php, PostsController.php and override it on the model, Post.php:
Pass the desired target inside the get request method and place it inside the wildcard, this is next to where you specify the controller and which function to use inside of the controller.
From this: Route::get('/posts/{post}', 'PostsController#show');
To this: Route::get('/posts/{slug}', 'PostsController#show');
Override the target (from id to "whatever") using the getRouteKeyModel function, this is just like #Yves Kipondo had provided
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug';
}
Tweak the show function inside the PostsController, passing the Model's name and the target so the query is completed. All of this inside the parameter of the function. And since your'e overriding the use of the id, you no longer have to specify it inside Eloquent query to the database.
So, instead of this:
public function show(Post $slug)
{
$post = Post::find($slug);
return view('posts.show', ['posts' => $post]);
}
Change it to this:
public function show(Post $slug)
{
return view('posts.show', ['post' => $slug]);
}

how can I access to another column in blade

I have the id in a blade and I want to access to another column.
I have $article->country_id which gives access to the id of the foreign key country.
How can I find the record using id and then get access to country->name.
I have done the things below but it doesn't work as I have explained.
Here is the blade
#foreach($articles as $article)
<div class="col-md-12">
کشور:<h4 class ="post-title">{{route('article.whichCountry',$article->country_id)}}</h4>
</div>
#endforeach
here is web.php
Route::get('article/whichCountry/{country}',[
'uses' => 'ArticleController#whichCountry',
'as' => 'article.whichCountry'
]);
and here is whichCountry in ArticleController
public function whichCountry($id){
$country = country::where('id',$id)->first();
return $country->name;
}
The point is that it doesn't call the function whichCountry
and prints:
http://127.0.0.1:8000/article/whichCountry/10
Thank you very much for your response in advance!
Your route access needs to be like below, giving value for {country} parameter.
{{ route('article.whichCountry',['country' => $article->country_id]) }}
Second, instead of where in your controller method, if Id is the primary key, you can just do:
Country::find($country);
Also, change your function definition like below for the parameter value filling
public function whichCountry($country){
This is very simple to implement this. First check your Controller is getting the id properly. Then use find method
Your route should be like this
{{route('article.whichCountry',['id'=>$article->country_id])}}
And in your controller you have to use like this
public function whichCountry($id){
$country = country::where('id',$id)->first();
return $country->name;
}
In your web.php looks like this
Route::get('article/whichCountry/{id}',[
'uses' => 'ArticleController#whichCountry',
'as' => 'article.whichCountry'
]);

Delete data from the database with Laravel 5.4

I am sort of new to the Laravel framework and I am building just a simple blog. I can create a blog, show a blog and show a overview of all blogs. Now I would like to delete a blog. So, I have created a delete button in my view with a route link which will pass also the id of the article. Then, in my routes file I specify a delete request and a controller method. In the method I find the id and try to delete the row with the id I specified in the route/view.
This doesn't work. Instead of activate the destroy/delete method it shows the article instead of deleting it and activates the show method instead of the delete method. Can somebody help me out, What do I wrong?
View.blade.php
<a href="{{route('nieuws.destroy', ['id' => $blog->id])}}" onclick="return confirm('Weet je dit zeker?')">
<i class="fa fa-trash"></i>
</a>
Route
Route::group(['middleware' => 'auth'], function () {
Route::get('/aanvragen', 'aanvragenController#index')->name('aanvragen.index');
Route::get('/logout' , 'Auth\LoginController#logout')->name('logout');
Route::get('/nieuws/toevoegen', 'blogController#create')->name('blogs.add');
Route::post('/nieuws/store', 'blogController#store')->name('nieuws.store');
Route::delete('/nieuws/{id}', 'blogController#destroy')->name('nieuws.destroy');
});
Route::get('/nieuws', 'blogController#index')->name('blogs.index');
Route::get('/nieuws/{blog}', 'blogController#show')->name('blogs.show');
Controller methods
Delete/Destroy
public function destroy($id) {
$blog = Blog::find($id);
$blog->delete();
return redirect('/nieuws');
}
Show
public function show(Blog $blog) {
dd('show');
return view('blogs.show', compact('blog'));
}
A delete() route requires you to POST your data.
HTML forms only supports GET and POST, other methods like DELETE, PUT, etc are not supported, that's why Laravel uses the _method to spoof methods which are not supported by HTML forms.
You do not want use GET in these cases, since someone can send a user the url (http://yoursite.com/blog/delete/1) in an IM or via email. The user clicks and the blog is gone.
Define your route as it would be when using resource controllers, so:
Route::delete('/nieuws/{id}', 'blogController#destroy')->name('nieuws.destroy');
And either use a form with the delete method:
// apply some inline form styles
<form method="POST" action="{{ route('nieuws.destroy', [$blog->id]) }}">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button type="submit">Delete</button>
</form>
Or do some javascript magic as the link SR_ posted in his comment on your OP.
One more thing, add some sort of validation in your destroy action. Right now when you provide a non-existing id or something else, you will get a 500 error, instead you want to have a 404.
public function destroy($id)
{
$blog = Blog::findOrFail($id);
$blog->delete();
return redirect('/nieuws');
}
I think you need to update your destroy function like:
public function destroy($id) {
$blog = DB::table('blog')->where('id',$id)->delete();
return redirect('/nieuws');
}
And update your view code like:
<a href="{{route('nieuws.destroy', [$blog->id])}}" onclick="return confirm('Weet je dit zeker?')">
<i class="fa fa-trash"></i>
</a>
Hope this work for you!
I'm also new to Laravel but I made it work through this way:
(I use 'Article' as the model's name and the resource "method" in the route stands for a bunch of useful routes including the route you wrote)
Controller:
public function destroy($id){
Article::find($id)->delete();
//$article = Article::find($id);
return redirect()->back()->withErrors('Successfully deleted!');
}
Route:
Route::resource('article','ArticleController');
However, I think the problem lies in the default definition of database's name of your model. Laravel will assume that you have a database named blogs since you have a model named "blog". Are you having the database's name right?
To use DELETE HTTP Verb, your form should consists of the POST method and settings the method_field('DELETE')
Example:
<form method="POST" action="{{ route('xxx.destroy', $xxx->id) }}">
{{ csrf_field }}
{{ method_field('DELETE') }}
</form>

redirect a against different requests (laravel 5.3)

I am working on laravel 5.3
I want to redirect a user on different pages again from which page user is coming .
I have 3 pages one is
create
view all
view
I am using create page for create and edit purpose.
view all and view both page have edit button. after click it goes in Controller edit method and redirect to edit page in both cases.
Edit page have a return button. I want when user click on return it should go to view all if he comes from view all page to edit other wise if he came form view it should go back to view when he click on return.
Code for edit button is as in both view and view all pages is as
<li>
Edit
</li>
on click edit it comes here in controller edit method
public function edit($id){
$student = Student::findOrFail($id);
$data = ['action' => 'edit'];
return view('student.create')->with(compact('data', 'student'));
}
Buttons on create page are as right now
<div class="row">
<button type="submit" value="dd">Save and add</button>
#if ($data['action'] == 'edit')
<a href="{{ route('student.index') }}">
<button type="button">Return</button>
</a>
<button type="submit" value="edit">Save</button>
#endif
</div>
Now its returning me to view all students fine from update method because i use check there on button value as
if(Input::get('add')) {
return redirect()->route('student.create');
}else{
return redirect()->route('student.index');
}
How can i redirect to student.view on base of that user cam from student view to edit
Any idea how can i do it may be i also can work with session please help how to do
You can get the URI on the request using $uri = $request->path(); then use a switch the checks against $uri to dictate what to do next.
You will also need to modify your controllers head with
use Illuminate\Http\Request;
and update the edit method to public function edit(Request $request, $id){.
https://laravel.com/docs/5.3/requests#request-path-and-method
To return to the previous page/route in your controller use:
return redirect()->back();
Or simple:
return back();
Then you can have edit function like this:
public function edit($id)
{
$student = Student::findOrFail($id);
$data = [ 'action' => 'edit'];
return back()->with(compact('data', 'student'));
}
Ref: Laravel 5.2 doc - redirect
UPDATES:
If you mean it should go back after clicking the Return button then this should be enough:
Return
PS: I tested this on Laravel 5.2.* and it worked
I hope this helps :)
Use {{ URL::previous() }}
you can update your code like below
<button type="button">Return</button>

Laravel 4 PHP: Routes Order Issue

EDIT:
I am using Laravel 4 PHP and initially I thought this problem was related to the 'link_to_route' method on a webpage so you can simply link to another webpage that does not contain any dynamic data.
However, I am discovering that the order you list your Routes will ultimately determine if your routes are successfully reached or not.
Authors2.php (Controller)
class Authors2_Controller extends BaseController {
public $restful = true;
public function contact() {
return View::make('authors2.index')
->with('title','Authors and Books')
->with('authors2', Author2::orderBy('name')->get());
}
public function getnew() {
return View::make('authors2.new')
->with('title', 'Add New Author');
}
Routes.php
Route::get('authors2', array('as'=>'authors2', 'uses' =>'Authors2_Controller#contact'));
Route::get('authors2/new', array('as'=>'new_author', 'uses'=>'Authors2_Controller#getnew'));
index.blade.php (view)
#extends('layouts.default')
#section('content')
<h1>Authors2 Home Page </h1>
<ul>
#foreach($authors2 as $author2)
<li>{{ link_to_route('author2', $author2->name, $parameters = array($author2->id)) }}</li>
#endforeach
</ul>
<p>{{ link_to_route('new_author', 'Add Author') }} </p>
#endsection
When I click on the 'Add Author' link, I get the error 'Trying to get property of non-object' error.
EDIT:
So now when I change the order of the routing where if I list the 'authors2/new' route BEFORE the 'authors2' route, the route will actually work:
Route::get('authors2/new', array('as'=>'new_author', 'uses'=>'Authors2_Controller#getnew'));
Route::get('authors2', array('as'=>'authors2', 'uses' =>'Authors2_Controller#contact'));
Does this have to deal with how Routes are first received and if so, why does this happen?
As mentioned by #Barry_127, Laravel will match routes based from most specific to least specific. So its good practice to list your routes in that order.

Categories