How to create data into junction table many to many relationship without create data into the junction point to - laravel

It inserts both table inside tags and tagables, what i want is just to insert into tagables ( junction ) table. Cause before it insert into tagables, theres code to check first if tag will insert into tags table already exist or not, if exist just grab the id. To make it simple to my problem. i just don't include code to check if tags is exist or not.
post model
public function tags(){ return $this->morphToMany( Tag::class, 'tagable', 'tagables', null, 'tag_id ); }
post controller
// tags table theres a row id 1 with name greeting
$post = Post::create( ['body' => 'Hello World'] );
$post->tags()->create( ['tag_id' => 1] );
Tables
// posts table
$table->mediumIncrements('post_id');
$table->string('body');
// tags table
$table->mediumIncrements('tag_id');
$table->string('tag_name');
//tagables table
$table->unsignedMediumInteger('tag_id');
$table->unsignedMediumInteger('tagable_id');
$table->string('tagable_type');

I think the simplest way do this to start by creating the tag with the eloquent method 'firstOrCreate', and then when you already have a new tag or existing tag you can add this tag to a new Post. The code may look like something like this:
class Tag extends Model
{
protected $guarded = [];
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable');
}
}
$tag = Tag::firstOrCreate(
['tag_name' => 'traveling'],
);
$post = $tag->posts()->create([
'body' => 'My new interesting post',
]);

Related

Laravel single blade file used for create and show

Is it possible and recommended that I have one lets say form.blade.php with html form file used for create new data and show existing data by ID.
I want to create this becouse file for insert and dispaly is the some. I want to avoid DRY.
Example: I have product categories, when I create a new category I need create.blade.php a file containing an html form. Now I want to use that same file to display the details of that category that will populate the fields in the fields by the given ID
Controller
// Create
public function create()
{
return view('admin.category.form');
}
// Show
public function show(Category $category)
{
$category = Category::find($category);
return view('admin.category.form', [
'category' => $category
]);
}
Or is it better to make a separate file for insert and separet file for show?
I read somewhere when you want to use same blade file then you can write in your create method as
public function create()
{
return view('admin.category.form',[
'category' => new Category()
]);
}

how to save multiple dropdownlist yii2

I'm trying to save multiple data from a dropdownlist, I have 2 tables Asistencia and Mecanico in the table Asistencia i have this in the _form
<?php
echo $form->field($model, 'mecanico_id[]')
->dropDownList(ArrayHelper::map(Mecanico::find()->all(), 'id_mecanico', 'nombre'),
[
'multiple'=>'multiple',
'class'=>'chosen-select input-md required',
]
)->label("Mecanicos");
?>
i know if i want to save multiple data i have to change in controllers-> actionCreate/Update but i dont know how. Here is my actionCreate
public function actionCreate()
{
$model = new Asistencia();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_asistencia]);
}
return $this->render('create', [
'model' => $model,
]);
}
I need sample controller code explaining how to save multiple items from a drop down list to the database, as well as update the list of saved items. Thanks.
here is my table of Asistencia
Asistencia table
Table of Mecanico
Mecanico table
and the relation of those 2 table
enter image description here
For example you have Product and Category many to many relation.
In your Product model,
Declare field:
public $categories_ids;
Put it in 'safe' in rules():
[['categories_ids'], 'safe']
3.Declare AfterSave function:
public function afterSave($insert, $changedAttributes) {
// If this is not a new record, unlink all records related through relationship 'categories'
if(!$this->isNewRecord) {
// We unlink all related records from the 'categories' relationship.
$this->unlinkAll('categories', true);
// NOTE: because this is a many to many relationship, we send 'true' as second parameter
// so the records in the pivot table are deleted. However on a one to many relationship
// if we send true, this method will delete the records on the related table. Because of this,
// send false on one to many relationships if you don't want the related records deleted.
}
foreach($this->categories_ids as $category_id) {
// Find and link every model from the array of ids we got from the user.
$category = Category::findOne($category_id);
$this->link('categories', $category);
}
parent::afterSave($insert, $changedAttributes);
}
Decare AfterFind function():
public function afterFind(){
parent::afterFind();
$this->categories_ids = ArrayHelper::getColumn($this->categories, 'id');
}
Declare relation:
public function getCategories() {
return $this->hasMany(Category::className(), ['id' => 'category_id'])->viaTable('product_category', ['product_id' => 'id']);
}
I hope it will help to you.

