I have select options in my form where it has first row when page loads and users can add more rows by AJAX and store all rows data at once.
The problem is that my first row (which is visible when page loads) does not save the data while all other added rows will be saved.
Here is a screenshot of my select options when page loads:
And here it is when user adds new rows:
Here is my sample data that those rows have sent to controller (screenshot #2):
array:2 [▼
0 => array:3 [▼
"name" => "ali"
"username" => "alireza"
"action" => "delete"
]
1 => array:3 [▼
"name" => "eraty"
"username" => "aery"
"action" => "optional"
]
]
As I explained in my screenshots, object 0 data will not be store in the database, not sure why.
Here is my controller:
public function update(Request $request, $id)
{
$this->validate($request, [
'note' => 'required|string',
]);
$post = Post::where('id', $id)
->where('user_id', Auth::id())
->first();
$post->user_id = Auth::id();
$post->note = $request->input('note');
if ($post->save()) {
// social media (add new)
$socialHeir = $request->input('social_media_heir');
$socialAction = $request->input('social_media_action');
$socialNames = $request->input('social_media_name');
$socialUsernames = $request->input('social_media_username');
if (!empty($socialNames)) {
$result_array = [];
foreach ($socialNames as $key => $val) {
$result_array[$key] = [
'name' => $socialNames[$key],
'username' => $socialUsernames[$key],
'action' => $socialAction[$key]
];
}
// dd($result_array); <-- result of this line I shared above (after screenshot 2)
foreach ($result_array as $key => $merge) {
if (!empty($key) && !empty($merge)) {
SocialMedia::create([
'owner_id' => Auth::id(),
'heir_id' => $socialHeir,
'post_id' => $post->id,
'name' => $merge['name'],
'username' => $merge['username'],
'what_to_do' => $merge['action'],
]);
}
}
}
}
return redirect()->route('posts.index');
}
Update
SocialMedia model:
protected $fillable = [
'owner_id',
'heir_id',
'post_id',
'name',
'username',
'what_to_do',
];
public function post()
{
return $this->belongsTo(Post::class);
}
Post model
protected $fillable = [
'user_id',
'note',
];
public function socialMedias()
{
return $this->hasMany(SocialMedia::class);
}
Solved
The issue was in $key in my foreach after removing it, it saves all rows now.
foreach($result_array as $merge) {
if(!empty($merge)) {
SocialMedia::create([
'owner_id' => Auth::id(),
'heir_id' => $socialHeir,
'post_id' => $will->id,
'name' => $merge['name'],
'username' => $merge['username'],
'what_to_do' => $merge['action'],
]);
}
}
Related
This method doesn't work:
public function update(Category $category) {
$data = request()->validate([
'name' => 'required',
]);
$category->update([
$data
]);
return redirect("/category/{$category->id}/edit");
}
But it works fine, like that:
public function update(Category $category) {
$data = request()->validate([
'name' => 'required',
]);
$category->update([
'name' => request()->input('name')
]);
return redirect("/category/{$category->id}/edit");
}
Result from dd($data) in first case is :
array:1 [▼
"name" => "test"
]
I'm using first way in other conrollers and it also works, I'm confused.
As you can see in the dd($data), $data is already an array with keys named as the validated fields. What you are doing is wrap it again inside another array:
$category->update([
$data
]);
So that is equivalent to:
$category->update([
[
'name' => 'test',
],
]);
Try it like this instead:
$category->update($data);
I encountered above error while update scenario, am trying to save the multi selected values into relation table('classification_vs_metric') along with master tables(classifications,metrics) id's in create metrics.
but when i click on edit button on already created record i encounter this error.
Metrics Master
id
name
type
3
Land
ha,m2
4
Floors
Nos
Classification Master
id
industry
sector
subsector
1
Construction
Commercial
Casino
2
Construction
Commercial
Cinema
3
Construction
Commercial
Convention Center
classification_vs_metric slave/relation table
id
metric_id
classification_id
1
3
1
2
3
2
3
3
3
4
4
1
5
4
2
and am using following method to get the slave table values in actionUpdate in metrics controller
public function getClassificationVsMetrics1()
{
return $this->hasMany(Classificationvsmetric::className(), ['metric_id' => 'id'])->select(['classification_id']);
}
as
public function actionUpdate($id)
{
$model = $this->findModel($id);
$classificationIndustry = array();
$releations = $model->getClassificationVsMetrics1()->asArray()->all();
if ($model->load(Yii::$app->request->post())) {
if($model->save()){
$classifications = Yii::$app->request->post()["Classificationvsmetric"]['classification_id'];
$classVsmetric = Classificationvsmetric::deleteAll(['metric_id'=>$model->id]);
foreach ($classifications as $key => $value) {
$Classificationvsmetric = new Classificationvsmetric();
$Classificationvsmetric->classification_id =(int)$value;
$Classificationvsmetric->metric_id = $model->id;
$Classificationvsmetric->save(false);
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
'Classificationvsmetric' => $releations
]);
}
and in _form.php
$classificationIndustry = ArrayHelper::map(\common\models\Classifications::find()->all(),'id',function($model,$default){
return $model["industry"]." - ".$model["sector"] ." - ".$model['sub_sector'];
});
echo $form->field($Classificationvsmetric[0], 'classification_id')->widget(Select2::classname(), [
'data' => $classificationIndustry, // error showing in this line
'value'=>(!$model->isNewRecord ? [$result] : ''),
'language' => 'en',
'options' => ['placeholder' => 'Select classification(s)','multiple' => true],
'pluginOptions' => [
'allowClear' => true,
],
]);
this is working fine with create scenario, but getting error "Call to a member function isAttributeRequired() on array" in edit scenario. Can any body help me !!
Finally after 2 days of head scratching i find solution myself.
I have made few minor changes like below
In metric master
public function getClassificationVsMetrics1()
{
return $this->hasMany(Classificationvsmetric::className(), ['metric_id' => 'id']);
}
In metric controller
public function actionUpdate($id)
{
$model = $this->findModel($id);
$releations = $model->getClassificationVsMetrics1()->all();
if ($model->load(Yii::$app->request->post())) {
if($model->save()){
$classifications = Yii::$app->request->post()["Classificationvsmetric"]['classification_id'];
$classVsmetric = Classificationvsmetric::deleteAll(['metric_id'=>$model->id]);
foreach ($classifications as $key => $value) {
$Classificationvsmetric = new Classificationvsmetric();
$Classificationvsmetric->classification_id =(int)$value;
$Classificationvsmetric->metric_id = $model->id;
$Classificationvsmetric->save(false);
}
if($Classificationvsmetric == true){
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
'Classificationvsmetric' => $releations
]);
}
and in view am managed to pass the values stored in the slave table as default value for select2 widget.
<?php
$classificationIndustry = ArrayHelper::map(\common\models\Classifications::find()->all(),'id',function($model,$default){
return $model["industry"]." - ".$model["sector"] ." - ".$model['sub_sector'];
});
foreach ($Classificationvsmetric as $key => $value) {
$selected[] = $value['classification_id'];
}
echo $form->field($Classificationvsmetric[0], 'classification_id')->widget(Select2::classname(), [
'data' => $classificationIndustry,
'language' => 'en',
'options' => [ 'value'=>(!$model->isNewRecord ? $selected : ''),'placeholder' => 'Select classification(s)','multiple' => true],
'pluginOptions' => [
// 'disabled' => $is_readonly,
'allowClear' => true,
// 'maximumSelectionLength' => 3,
],
]);
?>
i know this is not feasible solution, but right now this will save my butt.
preselected values in select2 widget in update scenario with many to many relation
I have a strange scenario where Laravel is returning a 0 for the ID. This works locally and I've also confirmed the model saves and returns the ID correctly in another function. Why is the ID always 0? ( The model always saves successfully ).
The ID column is auto-incrementing.
//MODEL
class Email extends Model
{
public $fillable = ['to', 'from', 'relates_to', 'name', 'email',
'subject', 'greeting','attachment',
'body', 'module_id', 'sign_off', 'course_id' ];
protected $casts = ['attachment'=>'integer'];
protected $dates = ['sent_at'];
public function scopeMine($query, $user)
{
return $query->where('from', $user);
}
}
//Controller
public function storeAndSend(Request $request)
{
$validatedData = $request->validate([
'subject' => 'sometimes|required|string',
'greeting' => 'required',
'body' => 'required',
'sign_off' => 'required',
'email' => 'required|email',
'module_id' => 'required',
'name' => 'required|string'
]);
//save Email
$email = new \App\Email;
$email->to = $request->has('user') ? $request->user : 0;
$email->name = $request->name;
$email->email = $request->email;
$email->relates_to = $request->has('entity') ? $request->entity : null;
$email->from = $request->user()->id;
$email->subject = $request->subject;
$email->greeting = $request->greeting;
$email->attachment = $request->attachment ?? null;
$email->body = $request->body;
$email->sign_off = $request->sign_off;
$email->course_id = $request->course_id;
$email->module_id = $request->module_id ?? null;
$email->save();
dd($email->toArray()); // $email->id = 0
//get to
dispatch(new \App\Jobs\SendCourse($email->id));
return response()->json(['success'=>true]);
}
//Output of the dump
array:15 [
"to" => "58"
"name" => "joe"
"email" => "joe#boobo.com"
"relates_to" => "App\User"
"from" => 1
"subject" => "test"
"greeting" => "Hello"
"attachment" => null
"body" => "<p>test</p>"
"sign_off" => "Catch you later"
"course_id" => 27
"module_id" => -1
"updated_at" => "2018-11-04 14:00:59"
"created_at" => "2018-11-04 14:00:59"
"id" => 0
]
It was a issue with telescope.
As said in the comments, this was the issue: https://github.com/laravel/telescope/issues/289
It looks like it is now fixed, btw.
I am trying to implement the 2amigos SelectizeDropDownList widget in a form to add new values to a table directly within the dropdown.
I am using the model Book and the Model Author so basically want to be able to add a new author in the book form.
This is the book controller at the update function:
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['index']);
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}
This is the form:
<?=
$form->field($model, 'author_id')->widget(SelectizeDropDownList::className(), [
// calls an action that returns a JSON object with matched
// tags
'loadUrl' => ['author/list'],
'value' => $authors,
'items' => \yii\helpers\ArrayHelper::map(\common\models\author::find()->orderBy('name')->asArray()->all(), 'id', 'name'),
'options' => [
'class' => 'form-control',
'id' => 'id'
],
'clientOptions' => [
'valueField' => 'id',
'labelField' => 'name',
'searchField' => ['name'],
'autosearch' => ['on'],
'create' => true,
'maxItems' => 1,
],
])
?>
And this is the function author controller:
public function actionList($query) {
$models = Author::findAllByName($query);
$items = [];
foreach ($models as $model) {
$items[] = ['id' => $model->id, 'name' => $model->name];
}
Yii::$app->response->format = \Yii::$app->response->format = 'json';
return $items;
}
The form works fine to load, filter, search and add new items.
But it is not inserting the new typed attribute in the author table.
Do I need to add something in the book controller?
How can I check if it is a new value or a change of an existing author?
Thanks a lot
I made it work with the following code, not sure the most elegant because i am checking the if the author_id is a number or a string.
In my case the author won't be a number anyway.
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$x = Yii::$app->request->post('Book');
$new_author = $x['author_id'];
if (!is_numeric($new_author)) {
$author = new Author();
$author->name = $new_author;
$author->save();
$model->author_id = $author->id;
}
if ($model->save()) {
return $this->redirect(['index']);
}
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}
I currently have an belongsToMany relationship between two Table, Skus and Medias. I named the join table skus_images though.
I'm here trying to save only ids, not inserting new data in an HABTM way.
I have in my form :
echo $this->Form->input('images._ids', ['options' => $images, 'multiple' => 'checkbox']);
And everything is working fine there, I'm correctly getting my Medias listed.
But whenever I try to submit the form, I get this :
Error: Call to a member function get() on a non-object
File /home/weshguillaume/AndyToGaby/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php
Line: 874
I've defined my relationship as such in SkusTable :
$this->belongsToMany('Images', [
'className' => 'Media.Medias',
'joinTable' => 'skus_images',
'targetForeignKey' => 'image_id'
]);
The context doesn't give any insights, neither does the stack trace as it's both (almost) empty. Thanks :)
EDIT:
Controller add method:
public function add($product_id)
{
$skus = $this->Skus->newEntity();
if ($this->request->is('post')) {
$skus = $this->Skus->patchEntity($skus, $this->request->data(), [
'associated' => [
'Attributes'
]
]);
if ($this->Skus->save($skus)) {
$this->Flash->success('The skus has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The skus could not be saved. Please, try again.');
}
}
$attributes = $this->Skus->Attributes->find('list');
$images = $this->Skus->Products->getMedias('list', $product_id, 'photo');
$this->set(compact('skus', 'products', 'attributes', 'images', 'product_id'));
$this->set('_serialize', ['skus']);
}
Controller posted data:
[
'product_id' => '65',
'attributes' => [
'_ids' => ''
],
'reference' => '',
'quantity' => '420',
'is_default' => '0',
'images' => [
'_ids' => [
(int) 0 => '90'
]
]
]
Forgot to add the name of the association in the patchEntity associated option. Still shouldn't throw a fatal error so I created a github ticket.