So I'm a total newbie in laravel and I don't know if it can be done but I saw that in the controller I can display data of a specific 'id' with this in my api.php:
Route::get('books/{id}', 'App\Http\Controllers\BooksController#getBookById');
And this in my BookController.php :
public function getBookByAuthor($id) {
$book = Books::find($id);
if (is_null($book)){
return response()->json(['message' => 'Book Not Found.'], 404);
}
return response()->json($book::find($id), 200);
}
I'm using Angular for the front and I have a searchbar to search by 'title' of a book, so in my database I have a column 'title' and I want to fetch data by 'title' instead of 'id'.
Is it possible ? And if yes how ?
I'm thinking you're wanting to retrieve the book based on user input...? You can inject the request in your method. Also you don't need to explicitly handle 404 and response codes.
use Illuminate\Http\Request;
use App\Models\Book;
public function getBookByAuthor(Request $request): Response
{
$input = $request->validate([
'title' => 'required|alpha_dash' // validate
]);
return Book::where('title', 'like', "%{$input['title']}%")
->firstOrFail();
}
Validation docs
Related
I want to redirect to my new post when I created a new post in Laravel
But I get a ArgumentCountError
Too few arguments to function App\Http\Controllers\ArticlesController::store(), 1 passed in C:\xampp\htdocs\forum\vendor\laravel\framework\src\Illuminate\Routing\Controller.php on line 54 and exactly 2 expected
How can I fix it? Thanks
web.php
<?php
Route::resource('articles', ArticlesController::class);
Route::get('/', [ArticlesController::class, 'index'])->name('root');
Route::resource('articles.comments', CommentsController::class);
ArticlesController.php
public function store(Request $request, $id) {
$content = $request->validate([
'title' => 'required|max:30',
'content' => 'required|min:10'
]);
//限制只有透過登入才能CREATE文章
auth()->user()->articles()->create($content);
return redirect('articles/'. $id)->with('notice', '文章發表成功!');
}
create.blade.php
<form class="container-fluid" action="{{ route('articles.store') }}" method="post">
Check your store() method. I think it should get only Request $request.
Example
public function store(Request $request) {
$content = $request->validate([
'title' => 'required|max:30',
'content' => 'required|min:10'
]);
//限制只有透過登入才能CREATE文章
$article = Article::create($content); // static is not best practice, only for example
return redirect('articles/'. $article->id)->with('notice', '文章發表成功!');
}
But before using the create method, you will need to specify either a fillable or guarded. Check docs
Presumably you need / have a way of viewing an article anyway, whether it's just been added or not, so in your web.php you would want a GET request to retrieve an article by passing its ID:
Route::get('/article/{id}', [ArticleController::class, 'viewArticle'])-> name('article.view');
Then you would want a POST request to add a new article :
Route::post('/addarticle', [ArticleController::class, 'addArticle'])-> name('article.add');
In your ArticleController, at the end of your addArticle method, once your new article has been created, you can then return a redirect to your "view article" route referencing its name, and passing in the parameter that it expects - the new article's ID - as part of the route, like so :
$article = new Article();
... populate the article's details here ...
return redirect()->route('article.view', ['id' => $article->id]);
I already solved it by my way
remove $id from store() function
just add $article before auth()->user()->articles()->create($content)
$id change to $article->id from redirect()
Example
public function store(Request $request) {
$content = $request->validate([
'title' => 'required|max:30',
'content' => 'required|min:10'
]);
$article = auth()->user()->articles()->create($content);
return redirect('articles/'. $article->id)->with('notice', '文章發表成功!');
}
Thank you
How can I remove the parameters from a URL after processing in my controller? Like this one:
mydomain/mypage?filter%5Bstatus_id%5D
to
mydomain/mypage
I want to remove the parameters after the ? then I want to use the new URL in my view file. Is this possible in laravel 5.2? I have been trying to use other approaches but unfortunately they are not working well as expected. I also want to include my data in my view file. The existing functionality is like this:
public function processData(IndexRequest $request){
//process data and other checkings
return view('admin.index')
->with([
'data' => $data,
'person' => $persons,
]);
}
I want it to be like:
public function processData(IndexRequest $request){
//process data and other checkings
// when checking the full url is
// mydomain/mypage?filter%5Bstatus_id%5D
// then I want to remove the parameters after the question mark which can be done by doing
// request()->url()
// And now I want to change the currently used url using the request()->url() data
return view('admin.index')
->with([
'data' => $data,
'person' => $persons,
]);
}
I'm stuck here for days already. Any inputs are appreciated.
You can use request()->url(), it will return the URL without the parameters
public function processData(IndexRequest $request){
$url_with_parameters = $request()->url();
$url= explode("?", $url_with_parameters );
//avoid redirect loop
if (isset($url[1])){
return URL::to($url[0]);
}
else{
return view('admin.index')
->with(['data' => $data,
'person' =>$persons,]);
}
}
add new url to your routes and assuming it will point to SomeController#SomeMethod, the SomeMethod should be something like :
public function SomeMethod(){
// get $data and $persons
return view('admin.index')
->with(['data' => $data,
'person' =>$persons,]);
}
I hope this helps
I have a table called Customer and with a Get Request I can already get all the Data (which I created with phpMyAdmin) on a HTML Template.
Now I want to create a new Customer with a Post Request.
This is the way I thought it would work:
In the Controller:
public function addNewCustomer(Request $request)
{
return \app\model\Customer::create($request->all());
}
The route:
Route::post('posttest', 'CustomerController#addNewCustomer');
How can I create a validation for it?
You can add validation of form like below in addNewCustomer,
public function addNewCustomer(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|max:255',
'body' => 'required',
]);
return \app\model\Customer::create($request->all());
}
For more information about input validation in Laravel Please readout Laravel Validation Documentation
When updating my Post model, I run:
$post->title = request('title');
$post->body = request('body');
$post->save();
This does not update my post. But it should according to the Laravel docs on updating Eloquent models. Why is my model not being updated?
I get no errors.
The post does not get updated in the db.
Besides not being updated in the db, nothing else seems odd. No errors. Behavior as normal.
Result of running this test to see if save succeeded was true.
This Laravel thread was no help
Post model:
class Post extends Model
{
protected $fillable = [
'type',
'title',
'body',
'user_id',
];
....
}
Post controller:
public function store($id)
{
$post = Post::findOrFail($id);
// Request validation
if ($post->type == 1) {
// Post type has title
$this->validate(request(), [
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
$post->title = request('title');
$post->body = request('body');
} else {
$this->validate(request(), [
'body' => 'required|min:19',
]);
$post->body = request('body');
}
$post->save();
return redirect('/');
}
Bonus info
Running dd($post->save()) returns true.
Running
$post->save();
$fetchedPost = Post::find($post->id);
dd($fetchedPost);
shows me that $fetchedPost is the same post as before without the updated data.
Check your database table if the 'id' column is in uppercase 'ID'. Changing it to lower case allowed my save() method to work.
I had the same and turned out to be because I was filtering the output columns without the primary key.
$rows = MyModel::where('...')->select('col2', 'col3')->get();
foreach($rows as $row){
$rows->viewed = 1;
$rows->save();
}
Fixed with
$rows = MyModel::where('...')->select('primary_key', 'col2', 'col3')->get();
Makes perfect sense on review, without the primary key available the update command will be on Null.
I had the same problem and changing the way I fetch the model solved it!
Was not saving even though everything was supposedly working just as you have mentioned:
$user = User::find($id)->first();
This is working:
$user = User::find($id);
You have to make sure that the instance that you are calling save() on has the attribute id
Since Laravel 5.5 laravel have change some validation mechanism I guess you need to try this way.
public function store(Request $request, $id)
{
$post = Post::findOrFail($id);
$validatedData = [];
// Request validation
if ($post->type == 1) {
// Post type has title
$validatedData = $request->validate([
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
} else {
$validatedData = $request->validate([
'body' => 'required|min:19',
]);
}
$post->update($validatedData);
return redirect('/');
}
Running dd() inside a DB::transaction will cause a rollback, and the data in database will not change.
The reason being, that transaction will only save the changes to the database at the very end. Ergo, the act of running "dump and die" will naturally cause the script to cease and no therefore no database changes.
Check your table if primary key is not id ("column name should be in small letters only") if you have set column name with different key then put code in your Model like this
protected $primaryKey = 'Id';
So this might be one of the possible solution in your case also if your column name contains capital letters.
Yes this worked for me fine,
You should have column names in small letter,
If you don't have then mention it in the model file, mainly for primaryKey by which your model will try to access database.
For use save () method to update or delete if the database has a primary key other than "id". need to declare the attribute primaryKey = "" in the model, it will work
Try this
public function store($id,Request $request)
{
$post = Post::findOrFail($id);
// Request validation
if ($post->type == 1) {
// Post type has title
$request->validate([
'title' => 'required|min:15',
'body' => 'required|min:19',
]);
$post->update([
'title' => request('title');
'body' => request('body');
]);
} else {
$request->validate([
'body' => 'required|min:19',
]);
$post->update([
'body' => request('body');
]);
}
return redirect('/');
}
In my experience, if you select an Eloquent model from the db and the primary_key column is not part of the fetched columns, your $model->save() will return true but nothing is persisted to the database.
So, instead of doing \App\Users::where(...)->first(['email']), rather do \App\Users::where(...)->first(['id','email']), where id is the primary_key defined on the target table.
If the (sometimes micro-optimization) achieved by retrieving only a few columns is not really of importance to you, you can just fetch all columns by doing \App\Users::where(...)->first(), in which case you do not need to bother about the name of the primary_key column since all the columns will be fetched.
If you using transactions.
Do not forget call DB::commit();
It must look like this:
try{
DB::beginTransaction();
// Model changes
$model->save();
DB::commit();
}catch (\PDOException $e) {
DB::rollBack();
}
I have the same issue although there are try / catch block in controller#action() but there were no response, it just stops at $model->save(); there is no log entry either in apache error.log or laravel.log. I have just wrapped the save() with try / cactch as follows, that helped me to figure out the issue
try{
$model->save();
}
catch (\PDOException $e) {
echo $e->getMessage();
}
I have been experiencing the same issue and found a workaround. I found that I was unable to save() my model within a function called {{ generateUrl() }} on my home.blade.php template. What worked was moving the save() call to the controller that returns the home.blade.php template. (IE, save()ing before the view is returned, then only performing read operations within {{ generateUrl() }}.)
I was (and am) generating a state to put in a URL on page load:
<!--views/home.blade.php-->
Add Character
Below is what did not work.
// Providers/EveAuth.php
function generateUrl()
{
$authedUser = auth()->user();
if (!$authedUser) {
return "#";
}
$user = User::find($authedUser->id);
$user->state = str_random(16);
$user->save();
$baseUrl = 'https://login.eveonline.com/oauth/authorize?state=';
return $baseUrl . $user->state;
}
This was able to find() the User from the database, but it was unable to save() it back. No errors were produced. The function appeared to work properly... until I tried to read the User's state later, and found that it did not match the state in the URL.
Here is what did work.
Instead of trying to save() my User as the page was being assembled, I generated the state, save()d it, then rendered the page:
// routes/web.php
Route::get('/', 'HomeController#index');
Landing at the root directory sends you to the index() function of HomeController.php:
// Controllers/HomeController.php
public function index()
{
$authedUser = auth()->user();
if ($authedUser) {
$user = User::find($authedUser->id);
$user->state = str_random(16);
$user->save();
}
return view('home');
}
Then, when generating the URL, I did not have to save() the User, only read from it:
// Providers/EveAuth.php
function generateUrl()
{
$authedUser = auth()->user();
$user = User::find($authedUser->id);
$baseUrl = 'https://login.eveonline.com/oauth/authorize?state=';
return $baseUrl . $user->state;
}
This worked! The only difference (as far as I see) is that I'm save()ing the model before page assembly begins, as opposed to during page assembly.
I just start learning Laravel 5, and I want to know what the proper way to handle submitted forms. I found many tutorials where we create two separate actions, where first render form, and the second actually handle form. I am came from Symfony2, where we create a single action for both, render and handle submitted form, so I want to know I need to create two separate actions because thats Laravel-way, or I can place all logic into single action, I do this like the folowing, but I dont like code what I get:
public function create(Request $request)
{
if (Input::get('title') !== null) {
$v = Validator::make($request->all(), [
'title' => 'required|unique:posts',
'content' => 'required',
]);
if ($v->fails()) {
return redirect()->back()->withErrors($v->errors());
}
$post = new Post(Input::all());
if ($post->save()) {
return redirect('posts');
}
}
return view('add_post');
}
So can somebody give me advice how I need do this properly? Thanks!
One of the most important reason to create two actions is to avoid duplicate form submissions . You can read more about Post/Redirect/Get pattern.
Another important reason is the way you keep the code cleaner. Take a look at this first change:
public function showForm(){
return view('add_post');
}
public function create(Request $request)
{
$v = Validator::make($request->all(), [
'title' => 'required|unique:posts',
'content' => 'required',
]);
if ($v->fails()) {
return redirect()->back()->withErrors($v->errors());
}
$post = new Post(Input::all());
if ($post->save()) {
return redirect('posts');
}
return redirect()->route('show_form')->withMessage();
}
The first thing that you can notice is that create() function is not rendering any view, it is used to manage the creation logic (as the name itself suggests). That is OK if you plan to stay in low-profile, but what happens when you do need to add some others validations or even better, re-utilize the code in other controllers. For example, your form is a help tool to publish a comment and you want to allow only "authors-ranked" users to comment. This consideration can be manage more easily separating the code in specific actions instead making an if-if-if-if spaghetti. Again...
public function showForm(){
return view('add_post');
}
public function create(PublishPostRequest $request)
{
$post = new Post($request->all());
$post->save()
return redirect('posts');
}
Take a look on how PublishPostRequest request takes place in the appropriated function. Finally, in order to get the best of Laravel 5 you could create a request class to keep all the code related with validation and authorization inside it:
class PublishPostRequest extends Request{
public function rules(){
return [
'title' => 'required|unique:posts',
'content' => 'required',
]
}
public function authorize(){
$allowedToPost = \Auth::user()->isAuthor();
// if the user is not an author he can't post
return $allowedToPost;
}
}
One nice thing about custom request class class is that once is injected in the controller via function parameter, it runs automatically, so you do not need to worry about $v->fails()