Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to add a custom stacktrace parsing method #1585

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

OzanKurt
Copy link

Hello there,

I use https://github.com/yajra/laravel-datatables package in almost all of my projects.

I currently have a problem of seeing the source of the queries inside my DataTable classes.

For example:

I have a query builder setup inside my UsersDataTable.

    public function query()
    {
        return User::query();
    }

Since this function only starts to bulid the query it doesn't show up in debug_backtrace().

For this I've added a solution which allows me to check the "query sender" object and modify how the $frame was filled.

I've added simple static method to add my custom callables to QueryCollector, in there I can modify and return the $frame as I wish in case the $trace['object'] is matching my first parameter $objectType.

Here is an example DataTable::class query tracer.

QueryCollector::addCustomFrameParser(DataTable::class, function (object $frame, array $trace) {
    // Remove the 'App\' prefix from the namespace
    $relativeNamespace = str_replace('App\\', '', $trace['object']::class);

    // Convert namespace to a directory path
    $directoryPath = str_replace('\\', DIRECTORY_SEPARATOR, $relativeNamespace);
    $filePath = app_path($directoryPath) . '.php';

    // Get the file path inside the project from the class object
    $frame->file = $filePath;

    return $frame;
});

After I add this to my AppServiceProvider, I can simply see the change inside my "Query" tab.

Before:
image

After:
image

This way I can simply tell where I built the query and continue debugging/development.

Hello there,

I use https://github.com/yajra/laravel-datatables package in almost all of my projects.

I currently have a problem of seeing the source of the queries inside my DataTable classes.

For example:

I have a query builder setup inside my `UsersDataTable`.

```php
    public function query()
    {
        return User::query();
    }
```

Since this function only starts to bulid the query it doesn't show up in `debug_backtrace()`.

For this I've added a solution which allows me to check the "query sender" object and modify how the `$frame` was filled.

I've added simple static method to add my custom callables to `QueryCollector`, in there I can modify and return the `$frame` as I wish in case the `$trace['object']` is matching my first parameter `$objectType`.

Here is an example `DataTable::class` query tracer.

```php
QueryCollector::addCustomFrameParser(DataTable::class, function (object $frame, array $trace) {
    // Remove the 'App\' prefix from the namespace
    $relativeNamespace = str_replace('App\\', '', $trace['object']::class);

    // Convert namespace to a directory path
    $directoryPath = str_replace('\\', DIRECTORY_SEPARATOR, $relativeNamespace);
    $filePath = app_path($directoryPath) . '.php';

    // Get the file path inside the project from the class object
    $frame->file = $filePath;

    return $frame;
});
```

After I add this to my `AppServiceProvider`, I can simply see the change inside my "Query" tab.

Before:
IMG HERE

After:
IMG HERE
@parallels999
Copy link
Contributor

Did you try adding PATH_TO_FILE/DataTablesController.php to options.db.backtrace_exclude_paths?
I have a bridge query builder, and I had a similar problem,
I added the file_path to the backtrace_exclude_paths and I already got the correct file

'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)

@OzanKurt
Copy link
Author

OzanKurt commented Mar 22, 2024

Yes I tried, but since the query is NOT actually sent from the UsersDataTable PHP's debug_backtrace() only detects the call from: DataTablesController.php

Also here is how mine looks like usually:

'backtrace_exclude_paths' => [
    '/vendor/yajra/laravel-datatables',
    '/vendor/staudenmeir',
],

@PaolaRuby
Copy link
Contributor

PaolaRuby commented Mar 22, 2024

Post Before\After with backtrace
image
Maybe there could be a simpler way

@OzanKurt
Copy link
Author

Before:
image

After:
image

@PaolaRuby
Copy link
Contributor

extends UsersDataTable some yajra class?? or uses some yajra trait?

@OzanKurt
Copy link
Author

It extends the DataTable class from the package.

@PaolaRuby
Copy link
Contributor

I think it could be made more native,
maybe some "demo minimal app" to find another approach?

@OzanKurt
Copy link
Author

I can make a demo next week, the change is actually very minimal anyway.

@OzanKurt
Copy link
Author

OzanKurt commented Mar 22, 2024

I actually already pushed a demo to GitHub.

https://github.com/OzanKurt/debugbar-demo

You can simply pull and run with php artisan serve.

After you install the app you can simply open these two pages:

http://127.0.0.1:8000/?custom_parsing=true
http://127.0.0.1:8000/?custom_parsing=false

replace the contents of QueryCollector and check it out.

@erikn69
Copy link
Contributor

erikn69 commented Mar 22, 2024

This removes a step from the trace, I'm going to try another approach
Try #1588

@OzanKurt
Copy link
Author

So you suggest adding an extra source to the trace instead of modifying its file...

I'm fine with that approach as well.

One thing to add maybe would be the custom source parsing:

So instead of

if (($trace['class'] ?? null) == 'Yajra\DataTables\Services\DataTable') {

looping through an array of customs would be nicer

foreach (static::$customSourceParsers as $objectType => $customSourceParser) {
    if (isset($trace['object']) && is_a($trace['object'], $objectType)) {

@erikn69
Copy link
Contributor

erikn69 commented Mar 22, 2024

QueryCollector::addCustomFrameParser(DataTable::class, function (object $frame, array $trace) {
// Remove the 'App' prefix from the namespace
$relativeNamespace = str_replace('App\', '', $trace['object']::class);

I try to avoid that, not everyone has the knowledge to do that customization, and not all cases can be solved in that way
the way I add it would be ready to use
but @barryvdh decides

@OzanKurt
Copy link
Author

Why not add both, so people with the knowledge to customize can do it without needing a PR process.

@barryvdh
Copy link
Owner

barryvdh commented Apr 1, 2024

I'm not really sure about this, not seeing this in my own datatables. Don't want to complicate the backtrace too much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants