Multiple Find Query in single database connection Laravel - php

Trying to enhance performance in Laravel query. Making multiple find operations on a single model, withing a loop, but trying to make it use a single database connection instance.
$departments = [];
foreach ($this->departments_only as $department) {
array_push($departments, Department::find($department));
}
return $departments;
No error. But just want a better performance.

As I can see the departments_only is array of ids, so you can use whereIn
$departments = Department::whereIn('id', $this->departments_only)->get();
This will return collection of departments.

For these cases, I use this library l5-repository
And do it:
$myArray = [1,2,3,4];
$result = $this->repository->scopeQuery(function ($query) use ($myArray) {
return $query
->whereIn("departament_id", $myArray);
})->all();
return $result
Or using raw queries and pure Laravel:
$myArray = [1,2,3,4,5];
$result = DB::table('departments')
->selectRaw('departament_id in (?)', $myArray)
->get();

if $this->departments_only has only ids in array then you can use
Model::whereIn('column','array')->get();
For more reference visit https://laravel.com/docs/5.8/queries#where-clauses
Or use DB object as,
DB::statement('SELECT * FROM table_name WHERE column_name IN ('"array_of_ids"')');

Related

Access to multilevel relationships in laravel

can someone help me on getting data from multi level relationships in laravel?
I want to do something like
BagageAnnouncement->Announcement->user->profile->"name of the field"
$data = $request->text;
$filter = BagageAnnouncement::whereHas('announcement',function ($query) {
})->whereHas('user', function ($query) {
})->whereHas('profile',function($query){
$query->where('level',$data)
})->get();
Thank you guys for you answers I finally figure out a solution
$data = $request->text;
$filter = BagageAnnouncement::whereHas(
'announcement.user.profile',
function ($q2) use ($data) {
$q2->where('level',$data);
}
)->get();
Not sure what you want as the result, but if you want a single result, you can do like this:
$bagage = BagageAnnouncement::where(specify_your_condition)->first();
$filter = $bagage->user->profile->name_of_the_field;
If you want an array of results, change the first() to get() and make use of foreach
Of course, you will need to set up the relationships in your models first.

Laravel - set array just with values

I'm trying to send an email to multiple emails, so I did a query to my users tables but the result is an array with keys that don't work mail->to().
I need an array like this: $owners = ['myoneemail#esomething.com', 'myother#esomething.com','myother2#esomething.com']; from database.
My query:
$owners = DB::table('users')->select('email')->where('active', 1)->where('userType', 1)->get();
I also try use ->toArray() but comes with keys.
Email:
Mail::send('email-view', $data, function($message) use ($data, $owners)
{
$message->from('no-reply#email.pt' , 'FROM');
$message->to($owners)->subject('subject');
});
$owners = DB::table('users')->where('active', 1)->where('userType', 1)->pluck('email')->toArray();
You can use ->pluck(), like this:
$owners = DB::table('users')->select('email')->where('active', 1)->where('userType', 1)->get();
$emailList = $owners->pluck('email');
$owners = DB::table('users')->where('active', 1)->where('userType', 1)->pluck('email');
or
$owners = User::where('active', 1)->where('userType', 1)->pluck('email');
here User is your model name
First of all, the where condition is not proper in your query builder code.
It has to be like:
$query->where([
['column_1', '=', 'value_1'],
['column_2', '<>', 'value_2'],
[COLUMN, OPERATOR, VALUE],
...
])
You can use pluck() to get the list in Laravel 5.
All collections also serve as iterators, allowing you to loop over them as if they were simple PHP arrays:
foreach ($owners as $owner) {
echo $owner->filed_name;
echo $owner->filed_name;
...
}
There is no restriction for using the core PHP code while using a PHP framework. You may refer the official PHP Arrays Manual page to work with the language construct.
If you need to convert JSON to array, use:
json_decode($owners);

Extract all possible values of AR column in yii2

Several models in yii2 are bound to a database using ActiveRecords. I now want to have a list of all ids of this model. Say, all user IDs when the Model is called User.
Sure I could just fetch all models and iterate over them, much like
$ids = [];
$users = User::find()->all();
foreach ($users as $user) {
$ids[] = $user->id;
}
But I feel there should be an easier way... Thanks in advance.
If you want to stay in ActiveRecord then this accomplishes the same thing:
$ids = User::find()->select('id')->column();
This returns array:
$ids = (new \yii\db\Query)->select('id')->from(User::tableName())->all();

Copy one table to another in laravel 5