How to make shortest code?

I use the following code to insert multi array to database:
foreach($request->category as $k => $v){
$category[] = array(
"category_id" => $v,
"announcement_id" => $announcement->id
);
}
AnnouncementCategory::insert($category);
So, input data is POST array $request->category.
I need to refactoring this code
I tried this code:
$announcement->categories()->attach($request->category);
In model Announcement I have:
public function categories()
{
return $this->hasMany("App\AnnouncementCategory", "announcement_id", "id");
}
If you define in your Announcement model relationship like this:
public function categories()
{
return $this->belongsToMany(AnnouncementCategory::class);
}
you can do it like this:
$announcement->categories()->attach($request->category);
EDIT
I see you updated your question and added categories relationship. But looking at your code, AnnounceCategory is rather pivot table, so you should use belongsToMany as I showed instead of hasMany
You can do it in one line if the request matches the columns:
AnnouncementCategory::insert($request->all());
Then in your AnnouncementCategory model, make sure you declare the protected $fillable array where you specify which field could be populated.

How to update field when delete a row in laravel

Let I have a table named customer where customer table has a field named deleted_by.
I implement softDelete in customer model. Now I want to update deleted_by when row delete. So that I can trace who delete this row.
I do search on google about it But I don't found anything.
I use laravel 4.2.8 & Eloquent
You may update the field using something like this:
$customer = Customer::find(1); // Assume 1 is the customer id
if($customer->delete()) { // If softdeleted
DB::table('customer')->where('id', $customer->id)
->update(array('deleted_by' => 'SomeNameOrUserID'));
}
Also, you may do it in one query:
// Assumed you have passed the id to the method in $id
$ts = Carbon\Carbon::now()->toDateTimeString();
$data = array('deleted_at' => $ts, 'deleted_by' => Auth::user()->id);
DB::table('customer')->where('id', $id)->update($data);
Both is done within one query, softDelete and recorded deleted_by as well.
Something like this is the way to go:
// override soft deleting trait method on the model, base model
// or new trait - whatever suits you
protected function runSoftDelete()
{
$query = $this->newQuery()->where($this->getKeyName(), $this->getKey());
$this->{$this->getDeletedAtColumn()} = $time = $this->freshTimestamp();
$deleted_by = (Auth::id()) ?: null;
$query->update(array(
$this->getDeletedAtColumn() => $this->fromDateTime($time),
'deleted_by' => $deleted_by
));
}
Then all you need is:
$someModel->delete();
and it's done.
I would rather use a Model Event for this.
<?php
class Customer extends \Eloquent {
...
public static function boot() {
parent::boot();
// We set the deleted_by attribute before deleted event so we doesn't get an error if Customer was deleted by force (without soft delete).
static::deleting(function($model){
$model->deleted_by = Auth::user()->id;
$model->save();
});
}
...
}
Then you just delete it like you would normally do.
Customer::find(1)->delete();
I know this is an old question, but what you could do (in the customer model) is the following....
public function delete()
{
$this->deleted_by = auth()->user()->getKey();
$this->save();
return parent::delete();
}
That would still allow the soft delete while setting another value just before it deletes.

Laravel 4 - save tags

I have 3 tables:
posts => id, title, body, ...
tags => id, name, count
post_tag => post_id, tag_id
Post model has
public function tags() {
return $this->belongsToMany('Tag');
}
Tag model has
public function posts() {
return $this->belongsToMany('Post');
}
Selecting is working, but I want insert to DB
If new tag - insert to tags
Insert relation to post_tag
Increase tag count
For now I have
$post = new Post;
$post->title = Input::post('title');
$post->body = Input::post('body');
$post->save();
I have tags separated with ,. For example javascript, jquery, ajax.
How to do it? Explode tags and then check every tag if exist and then do 2 inserts (to tags and post_tag) or is there "magic" solution?
Have a look to this, it'll probably help you
Inserting related models
I think the function you need is attach. I've never used but I believe it's what you need. Have a look ;)

Resources