Laravel Nova Metric displaying data from other metric - laravel

I have a two Nova Trend metrics called ApiCallsPerHour and ApiCallsPerMinute, each with a simple calculate function:
ApiCallsPerHour
public function calculate(NovaRequest $request)
{
return $this->countByHours($request, ApiCall::class);
}
ApiCallsPerMinute
public function calculate(NovaRequest $request)
{
return $this->countByMinutes($request, ApiCall::class);
}
The problem is the ApiCallsByMinute trend displays always displays the trend by hours.
I have tested and both components are loaded correctly: if I change their ranges array they independently update from each other. But whatever I put in the calculate method in the ApiCallsPerMinute, it always displays the hourly trend, even if I put return 100;.
Only when I remove the ApiCallsPerHour trend from the dashboard, the ApiCallsPerMinute is displayed correctly.
Both components do not have a value returned in the cacheFor method.

It was clear I was missing something big... These components had the same uriKey 🤦‍♂️. Don't copy paste your components folks, use the php artisan nova:trend command!

Related

How do I pass a value in my Route to the Controller to be used in the View in Laravel?

I have 2 entities called Match and Roster.
My Match routes are like this
http://localhost:8888/app/public/matches (index)
http://localhost:8888/app/public/matches/14 (show)
In order to view/create the teams for each specific match I added the routes for the match roster like this:
Route::get('/matches/'.'{id}'.'/roster/', [App\Http\Controllers\RosterController::class, 'index']);
Now I need that {id} i have in my URL to pass it to the Controller here:
public function index()
{
return view('roster.index');
}
I need that for a couple of things. First I need to do a search on the Roster table filtering by a column with that value, so I can display only the players that belong to that match.
Second, I need to pass it on to the view so I can use it on my store and update forms. I want to add or remove players from the roster from that same index view.
How can I do that?
#1 You can get the route parameter defined on ur routes via request()->route('parameter_name').
public function index()
{
// get {id} from the route (/matches/{id}/roster)
$id = request()->route('id');
}
#2 You can pass the data object via using return view(file_name, object)
public function index()
{
// get {id} from the route (/matches/{id}/roster)
$id = request()->route('id');
// query what u want to show
// dunno ur models specific things, so just simple example.
$rosters = Roster::where('match_id', '=', $id);
// return view & data
return view('roster.index', $rosters);
}
#3 It can be done not only index but also others (create, store, edit, update)
In addition, STRONGLY RECOMMEND learn Official Tutorial with simple example first.
Like a Blog, Board, etc..
You need to know essentials to build Laravel App.
Most of the time, I prefer named routes.
Route::get('{bundle}/edit', [BundleController::class, 'edit'])->name('bundle.edit');
In controller
public function edit(Bundle $bundle): Response
{
// do your magic here
}
You can call the route by,
route('bundle.edit', $bundle);

Eloquent model getRawOriginal() returns new values in `updating` observer

I need to compare original model values with changes that are done when update occurs, but I am not able to do that.
My model update code looks like this:
public function update(array $user, int $userId): ?bool
{
return User::find($userId)->update($user);
}
I thought that the best way to capture changes is to use observer and observe updating event, because I assume it's called right before changes are stored in the database. Here is updating method code:
public function updating(User $user)
{
Log::info('Original user', ['original' => $user->getRawOriginal('status')]);
}
I've tried logging a bit and it seems that updating method gets called after the update happens and then when I try to retrieve original model values there it returns new ones, instead of the original ones.
If I use getChanges() method in updating it returns exactly what has changed, so it seems that changes are tracked somehow, but not the original values?
Can someone give me any pointers how to solve this and explain to me why my approach doesn't work?
Update: Code, where I call update, is wrapped with DB transaction methods. After removing them it seems that updating method gets called at the right time and getRawOriginal then returns expected results.
In this case, what are my options? Is there a way to do what I want without removing transactions?
You can add boot method in your model .Both updating and updated trigger while updating .
protected static function boot()
{
parent::boot();
static::updating(function ($model){
echo "updating";
dump($model->getDirty());
dump($model->getRawOriginal('username'));
});
static::updated(function ($model){
echo "updated";
dump($model->getDirty());
dump($model->getRawOriginal('mobile_number'));
});
}

