Counting relations inside a loop - laravel

I have a many-to-many relationship between 'forms' and 'fields', on my intermediate table I have an additional column called 'order' so that I can edit the order of fields on a form.
I have this code for adding fields to forms. It takes an array of field ids and then loops through them and attaches them to the form. But once the fields are attached, the order is 0 for both of them when I dd?
I thought on the first iteration of the foreach, order would = 0 and on the second time it would = 1?
Assuming I was adding 2 fields to a form that didn't have any fields before.
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $field) {
$form->fields()->attach($field, ['order' => count($form->fields)]);
}
dd($form->fields()->get());
}

I recommend doing it like this:
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $order=>$field) {
$form->fields()->attach($field, ['order' => $order]);
}
}

After a bit more trial and error this seems to work.
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $field) {
$form->fields()->attach($field, ['order' => $form->fields()->count()]);
}
}

try this here:
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $field) {
$form->fields()->attach($field, ['order' => $form->fields()->get()->count()]);
}
}

Related

Laravel Scout map in toSearchableArray relationship fields

Is it possible to map in toSearchableArray relationship fields as well. What I mean, having User model I try to search in related model fields as well like;
/**
* Get the indexable data array for the model.
*
* #return array
*/
public function toSearchableArray()
{
return [
'name' => $this->name,
'plz' => $this->account->zip,
];
}
/**
* #return HasOne
*/
public function account(): HasOne
{
return $this->hasOne(Member::class);
}
In controller searching after results
if($request->has('s')) {
$founds = User::search($request->get('s'))->get();
}
will throw Attempt to read property "zip" on null
I do not really find any infos in documentation related to this question
I do have two ways to do it of which I consider one of them as crude.
Method 1:
Here's an example implementation where you're searching all of one model and then a relationship (accounts)
public function toSearchableArray()
{
$array = $this->toArray();
$array = $this->transform($array);
$array['country'] = $this->countries->map(function ($data) {
return $data['name'] ?? '';
})->toArray();
return $array;
}
Method 2:
public function toSearchableArray()
{
$array = $this->toArray();
// Customize array...
$array = [
'user_name' => $this->user_name,
'country' => $this->getCountryNameById($this->country_id),
...
];
return $array;
}
where relationship is defined in helpers or you can make a separate trait and import it in model with method.
Here relationship for country is defined within the model as
//Get Country name By id
function getCountryNameById($id) {
$country = \App\Country::select('name')->find($id);
return $country->name ?? '';
}

Method Illuminate\Database\Eloquent\Collection::salarylevels does not exist

I have a many to many relationship between users and salary_levels. All I have is an error stating Method Illuminate\Database\Eloquent\Collection::salarylevels does not exist. The salarylevels method is defined under User model. How could this happen?
User Model:
public function salarylevels(){
return $this->belongsToMany(SalaryLevel::class)->withPivot(['leave_entitlement']);
}
SalaryLevel:
public function users(){
return $this->belongsToMany(User::class)->withPivot(['leave_entitlement']);
}
Store Method:
public function store(Request $request) {
$users = User::where('id',$request->input('employee_id', []))->get();
$Ids = [
1 => ['leave_entitlement' => '30'],
3 => ['leave_entitlement' => '22']
];
$users->salarylevels()->sync($Ids);
}
Your issue is that $users->salaryLevels() is not correct. $users is a Collection because you have done:
$users = User::where('id', $request->input('employee_id', []))->get();
get() returns a Collection, so you should do:
$users = User::where('id', $request->input('employee_id', []))->first();

Laravel: getting data from index method in a controller with pagination or without pagination

I am using paginate() method to get paginated data in index method in controller but sometimes I need whole data so I wrote code like this.
public function index(Request $request)
{
if ($request->page === 'all') {
$posts = Post::all();
} else {
$posts = Post::paginate(10);
}
return response([
'posts' => $posts
], Response::HTTP_OK);
}
So if I want to get all data I send page value as all.
If I want paginated data I send page value as integer.
It works fine but just wondering if there are any other better way to do this?
You can further simplify the code you're using.
public function index(Request $request)
{
$page = $request->page;
return response([
'posts' => $page === 'all' ? Post::all() : Post::paginate($page)
], Response::HTTP_OK);
}
Avoid load several time of model instance.
public function index(Request $request)
{
$post = Post::query();
$data = ($request->page === 'all') ? $post : $post->paginate(10);
return response()->json(['posts' => $data], 200);
}

