kokoshneta's avatar

Tinker: How to continue using after outputting large object?

Tinker is an excellent tool, but there’s one enormous drawback to it that I can’t seem to find a way to get around. If you do this:

>>> $x = MyModel::find(123);

Then Tinker will immediately output the entire model, with any loaded relations. This can use up a lot of lines, and if the object representation is longer than what can comfortably fit in the terminal window with no browsing, you end up with the result cut off, a single line consisting of just one colon : at the bottom. You then need to hit enter to reveal more lines – one line at a time.

This is sort of annoying (my terminal scrolls just fine, so this ’80s-ish behaviour is useless), but what’s really annoying is that once you load all the lines, Tinker stops working.

When all lines are displayed, you get this:

// model contents here
}

(END)

The >>> prompt is gone, and I can find no way to get it back. Every time a large model is output, I have to restart Tinker completely.

I’m guessing this behaviour is probably inherited from PsySH, but their documentation doesn’t seem to contain any hints on how to change it either.

Is there some way to 1) get Tinker to just output everything at once, without needing to hit enter for each line that won’t fit on screen; or alternatively 2) get the prompt back after hitting enter however many times is needed?

0 likes
13 replies
kokoshneta's avatar

*bump*

No one has any idea how to get around this?

webrobert's avatar

Haven't experienced this. Though I'm not a huge tinker user. Trying to see if I can duplicate it. What do you use for terminal? I use oh-my-zsh.

Loaded this works fine... Longer than that?

