Laravel: getting a single value from a MySQL query - php

I'm trying get a single value from MySQL database using laravel but the problem I'm getting an array . this is my query result in MySQL command line:
select groupName from users;
+-----------+
| groupName |
+-----------+
| Admin |
+-----------+
my laravel function:
public static function PermitAddNewUser(){
$username=Session::get('key');
$data=DB::select("select groupName from users where username='$username';");
return $data;
}
expected $data value is a string with value= Admin
but what i get is : [{"groupName":"Admin"}]

yet another edit: As of version 5.2 pluck is not deprecated anymore, it just got new behaviour (same as lists previously - see side-note below):
edit: As of version 5.1 pluck is deprecated, so start using value instead:
DB::table('users')->where('username', $username)->value('groupName');
// valid for L4 / L5.0 only
DB::table('users')->where('username', $username)->pluck('groupName');
this will return single value of groupName field of the first row found.
SIDE NOTE reg. #TomasButeler comment: As Laravel doesn't follow sensible versioning, there are sometimes cases like this. At the time of writing this answer we had pluck method to get SINGLE value from the query (Laravel 4.* & 5.0).
Then, with L5.1 pluck got deprecated and, instead, we got value method to replace it.
But to make it funny, pluck in fact was never gone. Instead it just got completely new behaviour and... deprecated lists method.. (L5.2) - that was caused by the inconsistency between Query Builder and Collection methods (in 5.1 pluck worked differently on the collection and query, that's the reason).

Edit:
Sorry i forgot about pluck() as many have commented :
Easiest way is :
return DB::table('users')->where('username', $username)->pluck('groupName');
Which will directly return the only the first result for the requested row as a string.
Using the fluent query builder you will obtain an array anyway.
I mean The Query Builder has no idea how many rows will come back from that query.
Here is what you can do to do it a bit cleaner
$result = DB::table('users')->select('groupName')->where('username', $username)->first();
The first() tells the queryBuilder to return only one row so no array, so you can do :
return $result->groupName;
Hope it helps

As of Laravel >= 5.3, best way is to use value:
$groupName = \App\User::where('username',$username)->value('groupName');
or
use App\User;//at top of controller
$groupName = User::where('username',$username)->value('groupName');//inside controller function
Of course you have to create a model User for users table which is most efficient way to interact with database tables in Laravel.

[EDIT]
The expected output of the pluck function has changed from Laravel 5.1 to 5.2. Hence why it is marked as deprecated in 5.1
In Laravel 5.1, pluck gets a single column's value from the first result of a query.
In Laravel 5.2, pluck gets an array with the values of a given column. So it's no longer deprecated, but it no longer do what it used to.
So short answer is use the value function if you want one column from the first row and you are using Laravel 5.1 or above.
Thanks to Tomas Buteler for pointing this out in the comments.
[ORIGINAL]
For anyone coming across this question who is using Laravel 5.1, pluck() has been deprecated and will be removed completely in Laravel 5.2.
Consider future proofing your code by using value() instead.
return DB::table('users')->where('username', $username)->value('groupName');

Using query builder, get the single column value such as groupName
$groupName = DB::table('users')->where('username', $username)->pluck('groupName');
For Laravel 5.1
$groupName=DB::table('users')->where('username', $username)->value('groupName');
Or, Using user model, get the single column value
$groupName = User::where('username', $username)->pluck('groupName');
Or, get the first row and then split for getting single column value
$data = User::where('username', $username)->first();
if($data)
$groupName=$data->groupName;

Continuing, here is how you do it in Laravel 7.x or 8.x
$email = DB::table('users')->where('name', 'John')->value('email');
source: trust me
Updated based on #Shuhad zaman comment

On laravel 5.6 it has a very simple solution:
User::where('username', $username)->first()->groupName;
It will return groupName as a string.

Related

JSON Search in laravel eloquent

I am storing destinations field as json type in mysql
example column value ["Goa", "Moonar", "Kochi"]
I would like to get all rows that matches goa as destinations
However this row query returns the desired result
SELECT * FROM `packages`
WHERE JSON_CONTAINS(destinations, '["Goa"]');
But what is the eloquent equivalent of the above query??
Laravel version 5.3
Modelname :Search
Probably forced to use a partially raw query like:
use DB; (top of file definition)
DB::table('packages')->whereRaw('json_contains(destinations, \'["Goa"]\')')->get();
And if you have a model:
Package::whereRaw('json_contains(destinations, \'["' . $keyword . '"]\')')->get();
assuming your query above works in SQL.
In Laravel 5.6 and higher you can use whereJsonContains method:
Package::whereJsonContains('destinations',["Goa"])->get();
But not all DB support it: https://laravel.com/docs/5.6/queries#json-where-clauses

How to write MySQL Query in Laravel 5 without using PHP String function?

I need to eliminate the specific prefix of a string by default on getting value from the database.
In MySQL, i can use the following,
SELECT RIGHT('abc3',1) -- Results in "3"
SELECT RIGHT('abc3',2) -- Results in "c3"
But, how can i use same process in Laravel eloquent?.
Or any other solutions are available for remove the prefix of a string while retrieve from database in laravel.
I know trim will eliminate, but only spaces.
ex.
property_color
property_size
Here i need to extract "property_".
expect.
color
size
Is it possible in laravel, in without using PHP String function.
Only on Direct eloquent Operation.
Thanks in Advance !
That's what I would do:
$arrayData = DB::select(DB::raw("SELECT RIGHT('abc3',1) ")):
you can pass array of parameter to bind values:
DB::select(DB::raw(" SQL QUERY "),$paramsArray);
You have to use raw queries within your builder like
$results = YourRepo::where(DB::raw("SELECT SUBSTRING('property_color',9)") , 'LIKE', "%property_xxx%");
keep in mind that substring is slow.

Why is pluck('id') returning all id-s instead of just one?

The following query returns every Quote's id-s, instead of returning just one:
Quote::find(1)->pluck('id'); // --> [1, 2, 3, 4, ...]
Why is this happening?
Update
Strangely, the query:
Quote::where('id', 1)->pluck('id'); // --> [1]
works as expected.
There are (basically) two kinds of pluck() - one that works on collections, and one that works on Builder objects. When you do
Quote::where('id', 1)->pluck('id');
then you have a Builder object, since prior to the plucking you haven't returned anything from the database - you're still building the query. So that works, because the plucking is added to the query and executed.
However, when you do Quote::find(1), you get a Quote object back - which is neither a Builder nor a Collection. Instead, Laravel creates a new query where it tries to pluck values from the database for you, based on which model you're on. In this case, that's the Quote.
This behaviour was changed in 5.2, so in 5.1 you'd get just the column value back - 1 in your case, as expected. But pluck() is taking over what used to be called lists() in earlier versions of Laravel, starting from 5.2. So your results are correct - however confusing.
Quote::find(1) is returning a Quote object, not a Collection of Quotes. You are then calling pluck('id') on that quote object. Since the Quote object doesn't actually have a pluck() method, what this is actually doing is creating a new query builder instance for quotes, and calling pluck on that. It is the same as if you did Quote::pluck('id'). That is why you are getting all of the ids.
Since Quote::find(1) is going to return the Quote object, you don't need to call pluck() on it. You can just access the property.
$quote = Quote::find(1);
echo $quote->id;

Laravel - Eloquent or Fluent random row

How can I select a random row using Eloquent or Fluent in Laravel framework?
I know that by using SQL, you can do order by RAND(). However, I would like to get the random row without doing a count on the number of records prior to the initial query.
Any ideas?
Laravel >= 5.2:
User::inRandomOrder()->get();
or to get the specific number of records
// 5 indicates the number of records
User::inRandomOrder()->limit(5)->get();
// get one random record
User::inRandomOrder()->first();
or using the random method for collections:
User::all()->random();
User::all()->random(10); // The amount of items you wish to receive
Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();
Laravel 3:
User::order_by(DB::raw('RAND()'))->get();
Check this article on MySQL random rows. Laravel 5.2 supports this, for older version, there is no better solution then using RAW Queries.
edit 1: As mentioned by Double Gras, orderBy() doesn't allow anything else then ASC or DESC since this change. I updated my answer accordingly.
edit 2: Laravel 5.2 finally implements a wrapper function for this. It's called inRandomOrder().
This works just fine,
$model=Model::all()->random(1)->first();
you can also change argument in random function to get more than one record.
Note: not recommended if you have huge data as this will fetch all rows first and then returns random value.
tl;dr: It's nowadays implemented into Laravel, see "edit 3" below.
Sadly, as of today there are some caveats with the ->orderBy(DB::raw('RAND()')) proposed solution:
It isn't DB-agnostic. e.g. SQLite and PostgreSQL use RANDOM()
Even worse, this solution isn't applicable anymore since this change:
$direction = strtolower($direction) == 'asc' ? 'asc' : 'desc';
edit: Now you can use the orderByRaw() method: ->orderByRaw('RAND()'). However this is still not DB-agnostic.
FWIW, CodeIgniter implements a special RANDOM sorting direction, which is replaced with the correct grammar when building query. Also it seems to be fairly easy to implement. Looks like we have a candidate for improving Laravel :)
update: here is the issue about this on GitHub, and my pending pull request.
edit 2: Let's cut the chase. Since Laravel 5.1.18 you can add macros to the query builder:
use Illuminate\Database\Query\Builder;
Builder::macro('orderByRandom', function () {
$randomFunctions = [
'mysql' => 'RAND()',
'pgsql' => 'RANDOM()',
'sqlite' => 'RANDOM()',
'sqlsrv' => 'NEWID()',
];
$driver = $this->getConnection()->getDriverName();
return $this->orderByRaw($randomFunctions[$driver]);
});
Usage:
User::where('active', 1)->orderByRandom()->limit(10)->get();
DB::table('users')->where('active', 1)->orderByRandom()->limit(10)->get();
edit 3: Finally! Since Laravel 5.2.33 (changelog, PR #13642) you can use the native method inRandomOrder():
User::where('active', 1)->inRandomOrder()->limit(10)->get();
DB::table('users')->where('active', 1)->inRandomOrder()->limit(10)->get();
You can use:
ModelName::inRandomOrder()->first();
it's very simple just check your laravel version
Laravel >= 5.2:
User::inRandomOrder()->get();
//or to get the specific number of records
// 5 indicates the number of records
User::inRandomOrder()->limit(5)->get();
// get one random record
User::inRandomOrder()->first();
or using the random method for collections:
User::all()->random();
User::all()->random(10); // The amount of items you wish to receive
Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();
Laravel 3:
User::order_by(DB::raw('RAND()'))->get();
In Laravel 4 and 5 the order_by is replaced by orderBy
So, it should be:
User::orderBy(DB::raw('RAND()'))->get();
For Laravel 5.2 >=
use the Eloquent method:
inRandomOrder()
The inRandomOrder method may be used to sort the query results randomly. For example, you may use this method to fetch a random user:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
from docs: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
You can also use order_by method with fluent and eloquent like as:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()'));
This is a little bit weird usage, but works.
Edit: As #Alex said, this usage is cleaner and also works:
Posts::where_status(1)->order_by(DB::raw('RAND()'));
Use Laravel function
ModelName::inRandomOrder()->first();
You can easily Use this command:
// Question : name of Model
// take 10 rows from DB In shuffle records...
$questions = Question::orderByRaw('RAND()')->take(10)->get();
There is also whereRaw('RAND()') which does the same, you can then chain ->get() or ->first() or even go crazy and add ->paginate(int).
I prefer to specify first or fail:
$collection = YourModelName::inRandomOrder()
->firstOrFail();
Laravel has a built-in method to shuffle the order of the results.
Here is a quote from the documentation:
shuffle()
The shuffle method randomly shuffles the items in the collection:
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] - (generated randomly)
You can see the documentation here.
At your model add this:
public function scopeRandomize($query, $limit = 3, $exclude = [])
{
$query = $query->whereRaw('RAND()<(SELECT ((?/COUNT(*))*10) FROM `products`)', [$limit])->orderByRaw('RAND()')->limit($limit);
if (!empty($exclude)) {
$query = $query->whereNotIn('id', $exclude);
}
return $query;
}
then at route/controller
$data = YourModel::randomize(8)->get();
I have table with thousands of records, so I need something fast. This is my code for pseudo random row:
// count all rows with flag active = 1
$count = MyModel::where('active', '=', '1')->count();
// get random id
$random_id = rand(1, $count - 1);
// get first record after random id
$data = MyModel::where('active', '=', '1')->where('id', '>', $random_id)->take(1)->first();
Here's how I get random results in eloquent in one of my projects:
$products = Product::inRandomOrder()->limit(10);
10 - The number of random records to pull.
Try this code! It Works:
User::orderBy(DB::raw('RAND()'))->get();

Mongo Doctrine Query Builder Select does not work. Bug?

$dm = $this->get('doctrine.odm.mongodb.document_manager');
$query = $dm->createQueryBuilder('MyBundle:Listing')
->select('title')
->field('coordinates')->geoNear(
(float)$longitude,
(float)$latitude
)->spherical(true);
$classifieds_array = $classifieds->toArray();
$data = array('success'=>true,'classifieds' => $classifieds_array,
'displaymessage' => $classifieds->count(). " Search Results Found");
Even though I am selecting just one field, for my result set, I am getting every thing back in collection along with title. Is this a bug?
NOTE: I commented out the ->field('coordinates')->geoNear((float)$longitude, (float)$latitude)->spherical(true) line and now the select seems to work. This is crazy.
The geoNear command in MongoDB doesn't seem to support filtering result fields, according to the documentation examples. Only a query option is supported to limit matched documents.
In your case, it also looks like mixing up the geoNear() and near() builder methods in Doctrine. Since you're operating on the coordinates field, the appropriate syntax would be near(). geoNear() is a top-level method to tell the builder you wish to use the command, which doesn't require a field name since it uses the one and only geospatial index on the collection.
For usage examples, I would advise looking at the query and builder unit tests in the Doctrine MongoDB library.

Categories