how to load different data tables in different tabs?

i am using laravel data tables to generate different data table on different tabs. but it runs only query of first data table rendered to the page.i already have attached scope to data table to generate different results for different condition
i have attached ajax() method to the data table that are not displayed in the beginning of the page
controller file
public function index(UpcomingReservationDataTable $UpcomingReservationDataTable)
{
return $UpcomingReservationDataTable->render('admin.reservations.index');
}
public function getAllReservationTable(ReservationDataTable $ReservationDataTable){
return $ReservationDataTable->render('admin.reservations.index');
}
public function getPastReservationDataTable(PastReservationDataTable $PastReservationDataTable){
return $PastReservationDataTable->addScope(new PastReservationScope)->render('admin.reservations.index');
}
pastreservationdatatable query
public function query(Reservation $model)
{
return $model->newQuery()->where('pickup_date','<',date('Y-m-d'))->orderBy('id','desc')->with('customer','package','vehicle');
}
You can show first table in load tab and next change it by ajax.
You must write a function in javascript. This function should take a value. This value contains your query information. When this is clicked on any tab, this function must be executed with that value. The function of this function is to send information to the server, receive and display. Did you do these things?
The next issue is when the Ajax data is sent, if the server path is wrong, you will encounter an error. To view errors on your browser, press the combination keys CTR + Shift + i and in the menu at the top of the window, select the console to display the errors.

Laravel Nova - Save multiple rows to database on create

I'm converting a Laravel app that was using Backpack across to Laravel Nova.
One of my models Images allows the user to add multiple images with a base set of information from the initial form. The form in this instance asks how many images are in the series via a dropdown and then has a number of relevant fields that will be used for all of the new images being added. When saving, in the controller, I'm using the following eloquent feature to run a number of tasks and insert the required number of rows:
public function store(StoreRequest $request){
//Get some info
//Make some tweaks
//Use for loop to save multiple records
for ($k = 0; $k < $addim; $k++){
//Do some stuff
parent::storeCrud(${"request"});
}
}
This works perfectly and inserts however many records are required.
In Laravel Nova, I can't see a way to use this same approach. Using an event listener in the model doesn't seem like the right way to save multiple records and I can't find any reference to a controller function I can use to achieve this.
I would really appreciate some thoughts and guidance on the best way to complete this part.
If someone has stumbled upon this type of problem.
You can use Laravel Observers.
In order to restrict the event to be fired only when resource is created and only using nova you can declare Observer in NovaServiceProvider.php as follows
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
parent::boot();
Nova::serving(function () {
Image::observe(ImageObserver::class);
});
}
Above code will only be triggered when your image object is modified using nova system only.
For ref Observer code will look like following
<?php
namespace App\Observers;
use App\Models\Document;
class ImageObserver
{
/**
* Handle the Image "created" event.
*
* #param \App\Models\Image $image
* #return void
*/
public function created(Image $image)
{
//logic to create multiple records
}
}
You can use the saving event in an observable
https://laravel.com/docs/5.8/eloquent#events

Adding Index to Laravel Scout Conditionally (Algolia)

I'm trying to add index to Algolia using Laravel Scout based on a condition. For example I have a Article model and I only want to add this article to Algolia if the article is active. My first approach was this:
public function toSearchableArray()
{
if($this->active) return $record;
return [];
}
this only adds the active records but still attempts to add empty arrays which is considered as Operation in algolia ( I will be charged for it). The second approach was to use shouldBesearchable() function from scout:
public function shouldBeSearchable()
{
if($this->active) return true;
return false;
}
This doesn't work with php artisan scout:import "App\Article". Has anyone faced a similar problem?
It was a bug in Laravel Scout, shouldBeSearchable is not release yet (on master branch) so you may experience some issue like this one.
Although, good news: it was just fixed by this PR.
https://github.com/laravel/scout/pull/250

Resources