Project::find(1)->load('users')
= App\Models\Project {#5100
    id: 1,
    name: "Hirthe-Kunde",
    description: "Placeat asperiores maxime possimus quos neque accusantium.",
    start_date: "2022-12-20",
    end_date: "2023-01-26",
    tenant_id: 1,
    created_by: 2,
    pinned: 0,
    status: 1,
    access: 3,
    archived_at: null,
    created_at: "2022-12-06 00:25:00",
    updated_at: "2022-12-28 13:12:29",
    users: Illuminate\Database\Eloquent\Collection {#5102
      all: [
        App\Models\User {#5116
          id: 1,
          name: "Robert Wayne",
          title: null,
          time_zone: "America/Los_Angeles",
          username: "webrobert",
          email: "[email protected]",
          email_verified_at: null,
          #password: "y$O2JQoFZvF5oKC/Op4yfCzOxy8iBbJFwSv/YGNbaxs5QTSF1I0SHZq",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: null,
          role_id: 6,
          company_id: null,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:12",
          updated_at: "2022-12-28 12:26:12",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5115
            project_id: 1,
            user_id: 1,
            type: "2",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/1ea03b3d85fa94b16cf7f256a554a457?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FR+W%2F100%2FBBBBBB%2F333333",
        },
        App\Models\User {#5117
          id: 2,
          name: "Mary Owner",
          title: null,
          time_zone: "America/Fortaleza",
          username: "aurelia01",
          email: "[email protected]",
          email_verified_at: "2022-12-28 12:26:12",
          #password: "y$BR1wC1mOY4IAICd5iGRv2OmkTgcRfqHHSiEVAxFcAnXQPoAIWKx5G",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: "qEe3CeLNSC9Ba79mhRmdduWUMJlkzAUsbHgaKgxcprtgV0S15aKDWB4Putmq",
          role_id: 5,
          company_id: 1,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:13",
          updated_at: "2022-12-28 12:26:13",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5114
            project_id: 1,
            user_id: 2,
            type: "2",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/6aa07924c821ca580c4bd04a45918d4f?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FM+O%2F100%2FBBBBBB%2F333333",
        },
        App\Models\User {#5118
          id: 4,
          name: "Joe Company",
          title: null,
          time_zone: "Africa/Luanda",
          username: "ustehr",
          email: "[email protected]",
          email_verified_at: "2022-12-28 12:26:12",
          #password: "yk4OQ7OkmLoHIdh5MWnA/uwlvyOlIQNTwKJhOD85ViZwRMZWu.weC",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: "kBYEphbSWT",
          role_id: 3,
          company_id: 3,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:13",
          updated_at: "2022-12-28 12:26:13",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5112
            project_id: 1,
            user_id: 4,
            type: "1",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/eb7327d025dee350d21167235d0b715e?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FJ+C%2F100%2FBBBBBB%2F333333",
        },
        App\Models\User {#5119
          id: 5,
          name: "Tommy Collaborator",
          title: null,
          time_zone: "Europe/Ulyanovsk",
          username: "macejkovic.gwen",
          email: "[email protected]",
          email_verified_at: "2022-12-28 12:26:12",
          #password: "y$gU48E4VBffKMeeZhzfCVsekIrOyWrKMFDhS9UvsH2mclayjHTj3oi",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: "aKmksmSSlv",
          role_id: 2,
          company_id: 4,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:13",
          updated_at: "2022-12-28 12:26:13",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5111
            project_id: 1,
            user_id: 5,
            type: "2",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/bb21d490cce8bf780120f60e996ce71f?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FT+C%2F100%2FBBBBBB%2F333333",
        },
        App\Models\User {#5120
          id: 6,
          name: "Jane Client",
          title: null,
          time_zone: "Europe/Helsinki",
          username: "hertha.dach",
          email: "[email protected]",
          email_verified_at: "2022-12-28 12:26:12",
          #password: "y$cT0xiGNvfP1Wu5QRqJZ.neXqvyqrybvk5ppMggV.2PRTXglPbw2S2",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: "2DCIPGomlh",
          role_id: 1,
          company_id: 5,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:13",
          updated_at: "2022-12-28 12:26:13",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5110
            project_id: 1,
            user_id: 6,
            type: "1",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/c5cb77726d521139d57d32c2a506de7b?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FJ+C%2F100%2FBBBBBB%2F333333",
        },
        App\Models\User {#5121
          id: 7,
          name: "Michele Paucek",
          title: null,
          time_zone: "Europe/Belgrade",
          username: "gdare",
          email: "[email protected]",
          email_verified_at: "2022-12-28 12:26:13",
          #password: "yfrIHKUSSiE/hUY2POoxeHalJZbQXH047TrXXo.kktMQpuQ76Olu",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: "8dEO0JVhkl",
          role_id: 3,
          company_id: 6,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:13",
          updated_at: "2022-12-28 12:26:13",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5108
            project_id: 1,
            user_id: 7,
            type: "1",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/4f5011bc72938be683110dc9c7478c06?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FM+P%2F100%2FBBBBBB%2F333333",
        },
        App\Models\User {#5122
          id: 8,
          name: "Keely Adams",
          title: null,
          time_zone: "America/Mexico_City",
          username: "dooley.jerrell",
          email: "[email protected]",
          email_verified_at: "2022-12-28 12:26:13",
          #password: "y$NS.Z/0y79yboUDuc1ML7VO66QREGxcJ2zJc8U2qveN.prnm8BCBxK",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: "AwVpBH40c94HFFImzEaEwx1nqv0Lb9YxkxUXOoJL7Hv2m4FPaRWtpK8CgARG",
          role_id: 2,
          company_id: 7,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:13",
          updated_at: "2022-12-28 12:26:13",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5107
            project_id: 1,
            user_id: 8,
            type: "1",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/5482651e11ec4ab02684b51d0301a8f9?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FK+A%2F100%2FBBBBBB%2F333333",
        },
        App\Models\User {#5123
          id: 11,
          name: "Marquise Huel",
          title: null,
          time_zone: "America/Asuncion",
          username: "jacobson.leatha",
          email: "[email protected]",
          email_verified_at: "2022-12-28 12:26:13",
          #password: "y$JMxlP52cDjxx2jQ7iQ3tNOocCF5c7kl5FPXIoHUWv22Y3StYjEKVS",
          #two_factor_secret: null,
          #two_factor_recovery_codes: null,
          two_factor_confirmed_at: null,
          #remember_token: "mi2WKPysXv",
          role_id: 2,
          company_id: 10,
          tenant_id: 1,
          current_team_id: null,
          profile_photo_path: null,
          created_at: "2022-12-28 12:26:13",
          updated_at: "2022-12-28 12:26:13",
          pivot: Illuminate\Database\Eloquent\Relations\Pivot {#5109
            project_id: 1,
            user_id: 11,
            type: "2",
          },
          +profile_photo_url: "https://www.gravatar.com/avatar/73491006922ccfe11b5ff5015f7cfb6b?s=200&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FM+H%2F100%2FBBBBBB%2F333333",
        },
      ],
    },
  }
