Laravel: When creating a record with relations, cannot insert foreign key into table - forms

I am following this exercise of an "intermediate task list" from Laravel 5.2 documentations and have some difficulty understanding how this piece of code works.
$request->user()->tasks()->create([
'name' => $request->name,
]);
Question 1
Specifically, I am confused at the relation between the user() and tasks() methods. Why and how exactly can we make the user() and tasks() methods available from the $request object?
Question 2
I created a similar app and has Person and Country models. I want to pass the country_id input from a dropdown list, but I can't get the database updated, using the following code.
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'country_id' => 'required|max:3',
]);
$request->user()->people()->create([
'name' => $request->name,
'country_id' => $request->country_id,
]);
return redirect('/people');
}
Why is it that the country_id cannot be saved to the table? I tried changing the user() to country() but the error message says, "class Country" was not found. But why is the 'user()' in the tutorial available then? I am baffled.

The user() method of request is available if the user making the request is authenticated.
Since it uses User model it can also fetch the related model. For tasks() to work Task relationship must be defined in user model.
For country_id to be created(mass assigned) ensure its included in $fillable property of the People model
$fillable = ['country_id']
Please read Eloquent model relationship section in Laravel documentation.

Related

Laravel Backpack: Show a Many to Many relationship in Show Operation

Couldn't find this in the docs.
Is there any standard way, without creating a custom widget, or overriding the view template, to show a Many to Many relationships in a CRUD's showOperation in Backpack for Laravel? If the answer is NO, what would be your approach to implement it?
Let's say I have a Course Model, and a User model, and there is a Many to Many between both
class Course extends Model
{
public function students()
{
return $this->belongsToMany(User::class, 'course_students');
}
}
class User extends Model
{
public function courses()
{
return $this->belongsToMany(Course::class, 'course_students');
}
}
In the Show Operation for the Course. How do I show a Table with all students?
Indeed, you can use the relationship column for this
Excerpt:
Output the related entries, no matter the relationship:
1-n relationships - outputs the name of its one connected entity;
n-n relationships - enumerates the names of all its connected entities;
Its name and definition is the same as for the relationship field
type:
[
// any type of relationship
'name' => 'tags', // name of relationship method in the model
'type' => 'relationship',
'label' => 'Tags', // Table column heading
// OPTIONAL
// 'entity' => 'tags', // the method that defines the relationship in your Model
// 'attribute' => 'name', // foreign key attribute that is shown to user
// 'model' => App\Models\Category::class, // foreign key model
],
Backpack tries to guess which attribute to show for the related item.
Something that the end-user will recognize as unique. If it's
something common like "name" or "title" it will guess it. If not, you
can manually specify the attribute inside the column definition, or
you can add public $identifiableAttribute = 'column_name'; to your
model, and Backpack will use that column as the one the user finds
identifiable. It will use it here, and it will use it everywhere you
haven't explicitly asked for a different attribute.

Retrieve 'username' from Articles table

I have two tables, 'users' and 'articles'. Articles have a column 'user_id' which is a foreign key that references the user_id in 'users'.
I have in the Articles model this function which should return the user data:
public function user()
{
return $this->belongsTo('App\User');
}
And this works fine when I pass my articles to my viewer and call it in blade template:
#foreach($articles as $article)
<p>{{$article->user->name}}</p>
#endforeach
But I am trying to use the RESTful approach, so I am rather retrieving my data from JS (VueJS)
axios.get('/api/articles')
that should fire my Controller's function:
public function index()
{
$books = bookpost::all();
return $books;
}
So I was wondering if there's a way to append the user names to the JSON array of articles before returning it because in JS I couldn't get to find a way to get the username.
You can use "eager loading" in your query to help:
$books = bookpost::with('user')->get();
You may even eager load nested relationships:
$books = bookpost::with('user.friends')->get();
Have a look at the documentation for further help.

Edit form dynamically through subscriber