Create new Post with default Category belongsToMany

I have a Post/Category manyToMany relations and would like to be able to attach a default category named "Uncategorised" to each new post that is created. How can I do that? A BelongsToMany method only works on the Details page, not on Create page.
BelongsToMany::make(__('Categories'), 'categories', Category::class),
You can also set default value to your database field so that you can omit passing category and will be taken default to Uncategorised like if you are using MySQL you can do it this way by creating migration
$table->text('category')->default(0);
Because the BelongsToMany not show on mode create in Post Nova model. So we have to make our custom Select, by add this code to your fields:
public function fields(Request $request)
{
if($request->editMode=="create"){
$categories = \App\Category::get(['id','name']);
$options = [];
foreach($categories as $value){
$options[$value->id] = $value->name;
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
Select::make('Categories', 'category_id')
->options($options)
->displayUsingLabels()
->withMeta(['value' => 1]) // 1 = id of Uncategorised in categories table
];
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
BelongsToMany::make('Categories','categories')->display('name'),
];
}
Don’t forget relationship function in both, Post and Category model:
class Post extends Model
{
public function categories(){
return $this->belongsToMany(Category::class, 'category_post', 'post_id', 'category_id');
}
}
And:
class Category extends Model
{
public function posts(){
return $this->belongsToMany(Post::class,'category_post', 'category_id', 'post_id');
}
}
Then, custom the function process the data on mode Create of Post resource page, it’s at nova\src\Http\Controllers\ResourceStoreController.php, change function handle to this:
public function handle(CreateResourceRequest $request)
{
$resource = $request->resource();
$resource::authorizeToCreate($request);
$resource::validateForCreation($request);
$model = DB::transaction(function () use ($request, $resource) {
[$model, $callbacks] = $resource::fill(
$request, $resource::newModel()
);
if ($request->viaRelationship()) {
$request->findParentModelOrFail()
->{$request->viaRelationship}()
->save($model);
} else {
$model->save();
// your code to save to pivot category_post here
if(isset($request->category_id)&&($resource=='App\Nova\Post')){
$category_id = $request->category_id;
$post_id = $model->id;
\App\Post::find($post_id)->categories()->attach($category_id);
}
}
ActionEvent::forResourceCreate($request->user(), $model)->save();
collect($callbacks)->each->__invoke();
return $model;
});
return response()->json([
'id' => $model->getKey(),
'resource' => $model->attributesToArray(),
'redirect' => $resource::redirectAfterCreate($request, $request->newResourceWith($model)),
], 201);
}
}
All runs well on my computer. A fun question with me! Hope best to you, and ask me if you need!
What I ended up doing was saving the data on Post Model in boot().
public static function boot()
{
parent::boot();
static::created(function (Post $post) {
$post->categories()->attach([1]);
});
}

how to add extra data into create method with laravel

public function store(Request $request) {
$user = Book::create([
'user_id' => auth()->id(),
'name => $request->name,
'year => $request->year
)];
}
The above code is able to store into Database.
I want to know how to add below extra data TOGETHER.
I found out that merge was not working as it is not collection.
Tried to chain but was not working.
public function data() {
$array = [
'amount' => 30,
'source' => 'abcdef',
];
return $array;
}
You can catch create Event in Model.
This code may can help you.
/**
* to set default value in database when new record insert
*
*/
public static function bootSystemTrait()
{
static::creating(function ($model) {
$model->amount = 30;
});
}
You can write this code into your model. It will execute every time when you create record using Laravel model.
If you want to modify it you can use property into Model class. Something like this:
class TestClass extends Model
{
public static $amount = 0;
static::creating(function ($model) {
$model->amount = self::$amount;
});
}
Good Luck.

Resources