How do i use the following insert into query in laravel 5?
INSERT INTO connection2.table (SELECT * from connection1.table);
I am looking for two different connections, Connection1.table record should goes to Connection2.table.
try
$c1 = DB("Connection1")->select("SELECT * from table")
foreach($c1 as $record){
DB("Connection2")->table("table")->insert(get_object_vars($record))
}
Since laravel 5.7+ insertUsing(array $columns, Closure|Builder|string $query) is available,
DOCS: https://laravel.com/api/5.8/Illuminate/Database/Query/Builder.html#method_insertUsing
therefore you can now make this whole query in Laravel chaining style like
DB::table('newTable')->insertUsing(
['column1', 'column2', 'column3',], // ..., columnN
function ($query) {
$query
->select(['column1', 'column2', 'column3',]) // ..., columnN
->from('oldTable');
// optional: you could even add some conditions:
// ->where('some_column', '=', 'somevalue')
// ->whereNotNull('someColumn')
}
);
DB here is set-up in app.php 'aliases' as
'DB' => Illuminate\Support\Facades\DB::class,
#Wistar, Thanks for reply, with your code $record comes with an object class which is not accepted by insert,
it required the array type.
I have used it as follows:
DB::setFetchMode(PDO::FETCH_ASSOC);
$table_records = DB::connection('Connection1')->select("SELECT * from table");
DB::setFetchMode(PDO::FETCH_CLASS);
DB::connection('Connection2')->table("table")->insert($table_records);
Elaborating on how to chunk results in case of large tables. You can of course chunk as you see fit, 5000 is just an example.
$chunk1 = DB("Connection1")->table("table")->orderBy("id")->chunk(5000, function($c1) {
foreach($c1 as $record) {
DB("Connection2")->table("table")->insert(get_object_vars($record))
}
});
$basket_data = DB::table('baskets')->get();
foreach($basket_data as $records)
{
DB::table('basket_after_payments')->insert(get_object_vars($records));
}

How to get a one-dimensional scalar array as a doctrine dql query result?

I want to get an array of values from the id column of the Auction table.
If this was a raw SQL I would write:
SELECT id FROM auction
But when I do this in Doctrine and execute:
$em->createQuery("SELECT a.id FROM Auction a")->getScalarResult();
I get an array like this:
array(
array('id' => 1),
array('id' => 2),
)
Instead, i'd like to get an array like this:
array(
1,
2
)
How can I do that using Doctrine?
PHP < 5.5
You can use array_map, and since you only have on item per array, you can elegantly use
'current' as callback, instead of writing a closure.
$result = $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult();
$ids = array_map('current', $result);
See Petr Sobotka's answer below for additional info regarding memory usage.
PHP >= 5.5
As jcbwlkr's answered below, the recommended way it to use array_column.
As of PHP 5.5 you can use array_column to solve this
$result = $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult();
$ids = array_column($result, "id");
A better solution is to use PDO:FETCH_COLUMN . To do so you need a custom hydrator:
//MyProject/Hydrators/ColumnHydrator.php
namespace DoctrineExtensions\Hydrators\Mysql;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator, PDO;
class ColumnHydrator extends AbstractHydrator
{
protected function hydrateAllData()
{
return $this->_stmt->fetchAll(PDO::FETCH_COLUMN);
}
}
Add it to Doctrine:
$em->getConfiguration()->addCustomHydrationMode('COLUMN_HYDRATOR', 'MyProject\Hydrators\ColumnHydrator');
And you can use it like this:
$em->createQuery("SELECT a.id FROM Auction a")->getResult("COLUMN_HYDRATOR");
More info:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes
Ascarius' answer is elegant, but beware of memory usage! array_map() creates a copy of passed array and effectively doubles memory usage. If you work with hundreds of thousands of array items this can become an issue. Since PHP 5.4 call-time pass by reference has been removed so you cannot do
// note the ampersand
$ids = array_map('current', &$result);
In that case you can go with obvious
$ids = array();
foreach($result as $item) {
$ids[] = $item['id'];
}
Since doctrine/orm 2.10.0 there is a built-in solution for this:
use Doctrine\ORM\AbstractQuery;
$query = $em->createQuery("SELECT a.id FROM Auction a");
return $query->getSingleColumnResult();
// Same as:
return $query->getResult(AbstractQuery::HYDRATE_SCALAR_COLUMN);
Docs: https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/dql-doctrine-query-language.html#scalar-column-hydration
I think it's impossible in Doctrine.
Just transform result array into the data structure you want using PHP:
$transform = function($item) {
return $item['id'];
};
$result = array_map($transform, $em->createQuery("SELECT a.id FROM Auction a")->getScalarResult());

Categories