I am working on one to many relationship between tasks and Projects, i.e. a task can only belong to a single project, and I have used laravel's Accessor to get the selected project in my view in drop down:
my code is as follow:
public function getAssignUserAttribute($value)
{
dd($value); // gives me null
// if $value have id of user I want to get that user from db
}
and my view contains the drop down is:
{!! Form::select('assign_user', $assign_user, null, ['class' => 'form-control select2', 'id' => 'assign_user']) !!}
I have accessed all the users from database into TasksController to the view as:
$assign_user = User::pluck('title', 'id');
return view('tasks.edit', compact('task', 'assign_user'));
But I get all users selected, while I only want to have the selected user in my drop down.
Can someone guide me to the right path.
Thank you
finally I solved the issue by myself I have edit the Accessor as follow:
public function getAssignUserAttribute()
{
return [0 => $this->attributes['assign_user'] ];
}
Since I required an array so I assigned the current user to the array index 0 and return, in that case the view selected the returned user in drop down :)
This may help someone :)
Related
I have two related tables and I want to return all fields including the ID (key) field. My query below returns all fields except the ID. how do I return the ID field from one of the tables?
'programmes' => ProgrammeInstances::with('programmes')->get(),
the query below returns Unknown column 'programmes.programme_title' as it is looking for it in the table 'programme_instances'
'programmes' => ProgrammeInstances::with('programmes')->select('programmes.programme_title', 'programmeInstances.id', 'programmeInstances.name', 'programmeInstances.year')->get(),
Laravel provides multiple relationships, one of these is the hasMany() relationship which should return a collection where a User hasMany rows inside of your database
For example, inside your User model :
public function programmes() {
return $this->hasMany(Program::class);
}
Now in your controller, you can do :
public function edit($id) {
$programmes = User::find($id)->with('programmes')->get();
return view('user.edit')->with('programmes', $programmes);
}
And then you can loop over it inside your view
#forelse($programmes->programmes as $program)
// provide the data
#empty
// the user doesn’t have any programmes
#endforelse
a solution i found below - still not sure why ID isnt automatically returned when i get all fields, but works when i specify individual fields:
'programmes' => ProgrammeInstances::with('programmes')
->get()
->transform(fn ($prog) => [
'programme_title' => $prog->programmes->programme_title,
'id' => $prog->id,
'name' => $prog->name,
'year' => $prog->year,
]),
So, i have a table called Items table and another table called item_quantities, on item_quantities ive a column named item_id which is connected to items table id. All the fillable properties on both tables are all in one form on the frontend, and i take care of the form fields on the backend
Whenever i try to update the quantity on the form which is from item_quantities's table with a form, i'm facing serious issue updating the item_quantities. getting Attempt to read property "item_id" on null.
It all started when i noticed a duplicate entries on the item-quantities table, so i deleted all the datas on it..
Here's is the form screenshot
The vue form
and the backend logic
public function saveData(Request $request, $id) {
// dd($request->name);
$updateGroceries = Item::where('id', $request->id)->get()->first();
$updateGroceries->update([
'name' => $request->name,
'description' => $request->description,
'price' => $request->price,
]);
if($updateGroceries) {
$item_quantity = ItemQuantity::where('item_id', $updateGroceries->id) ?
ItemQuantity::where('item_id', $updateGroceries->id)->get()->first() :
new ItemQuantity;
if($item_quantity->item_id == null) {
$item_quantity->item_id = $updateGroceries->id;
}
$item_quantity->quantity = $request->quantity;
$item_quantity->save();
}
}
I'M SO SORRY IF MY ENGLISH WAS'NT CLEARED ENOUGH
Thanks in anticipation
You can simply use firstOrNew() method. This will first find the item, if not exist create e new instance.
$item_quantity = ItemQuantity::firstOrNew(['item_id' => $updateGroceries->id]);
$item_quantity->quantity = $request->quantity;
$item_quantity->save();
Note that the model returned by firstOrNew() has not yet been persisted to the database. You will need to manually call the save method to persist it.
Actually your errors workflow as that:
$item_quantity=null;
$item_quantity->item_id;
You can do that with optional global helper:
optional($item_quantity)->item_id ?: 'default value';
I'm brand new to Laravel and am working my way through the Laravel 6 from Scratch course over at Laracasts. The course is free but I can't afford a Laracasts membership so I can't ask questions there.
I've finished Section 6 of the course, Controller Techniques, and am having unexpected problems trying to extend the work we've done so far to add a few new features. The course has students build pages that let a user show a list of articles, look at an individual article, create and save a new article, and update and save an existing article. The course work envisioned a very simple article containing just an ID (auto-incremented in the database and not visible to the web user), a title, an excerpt and a body and I got all of the features working for that. Now I'm trying to add two new fields: an author name and a path to a picture illustrating the article. I've updated the migration, rolled back and rerun the migration to include the new fields and got no errors from that. (I also ran a migrate:free and got no errors from that.) I've also updated the forms used to create and update the articles and added validations for the new fields. However, when I go to execute the revised create code, it fails because the SQL is wrong.
The error message complains that the author field doesn't have a default, which is true, I didn't assign a default. However, I did give it a value on the form. What perplexes me most is the SQL that it has generated: the column list doesn't show the two new columns. And that's not all: the values list is missing apostrophes around any of the string/text values. (All of the columns are defined as string or text.)
As I said, I'm completely new to Laravel so I don't know how to persuade Laravel to add the two new columns to the Insert statement nor how to make it put apostrophes around the strings in the values list. That hasn't come up in the course and I'm not sure if it will come up later. I was hoping someone could tell me how to fix this. All of my functionality was working fine before I added the two new fields/columns.
Here is the error message:
SQLSTATE[HY000]: General error: 1364 Field 'author' doesn't have a default value (SQL: insert into `articles` (`title`, `excerpt`, `body`, `updated_at`, `created_at`) values (Today in Canada, The ideal winter-beater, This car is the ideal winter-beater for the tough Canadian climate. It is designed to get you from A to B in style and without breaking the bank., 2020-02-15 17:37:54, 2020-02-15 17:37:54))
Here is ArticlesController:
<?php
namespace App\Http\Controllers;
use App\Article;
use Illuminate\Http\Request;
class ArticlesController extends Controller
{
public function index()
{
$articles = Article::latest()->get();
return view ('articles.index', ['articles' => $articles]);
}
public function show(Article $article)
{
return view('articles.show', ['article' => $article]);
}
public function create()
{
return view('articles.create');
}
public function store()
{
//Stores a NEW article
Article::create($this->validateArticle());
return redirect('/articles');
}
public function edit(Article $article)
{
return view('articles.edit', ['article' => $article]);
}
public function update(Article $article)
{
//Updates an EXISTING article
$article->update($this->validateArticle());
return redirect('/articles/', $article->id);
}
public function validateArticle()
{
return request()->validate([
'title' => ['required', 'min:5', 'max:20'],
'author' => ['required', 'min:5', 'max:30'],
'photopath' => ['required', 'min:10', 'max:100'],
'excerpt' => ['required', 'min:10', 'max:50'],
'body' => ['required', 'min:50', 'max:500']
]);
}
public function destroy(Article $article)
{
//Display existing record with "Are you sure you want to delete this? Delete|Cancel" option
//If user chooses Delete, delete the record
//If user chooses Cancel, return to the list of articles
}
}
Is there anything else you need to see?
It may be possible because of you don't have defined that column in fillable property, to use mass assignment you have to specify that columns.
Try after adding that columns in fillable property.
Laravel mass assignment
Hope this helps :)
i'm new to Laravel and i'm using InfyOm laravel generator to create an app.
I came to an issue and would like to know what is the best practice to do this:
I have a model "Mission". When creating a mission, it need to have a client id and agent id associated with it.
In my view, i want to display 2 dropdown lists, one containing all the active clients (id + name) and the other containing all the active agents (id + name).
my controller
public function create()
{
return view('missions.create');
}
my view blade
{!! Form::select('client_id', ?????? , null, ['class' => 'form-control']) !!}
Thanks for your suggestions
Most convenient way is to use pluck() method to build a list from a collection, for example:
public function create()
{
return view('missions.create', [
'users' => User::pluck('name', 'id')
]);
}
Then use $list variable:
{!! Form::select('client_id', $users , null, ['class' => 'form-control']) !!}
I have two collections on a single page which should be both paginated. But pagination generates the same Parameter for both (?page=X).
How can I solve that kind of an issue?
You can change the param of either pagination by
Paginator::setPageName('someparam');
Read more about Pagination here In the section Customizing The Paginator URI
Note : You should do this before paginator is done i.e.,
$yourCollection = Model::paginate(10);
Example :
I assume you have two pagination like this
Paginator::setPageName('yourFirstParam');
$firstCollection = FirstModel::paginate(10);
Paginator::setPageName('yourSecondParam');
$secondCollection = SecondModel::paginate(10);
Where you use this to get in your view
Paginator::setPageName('yourFirstParam');
$firstCollection->links();
Paginator::setPageName('yourSecondParam');
$secondCollection->links();
There is a way to "automatically" set the page name (in a sense), which I'll get to in a bit.
First, if we go over the paginate method, you'll see that it accepts a pageName argument as its 3rd parameter:
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
Lets say you have a User and Post model. You can then do something like this in your controller:
$users = User::paginate(10, ['*'], 'users');
$posts = Post::paginate(10, ['*'], 'posts');
return view('example', compact('users', 'posts'));
It works like your normal pagination except the second argument specifies the columns you want to select and the third argument specifies the page name.
In your view, when you render your pagination links, you might run into a problem when you do this:
{!! $users->render() !!}
{!! $posts->render() !!}
While the pagination links will be rendered, when you click on a link to a posts page, the users query string parameter is gone. Therefore, the users are back to page one and vice versa.
To fix this, you can use the appends method to keep the query parameters for both models:
{!! $users->appends(['posts' => Request::query('posts')])->render() !!}
{!! $posts->appends(['users' => Request::query('users')])->render() !!}
All this works, but it's a bit ugly so how can we clean this up? You can create your own method to "automate" this process. In your model, you can add your own paginate method:
// Name it whatever you want, but I called it superPaginate lol
protected function superPaginate($perPage)
{
return $this->newQuery()->paginate(10, ['*'], $this->getTable());
}
This will automatically set the pagination name to the model's table name. So for the User model, the page name will be "users". For the Post model, the page name will be "posts".
There's still the problem with rendering links. You don't want to call appends all the time and specify the query parameters. To fix that, we can improve the superPaginate method into this:
protected function superPaginate($perPage, $columns = ['*'], $page = null)
{
$params = \Request::query();
return $this->newQuery()->paginate(10, $columns, $this->getTable(), $page)->appends($params);
}
Now, all you need to do is Model::superPaginate(10); and $models->render(). Everything should work properly.