kokoshneta's avatar

@webrobert I just use the default ZSH shell that comes with macOS. It happens both in the terminal built into VSCode and in iTerm, though.

The object you just posted there is much longer than what’s needed to trigger it for me. I’m on my laptop now, so the terminal window isn’t very tall; anything more than about 15–20 lines will do it.

jivanrij's avatar

I don't have a specific fix for your problem. But maybe an alternative.

php artisan make:command TestItCommand

Then add that file in your .gitignore and give it a signature like 'test-it'.

Test your code in that file. This is much faster than on CLI. You can also easily read through the objects.

Personally, I prefer this above working with tinker because you will always get the recent version of the code without needing to restart tinker.

You could check out Ray, it's a debug app built by Spatie. you could use it like dd(), but then do ray(). Then it shows you the data. Default 'closed', but you can click through it, just like js objects in the debug console of your browser.

https://spatie.be/docs/ray/v1/introduction

kokoshneta's avatar

@jivanrij I have looked at Ray before, but can’t justify the cost of an annual licence for a debugger.

Making a test command seems like it would be a lot less efficient for the kind of things I use Tinker for. The advantage of Tinker is that it’s interactive, allowing you do whatever you want and immediately see the result.

I do already have and use various testing routes that just output stuff in the browser, which seems like it would be fairly equivalent to the Artisan test command way of doing things. Every time you want to test something new, you need to update and save a file, then run the command/refresh the page. That’s fine if it’s a larger, more complex debugging test, but it doesn’t replicate the immediate interactivity of Tinker that’s so useful for other situations.

psrz's avatar

@kokoshneta

Not what you ask, but for what it's worth, I use a similar approach to @jivanrij's . I have a routes/console.test.php (on .gitignore obviously) which gets loaded on local env (if exists).

I find it very convenient to test the services/actions I'm writing, or whatever I need.

Tinker is great, but it doesn't have intelisense (I use PHPStorm, so it's a big loss in comparisson).

But the deal breaker for me is that any change you do to your code, you have to exit the console, restart the console and set again every object / variable you had before. That's a major pain in the butt. If I'm using some console command all I have to do test again is "arrow up" , "enter" and that's it.

sean-oreilly's avatar
Level 2

To get the >>> prompt back, you just need to press 'q'. Haven't found a good way to get around the ':' behaviour in general though . . .

8 likes
kokoshneta's avatar

@sean-oreilly I actually discovered this a while ago, but must have forgotten to update the thread – thanks for reminding me!

The reason this happens at all is that Tinker (or PsyH, or perhaps the underlying terminal itself, I’m not sure) sometimes passes output through less instead of just outputting it via stdout (or whatever it does normally).

You can use the G command inside less to jump to the last line, which I think solves the slow scrolling issue.

hybridstorm's avatar

Noting this here since google leads you to this thread when searching for this... You may have to press "Q" vs "q" to go right back to the prompt. Lowercase q does not work for me.

1 like
jmason81's avatar

Still trying to find an answer to this nagging problem. q takes me out of tinker entirely, and Q says undefined constant. I just want to get from the > output back to the tinker entry line where I can put in another command. Super frustrating.

kokoshneta's avatar

@jmason81 That seems rather odd. q certainly doesn’t take me out of Tinker entirely. The manual I linked to in my comment above says that the command to exit Less is “q or Q or :q or :Q or ZZ” – have you tried any of the others on that list?

Carlos-isid's avatar

Hey, i don't like the less pagination, so to get back the old prompt, just create a file named .psysh.php with the following content:

<?php

return [
    'pager' => false,
];

it will turn off pagination in tinker.

1 like

Please or to participate in this conversation.