// buildForm
...
->add('book', 'entity', [
'class' => 'MyBundle\Entity\Book',
'choices' => [],
])
->addEventSubscriber(new MySubscriber());
The field book gets filled through javascript and gets the title of the book.
What I need to do is check if the book already exists in my db, otherwise I create it. I created a subscriber for that works well.
The problem is that I couldn't get rid of the error emitted by $form->handleRequest($request)->isValid(), Which is weird because I edited data in the request this way in my subscriber:
public function preSetData(FormEvent $event)
{
...
$author = $event->getData();
$requestForm = $this->request->request->get('mybundle_author');
$bookTitle = $requestForm['book'];
// if this book title doesn't exist -> create it
...
$requestForm['book] = (string) $book->getId();
$this->request->request->set('mybundle_author', $requestForm);
}
No matter what FormEvents I used, it emits the error that book value is not valid
I crossed a similar problem with the entity type.
The problem is that the new Entity is not marked as managed, and the entity type is focused on selecting existing entities. You could either pass the ObjectManager to the subscriber and set the entity as managed (with persist), or get rid of the validation error yourself. The latter is cleaner, but may require more work.
Removing the option choices fixed the problem.
My subscriber is correct but in my form I had to edit the field
// buildForm
...
->add('book', 'entity', [
'class' => 'MyBundle\Entity\Book',
//'choices' => [], // removing this fixed the problem
])
->addEventSubscriber(new MySubscriber());

Yii2 REST API fields (user?fields=id) does not work

I've got the REST API working with the user table provided in the base migration. I can "GET /users" just fine, but according to the docs, I should also be able to "GET /users?fields=id" and receive a response limited to the id fields.
But instead I get the full result set.
Under the topic Fields in Yii2 Guide it says;
// only returns field id and email, provided they are declared in fields()
http://localhost/users?fields=id,email
so you have to override the fields() function to get the expected result.
// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public function fields()
{
return [
// field name is the same as the attribute name
'id',
// field name is "email", the corresponding attribute name is "email_address"
'email' => 'email_address',
// field name is "name", its value is defined by a PHP callback
'name' => function ($model) {
return $model->first_name . ' ' . $model->last_name;
},
];
}

Entity mapping in a Symfony2 choice field with optgroup

Suppose to have an entity in Symfony2 that has a field bestfriend, which is a User entity selected from a list of User entities that satisfy a complex requirement.
You can render this field in a form by specifying that it is an entity field type, i.e.:
$builder->add('bestfriend', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'property' => 'username',
));
This form field is rendered as a <select>, where each one of the displayed values is in the form:
<option value="user_id">user_username</option>
So, one would render the field by using the <optgroup> tags to highlight such special feature of the friends.
Following this principle, I created a field type, namely FriendType, that creates the array of choices as in this answer, which is rendered as follows:
$builder->add('bestfriend', new FriendType(...));
The FriendType class creates a <select> organized with the same <option>s but organized under <optgroup>s.
Here I come to the problem! When submitting the form, the framework recognize that the user field is not an instance of User, but it is an integer. How can I let Symfony2 understand that the passed int is the id of an entity of type User?
Here follows my solution.
Notice that it is not mentioned in the Symfony2 official docs, but it works! I exploited the fact that the entity field type is child of choice.
Hence, you can just pass the array of choices as a param.
$builder->add('bestfriend', 'entity', array(
'class' => 'AcmeHelloBundle:User',
'choices' => $this->getArrayOfEntities()
));
where the function getArrayOfEntities() is a function that fills the choice list with the friends of my friends, organized by my friends:
private function getArrayOfEntities(){
$repo = $this->em->getRepository('AcmeHelloBundle:User');
$friends = $repo->findAllFriendByComplexCriteria(...);
$list = array();
foreach($friends as $friend){
$name = $friend->getUsername();
if(count($friend->getFriends())>0){
$list[$name] = array();
foreach($friend->getFriends() as $ff){
$list[$name][$ff->getUsername()] = $ff;
}
}
}
return $list;
}
I know the example could be meaningless, but it works...
PS: You need to pass the entity manager to let it working...