How to debug/view SQL requests with Laravel / Laragon - laravel

My question is very simple but I have no clue: I have always been working with java and eclipse or C# until now so it's a "new world" :)
How can I debug my laravel code?
I am using laravel and vuejs. I start my server with laragon, and I use VScode. I have tried starting it from VScode (added xdebug dll in laragon) but it doesn't give me more info, and I don't manage to debug anything using breakpoints:
{
"name": "Launch localhost",
"type": "chrome",
"request": "launch",
"url": "http://127.0.0.1/",
"webRoot": "C://laragon//www//projet"
},
{
"name": "Launch index.php",
"type": "chrome",
"request": "launch",
"file": "C://laragon//www//projet//index.php"
},
When I get an error with sql, all I get is
app.js:651 Uncaught (in promise) Error: Request failed with status code 500
at createError (app.js:651)
at settle (app.js:814)
at XMLHttpRequest.handleLoad (app.js:184)
How can I see my SQL request and get the "real error"?
And how can I properly debug?
Thanks a lot in advance.

You have multiple options to achieve the SQL logging:
1.Use query listener by registering it in service provider (boot method as follow)
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
use DB;
use Log;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Schema::defaultStringLength(191);
DB::listen(function($query) {
Log::info(
$query->sql,
$query->bindings,
$query->time
);
});
}
}
Use Query logging please refer to https://laravel.com/docs/5.0/database#query-logging
Use laravel debugger package please refer to https://github.com/barryvdh/laravel-debugbar
You can debug php with xdebug but i would still prefer any option among above 3.

You can use Laravel Debugbar to see the real time queries. It provides many other useful information for debugging purpose. Please check this link https://github.com/barryvdh/laravel-debugbar
Also try to log the collection into SQL using query listener by registering it inside service provider:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Log;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
Log::useDailyFiles(storage_path().'/logs/query_log.log');
$query = $query->sql;
Log::info($query);
});
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}

Related

Can not get access to Telescope dashboard

I want to add telescope into my laravel 8 app, but having in .env
APP_ENV=local
TELESCOPE_ENABLED=true
and reading at site :
https://laravel.com/docs/8.x/telescope
The Telescope dashboard may be accessed at the /telescope route. By default, you will only be able to access this dashboard in the local environment.
on url
http://local-tads.com/telescope
I got 404 error, where http://local-tads.com - is local hosting of my app
In app/Providers/AppServiceProvider.php file I added lines :
<?php
namespace App\Providers;
class AppServiceProvider extends ServiceProvider
...
if ($this->app->environment('local')) {
$this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
\Event::listen(
[
TransactionBeginning::class,
],
function ($event) {
...
I have unmodified vendor/laravel/telescope/config/telescope.php file.
Have I to add route in routes/web.php and in which way ?
How to get access to telescope dashboard ?
UPDATED BLOCK :
I run both commands :
php artisan telescope:install
php artisan migrate
But I did not find config/telescope.php, so I copied it from /vendor/ subdirectory
Running command
php artisan route:list
has no any “telescope” entry.
In file app/Providers/AppServiceProvider.php I added lines with telescope :
<?php
namespace App\Providers;
use App\Library\Services\AdminCategoryCrud;
//use App\Providers\TelescopeServiceProvider;
use Illuminate\Database\Events\TransactionBeginning;
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Database\Events\TransactionRolledBack;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\TelescopeServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
if ($this->app->environment('local')) {
$this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
$this->app->register(TelescopeServiceProvider::class);
}
Not sure if all is correct?
in env I have :
APP_ENV=local
TELESCOPE_ENABLED=true
and in composer.json I added line :
"extra": {
"laravel": {
"dont-discover": [
"laravel/telescope"
]
}
},
and updated composer
But http://local-tads.com/telescope - still raise 404 error...
Thanks in advance!
I have this problem but I attention Laravel Documentation I watch this code and run them:
telescope:install
, you should remove the
TelescopeServiceProvider
service provider registration from your application's
config/app.php
configuration file. Instead, manually register Telescope's service providers in the
register
method of your
App\Providers\AppServiceProvider
class.
A potential answer to your problem could be removing the telescope package from the dont-discover array. So your new extra section would be like this one:
"extra": {
"laravel": {
"dont-discover": []
}
}
Also, don't forget to dump your autoload by running composer dump-autoload in your project folder. I hope this helps you :D
For more information please check this issue on the github repository.

Laravel Passport and Heroku where to store encryption keys?

I am trying to deploy a Laravel application, which uses Laravel Passport, with Heroku.
Everytime the app is deployed the slug is rebuilt causing the Laravel Passport encryption keys to be erased. It means everytime the app is deployed:
the storage folder permissions should be changed
new encryption keys should be generated
all existing tokens would be undecryptable
For now, the solution I ended up with is to store the OAuth private and public keys in two different Heroku config variables (a.k.a. environment variables). And I extended the PassportServiceProvider class so it looks for the encryption keys in environment variables if the environment is set to "production":
I created a new PassportServiceProvider class in app/Providers:
<?php
namespace App\Providers;
use Laravel\Passport\PassportServiceProvider as LaravelPassportServiceProvider;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\ResourceServer;
class PassportServiceProvider extends LaravelPassportServiceProvider
{
protected function registerResourceServer()
{
$publicKeyPath = config('app.env') === 'production' ? env('OAUTH_PUBLIC_KEY') : 'oauth-public.key';
$this->app->singleton(ResourceServer::class, function () use ($publicKeyPath) {
return new ResourceServer(
$this->app->make(\Laravel\Passport\Bridge\AccessTokenRepository::class),
$this->makeCryptKey($publicKeyPath)
);
});
}
public function makeAuthorizationServer()
{
$privateKeyPath = config('app.env') === 'production' ? env('OAUTH_PRIVATE_KEY') : 'oauth-private.key';
return new AuthorizationServer(
$this->app->make(\Laravel\Passport\Bridge\ClientRepository::class),
$this->app->make(\Laravel\Passport\Bridge\AccessTokenRepository::class),
$this->app->make(\Laravel\Passport\Bridge\ScopeRepository::class),
$this->makeCryptKey($privateKeyPath),
app('encrypter')->getKey()
);
}
protected function makeCryptKey($key)
{
if (config('app.env') === 'production') {
return new CryptKey(str_replace('\n', "\n", $key), null, false);
}
return new CryptKey(file://'.Passport::keyPath($key), null, false);
}
}
Append the following line to the providers array in config/app.php:
Api\Providers\PassportServiceProvider::class,
Tell Laravel to not auto-discover the Laravel Passport package. in composer.json:
"extra": {
"laravel": {
"dont-discover": [
"laravel/passport"
]
}
}
This solution is not fully functional on its own because of this issue.
But I am not convinced it is the right way to do it. I wonder if someone already faced the problem. If so how did you solve it?
Thank you in advance.

Private channel not working with Laravel echo server

I'm getting this JS error on the console:
app.js:167 Uncaught ReferenceError: receiverId is not defined
Here is my complete code:
PrivateChatController:
event(new PrivateMessageEvent($chat, $receiverId));
PrivateMessageEvent:
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\User;
use App\PrivateChat;
class PrivateMessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $privateChat, $receiverId;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(PrivateChat $privateChat, $receiverId)
{
$this->privateChat = $privateChat;
$this->receiverId = $receiverId;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('private-chat.' . $this->receiverId);
}
}
Bootstrap.js
import Echo from "laravel-echo"
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
window.Echo.private(`private-chat.${receiverId}`)
.listen('PrivateMessageEvent', (e) => {
console.log(e);
});
channels.php
Broadcast::channel('private-chat.{receiverId}', function ($user, $receiverId) {
return true; // this is just for debugging to allow anyone to listen on this channel
//return $user->id === $receiverId;
});
laravel-echo-server.json
{
"authHost": "http://localhost",
"authEndpoint": "/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {},
"sqlite": {
"databasePath": "/database/laravel-echo-server.sqlite"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": ""
}
In background queue:work and laravel-echo-server are already running
Upon firing that event, I'm getting this message on the laravel-echo-server console:
Channel: private-private-chat.
Event: App\Events\PrivateMessageEvent
CHANNEL private-private-chat.
Notes:
I'm successfully able to listen to the public channel. The only issue with the private channel.
Using latest Laravel version i.e 5.4
I have done all the things as per the official docs:
https://laravel.com/docs/master/broadcasting
https://github.com/tlaverdure/laravel-echo-server
I have also raised issue on github repo:
https://github.com/tlaverdure/laravel-echo-server/issues/158
I have spent more than 10 hours and tried everything I could, but no luck.
Thanks
You can set REDIS_PREFIX to NULL to remove the prefix else if it has a value then you must set keyPrefix in the echo server config.
If REDIS_PREFIX = NULL then do not add keyPrefix.
Important Notice
When using broadcastAs(), the call to listen('') call must start with a DOT
At this moment the behavior when keyPrefix is used is unknown, if you use the prefix settings, please comment on the outcome of the DOT requirement.
https://laravel.com/docs/6.x/broadcasting#broadcast-name
public function broadcastAs()
{
return 'server.created';
}
.listen('.server.created', function (e) {
....
});
I would check the DOT + PREFIX combo my self but I feel Laravel Echo is going to give me a heart attack if I work on it any longer.
If you do not use broadcastAs() then the naming will fallback to the event class name, in this case there is no DOT prefix injected, see the setup below:
laravel-echo-server.json
{
"host": "127.0.0.1",
"port": "6001",
"protocol": "http",
"database": "redis",
"databaseConfig": {
"redis": {
"host": "127.0.0.1",
"port": 6379,
"db": 0,
"keyPrefix": "VALUE OF REDIS_PREFIX"
}
}
/app/Events/MyExample.php
<?php
namespace App\Events;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class MyExample implements ShouldBroadcastNow
{
private $id;
public $payload;
public function __construct($id, $payload)
{
$this->id = $id;
$this->payload = $payload;
}
public function broadcastOn()
{
return new PrivateChannel('example.' . $this->id);
}
}
Trigger an event (PHP)
use App\Events\MyExample
$payload = [
'duck' => 'sauce',
'Bass' => 'Epic'
];
event(new MyExample($id, $payload))
Listening for event (JavaScript)
Echo.private(`example.${id}`).listen('MyExample', event => {
console.log('payload', event.payload)
})
Try to change this line:
$this->$receiverId = $receiverId;
To this line:
$this->receiverId = $receiverId;
In your PrivateMessageEvent __construct()
Update:
Try to use use a fixed channel id like this:
window.Echo.private('private-chat.1')
I suggest you also to use presence channel, are private too but with more features, i.e.:
Echo.join('private-chat.1')
.listen('PrivateMessageEvent', (e) => {
console.log(e);
});
If you use a dinamic channel number like you use, i.e.:
window.Echo.private(`private-chat.${receiverId}`)
You have to give receiverId a value in javascript, this declaration is a generic room listener but receiverId should be defined, ${receiverId} is a string interpolation.
You can define receiverId in the template before inluding app.js, for example, using blade syntax:
<script>
receiverId = {{ $receiverId }};
</script>
Another think: I want to be clear that, in all the code above, receiverId represent the id of the chat/room a client want join to not the ID of the receiving user.
Try instead of event(new PrivateMessageEvent($chat, $receiverId));
this
App\Events\PrivateMessageEvent::dispatch($chat, $receiverId);
There are a few things you need to do.
1) Remove all 'private-' from the beginning of your channel names. These get handled behind the scenes by the various libraries (eg socket.io/laravel-echo). If you look at any debug output you will see 'private-' prepended to the front of the channel names but you DO NOT need to add these.
2) If you're using redis then make sure the REDIS_PREFIX is set to an empty string in your .env file. By default it's set to something like 'laravel_database' and this messes up the channel names.
REDIS_PREFIX=
3) Make sure you've got your laravel-echo server running (and redis/pusher). Also you need to make sure you have the queue worker running. In my case, as i;m running redis, i had to run:
php artisan queue:work redis

Laravel Excel can't download and export

My code is copyed from the website.
Excel::create('Filename', function($excel) {
// Set the title
$excel->setTitle('Our new awesome title');
// Chain the setters
$excel->setCreator('Maatwebsite')
->setCompany('Maatwebsite');
// Call them separately
$excel->setDescription('A demonstration to change the file properties');
})->download('xls');
I successfully download once.
However the other try is error.
The error Message is that.
Whoops, looks like something went wrong.
FatalErrorException in LaravelExcelWriter.php line 263:
Call to a member function getMergeCells() on a non-object
in LaravelExcelWriter.php line 263
• Write following in cmd
composer require Maatwebsite/excel
• after install /run upper composer........Maalwebsite/excel successfully check in composer.json that
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.2.*",
"laravelcollective/html": "5.2.*",
"Maatwebsite/excel": "^2.1"
},
• config/app.php/ in provides
Maatwebsite\Excel\ExcelServiceProvider::class,
• config/app.php/ in alias
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
• php artisan vendor:publish
• php artisan make:controller ExcelController
• open excel then create first_name,last_name,sex,email,phone then store datas and save as .csv
• in controlller for import
use App\Customer;
use Input;
use DB;
use Excel;
class ExcelController extends Controller
{
//
public function getImport()
{
return view('excel.importCustomer');
}
public function postImport()
{
Excel::load(Input::file('customer'),function($reader){
$reader->each(function($sheet){
Customer::firstOrCreate($sheet->toArray());
});
});
}
}
• in routes for import
Route::get('/getImport','ExcelController#getImport');
Route::post('/postImport','ExcelController#postImport');
• In controller for export
public function getExport()
{
$export=Customer::all();
Excel::create('Export Data',function($excel) use ($export){
$excel->sheet('Sheet 1',function($sheet) use ($export){
$sheet->fromArray($export);
});
})->export('xlsx');
}
I know why the reason.
Because there is not any sheet in my case.
However the sheet is necessary.
Thank you.

Test Api 404 on multiple requests

I'm trying to test all the routes on my api but only the first request gets 200, all the other following requests get 404. But if I run any test individually using (phpunit --filter test_something) it works.
<?php
class ProgramTest extends TestCase {
/** #test */
public function it_returns_index() {
$this->get('api/v1/test')
->assertReturnOk(['limit' => 10]);
}
/** #test */
public function it_returns_show() {
$this->get('api/v1/test/12')
->seeJson(['id' => 12]);
}
}
getting error as
PHPUnit 4.8.23 by Sebastian Bergmann and contributors.
.F
Time: 2.33 seconds, Memory: 20.25Mb
There was 1 failure:
1) ProgramTest::it_returns_show
Invalid JSON was returned from the route. Perhaps an exception was thrown?
You need to fix the problem in Routes.php I think. I have seen a similar question that has been answered in the below link. Hope this would solve you. The Route modification that was done is as per the below link
$phpunit = simplexml_load_file('phpunit.xml');
foreach (File::allFiles(__DIR__ . '/Routes') as $partial) {
if ($phpunit->php->xpath('env[#name="APP_ENV"]')[0]['value'] == 'testing') {
require $partial->getPathname();
} else {
require_once $partial->getPathname();
}
}
https://laracasts.com/discuss/channels/testing/test-api-404-on-multiple-requests

Resources