framework icon indicating copy to clipboard operation
framework copied to clipboard

withoutGlobalScope not working when model gets serialized

Open gepopp opened this issue 2 years ago • 7 comments

  • Laravel Version: 9.1
  • PHP Version: 8.1
  • Database Driver & Version: mysql

Description:

If i query a Model like so:

Contact::withoutGlobalScope( AccountScope::class )
                           ->without([ 'company', 'timetracks', 'customer_page' ])
                           ->where('id', $customer)
                           ->first();

and dump the result everything works as expected. But as soon as i chain the ->toJson() mehtod like:

Contact::withoutGlobalScope( AccountScope::class )
                           ->without([ 'company', 'timetracks', 'customer_page' ])
                           ->where('id', $customer)
                           ->first()
                           ->toJson();

the scope kicks in again.

So how can i prevent that the scope is added in serialization?

Steps To Reproduce:

gepopp avatar Dec 16 '22 06:12 gepopp

Thank you for reporting this issue!

As Laravel is an open source project, we rely on the community to help us diagnose and fix issues as it is not possible to research and fix every issue reported to us via GitHub.

If possible, please make a pull request fixing the issue you have described, along with corresponding tests. All pull requests are promptly reviewed by the Laravel team.

Thank you!

github-actions[bot] avatar Dec 16 '22 09:12 github-actions[bot]

Hey @gepopp can you please create a laravel repo that demos your problem? I would be glad to dig in if you do

abbood avatar Dec 21 '22 13:12 abbood

@abbood u mean a git repo here with a laravel installation? I think i will have time on the weekend.

gepopp avatar Dec 21 '22 14:12 gepopp

@gepopp I'm curious, does this work?

Contact::withoutGlobalScopes()
                           ->without([ 'company', 'timetracks', 'customer_page' ])
                           ->where('id', $customer)
                           ->first()
                           ->toJson();

abbood avatar Dec 21 '22 14:12 abbood

@gepopp I created this repo that reproduces your problem: https://github.com/abbood/laravel-sandbox/commit/b24b604fa1c1699815dfda4deb88961e8ebb8e2d

This is the data I have:

select * from contacts;
 id |     created_at      |     updated_at      | first_name | last_name | company | timetracks | customer_page
----+---------------------+---------------------+------------+-----------+---------+------------+---------------
  5 | 2022-12-21 14:13:03 | 2022-12-21 14:13:03 | abdullah   | bakhach   | toters  | 42342      |             1
  6 | 2022-12-21 14:14:00 | 2022-12-21 14:14:00 | mohammed   | skafi     | anghami | 23423425   |             2
  7 | 2022-12-21 14:15:19 | 2022-12-21 14:15:19 | taha       | miqati    | dtp     | 634543     |             2

and I noticed that withoutGlobalScope(AccountScope::class) doesn't work, but withoutGlobalScopes() does work:

> Contact::withoutGlobalScope(AccountScope::class)->where('id',7)->first();
= null

> Contact::withoutGlobalScopes()->where('id',7)->first();
= App\Models\Contact {#4887
    id: 7,
    created_at: "2022-12-21 14:15:19",
    updated_at: "2022-12-21 14:15:19",
    first_name: "taha",
    last_name: "miqati",
    company: "dtp",
    timetracks: "634543",
    customer_page: 2,
  }

abbood avatar Dec 21 '22 14:12 abbood

@abbood great to know, thanks!

But at the end it doesnt really solve my issue bcs. i've multiple scopes and i want to remove just one.

But knowing that withoutGlobalScopes() works helps allot! I guess some code duplication is forgivable at chrismas :)

gepopp avatar Dec 21 '22 14:12 gepopp

@gepopp my bad, it turns out that my above statement is misleading

> Contact::withoutGlobalScope(AccountScope::class)->where('id',7)->first();
= null

> AccountScope::class
= "AccountScope"

> use App\Models\Scopes\AccountScope

> AccountScope::class
= "App\Models\Scopes\AccountScope

> Contact::withoutGlobalScope(AccountScope::class)->where('id',7)->first();
= App\Models\Contact {#3582
    id: 7,
    created_at: "2022-12-21 14:15:19",
    updated_at: "2022-12-21 14:15:19",
    first_name: "taha",
    last_name: "miqati",
    company: "dtp",
    timetracks: "634543",
    customer_page: 2,
  }


> Contact::withoutGlobalScope(AccountScope::class)->where('id',7)->first()->toJson();
= "{"id":7,"created_at":"2022-12-21T14:15:19.000000Z","updated_at":"2022-12-21T14:15:19.000000Z","first_name":"taha","last_name":"miqati","company":"dtp","timetracks":"634543","customer_page":2}"

I figured this out by running this little experiment:

> $contact = Contact::where('id',5)->first();
= App\Models\Contact {#4537
    id: 5,
    created_at: "2022-12-21 14:13:03",
    updated_at: "2022-12-21 14:13:03",
    first_name: "abdullah",
    last_name: "bakhach",
    company: "toters",
    timetracks: "42342",
    customer_page: 1,
  }

> $contact->getGlobalScopes();
= [
    "App\Models\Scopes\AccountScope" => App\Models\Scopes\AccountScope {#3588},
  ]

So my mistake was that I was using the wrong scope string.

So far I cannot reproduce your bug where adding toJson() makes the scope kick back up again. If you can reproduce it yourself please do let me know! Enjoy your holidays :)

abbood avatar Dec 21 '22 15:12 abbood

Afaik from skimming through this again it seems withoutGlobalScopes is working as expected.

driesvints avatar Jan 19 '23 10:01 driesvints