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

[5.4] DB::setFetchMode(PDO::FETCH_ASSOC) in Laravel 5.4 #17557

Closed
PheRum opened this issue Jan 26, 2017 · 29 comments
Closed

[5.4] DB::setFetchMode(PDO::FETCH_ASSOC) in Laravel 5.4 #17557

PheRum opened this issue Jan 26, 2017 · 29 comments

Comments

@PheRum
Copy link

PheRum commented Jan 26, 2017

use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;

$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => 'password',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]);

$capsule->setFetchMode(PDO::FETCH_ASSOC);

$capsule->setAsGlobal();
$capsule->bootEloquent();

$capsule->setFetchMode(PDO::FETCH_ASSOC); not working? return object

prompt. is now set FetchMode if the database is used not laravel?

@mariomka
Copy link

Check out upgrade guide (https://laravel.com/docs/5.4/upgrade):

Fetch Mode

Laravel no longer includes the ability to customize the PDO "fetch mode" from your configuration files. Instead, PDO::FETCH_OBJ is always used. If you will still like to customize the fetch mode for your application you may listen for the new Illuminate\Database\Events\StatementPrepared event:

Event::listen(StatementPrepared::class, function ($event) {
$event->statement->setFetchMode(...);
});

@PheRum
Copy link
Author

PheRum commented Jan 26, 2017

@themsaid @mariomka Of course, I read this documentation
but through this event also does not work

use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;

$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => 'password',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]);

$capsule->setFetchMode(PDO::FETCH_ASSOC);

$capsule->setAsGlobal();
$capsule->bootEloquent();
$dispatcher = new Illuminate\Events\Dispatcher;
$dispatcher->listen(Illuminate\Database\Events\StatementPrepared::class, function ($event) {
    $event->statement->setFetchMode(PDO::FETCH_ASSOC);
});

@taylorotwell Please return back $capsule->setFetchMode(...);

@themsaid themsaid reopened this Jan 26, 2017
@bubach
Copy link

bubach commented Jan 26, 2017

Would be so much easier just to keep the god damn setter, why even have the protected var and then a getter for it - but no way of setting it except hacking the source or setting up event listeners? Retarded. Simply retarded, no way around it.

@GrahamCampbell
Copy link
Member

It's not intended for people to try to change this setting anymore.

@juanpscotto
Copy link

This does not work for me neither:

$dispatcher = new Illuminate\Events\Dispatcher;
$dispatcher->listen(Illuminate\Database\Events\StatementPrepared::class, function ($event) {
    $event->statement->setFetchMode(PDO::FETCH_ASSOC);
});

Can you put an example of how implement the listener please

@cnanney
Copy link
Contributor

cnanney commented Mar 28, 2017

Another downside of needing to set the fetch mode via event listener, you lose it when mocking events in unit tests. Currently event mocking is all or nothing, as soon as you want to mock and test one event, your new setFetchMode event will then not be fired.

@cnanney
Copy link
Contributor

cnanney commented Mar 29, 2017

@GrahamCampbell Can you please expand on why it is no longer intended for people to change the fetch mode?

If we are no longer supposed to, why is it mentioned in the docs that you CAN keep using FETCH_ASSOC if you really want to, you just now have to use an event listener, which is a hacky workaround for something that was totally simple before. In this section of the docs it doesn't say that doing so will break anything, so there must not be any internal reason why you can't use FETCH_ASSOC, but rather a convention you are arbitrarily forcing on people?

You took something simple and flexible, a config value or a public setter, and made it inflexible and problematic (the event listener method breaks when mocking events in tests). Why?

@grumpysi
Copy link

Causing me some headaches too. +1 for bring it back.

@cnanney
Copy link
Contributor

cnanney commented Apr 24, 2017

Added proposal to laravel/ideas#546 for some hopeful feedback.

@grumpysi
Copy link

For me the FETCH_ASSOC mode allows for a much simpler and far more resource efficient way to export large chunks of data into Excel. It's a useful feature, not often used but worth keeping around.

@lovelock
Copy link

lovelock commented May 3, 2017

I just want to drop it for this reason.

@spierman
Copy link

spierman commented Jun 6, 2017

$capsule = new Capsule();
$capsule->addConnection([
'driver' => 'mysql',
'host' => '',
'database' => '
',
'username' => '',
'password' => '
',
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => ''
]);
$dispatcher = new Illuminate\Events\Dispatcher;
$dispatcher->listen(Illuminate\Database\Events\StatementPrepared::class, function ($event) {
$event->statement->setFetchMode(PDO::FETCH_ASSOC);
});
$capsule->setEventDispatcher($dispatcher);
$capsule->setAsGlobal();
$capsule->bootEloquent();

@bubach
Copy link

bubach commented Jun 9, 2017

Eloquent is used outside of Laravel. Also, how in the hell is this an issue, why remove something that is common, worked, and obviously affects people?

@lovelock
Copy link

lovelock commented Jun 11, 2017

This is what I do

$capsule = new Manager();
$capsule->addConnection($dbConfig);
$capsule->setAsGlobal();
$capsule->bootEloquent();
$connection = $capsule->getConnection();
$connection->enableQueryLog();
$dispatcher = new Dispatcher();
$dispatcher->listen(StatementPrepared::class, function ($event) {
    $event->statement->setFetchMode(PDO::FETCH_ASSOC);
});
$dbName = $dbConfig['database'];
$dispatcher->listen(QueryExecuted::class, function ($event) use ($dbName) {
    $sql = str_replace("?", "'%s'", $event->sql);
    $query = vsprintf($sql, $event->bindings);
    $context = ['connection' => $dbName, 'sql' => $query, 'time' => $event->time];
    Logger::makeLogger()->info('query', $context);
    Log::info('query', $context);
});
$connection->setEventDispatcher($dispatcher);
return $connection;

I don't agree with the author. The setFetchMode is obviously a better way of doing this, which has been removed. Read code in illuminate\database\connection.php and you will find the answer. This is not a bug, but a personal flavor.

image

image

@viamage
Copy link

viamage commented Jan 20, 2018

Removing this was so evil. Many hours of unnecessary work for everybody that want to upgrade code that used this.

@omarjebari
Copy link

Let's hear it for a rewind!
[Bring that code back]

@EgorGruzdev
Copy link
Contributor

Коллеги, вы все ищите решение проблемы, а кто нибудь знает почему был выбран такой режим выборки.

Colleagues, you all are looking for a solution to the problem, and who knows why this selection mode was chosen.

@JustinLawrenceMS
Copy link

What I don't understand is that there are methods native to Laravel that will reject PDO objects and demand an array. Specifically class DB. Why demand array if you are going make it next to impossible to let us give you one.

@pablosebastianr
Copy link

What I don't understand is that there are methods native to Laravel that will reject PDO objects and demand an array. Specifically class DB. Why demand array if you are going make it next to impossible to let us give you one.

Yeah, it really sucks. We're migrating a legacy system into a new project and we're working with very large sets of data and we need to do an extra step to convert that pdo object into an array because DB::insert won't work with objects... a totally unneeded step, for every record we grab from the database.... I roll my eyes every time I think of this....

@lovelock
Copy link

lovelock commented Oct 1, 2019 via email

@awesomedeba10
Copy link

Theres another option I find to by pass it
Add env DB_FETCHMODE=FETCH_ASSOC
In config/database add for connections.mysql
'fetch_mode' => env('DB_FETCHMODE', 'FETCH_ASSOC'),
In illuminate/datbase/connection.php replace prepared function with
protected function prepared (PDOStatement $statement){ $config = $this->config; $statement->setFetchMode($config['fetch_mode'] == "FETCH_OBJ" ? 5 : ($config['fetch_mode'] == "FETCH_NUM" ? 3 : 2)); $this->event(new Events\StatementPrepared( $this, $statement )); return $statement; }

This make default FETCH_ASSOC for your application

Then if you want to change it like before,
add config(['database.connections.mysql.fetch_mode' => 'FETCH_OBJ']);
a replacement of DB::setFetchMode(PDO::FETCH_ASSOC);

@awesomedeba10
Copy link

@lovelock If laravel official don't return it back to us, we have to bypass it. And how should you do it without modifying library code a little. What I did was just passing PDO fetch method to config data and achieve the same thing dynamically

@lovelock
Copy link

lovelock commented Oct 1, 2019 via email

@JustinLawrenceMS
Copy link

JustinLawrenceMS commented Oct 1, 2019 via email

@awesomedeba10
Copy link

@JustinLawrenceMS actually its still same as of laravel 6, and the code I provide, it was in laravel 6.0.4 latest as of now

@benyaminl
Copy link

Can anyone tell the reason why setFetchMode is removed from laravel?

@kmacute
Copy link

kmacute commented Sep 16, 2020

Hi any update?

@JustinLawrenceMS
Copy link

JustinLawrenceMS commented Sep 16, 2020 via email

@driesvints
Copy link
Member

Hey everyone,

I'm locking this issue because it either has gone off-topic, become a dumping ground for things which shouldn't be in an issue tracker or is just too old. Please try to discuss things further on one of the below channels:

@laravel laravel locked and limited conversation to collaborators Sep 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests