Howv to assign multiple result of query laravel php - php

New to Laravel php and trying to find out solution of this,
$periods = Period::where('timetable_id', $id);
echo $periods;
giving this error
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string
i know why its giving this error but can not think of an alternate.

You'd need to ->get() your results first. Also, since you'll get a Collection returned you'd need to use dd() (or print_r/var_dump) to output the results:
$periods = Period::where('timetable_id', $id)->get();
dd($periods);
More on Building Queries

Related

How to pass the value in consoletvs charts using Laravel

I want to pass the average time and the user e-mail in consoletvs/charts i worte the SQL for that
$currentTime = Carbon::today();
$time_difference = DB::select(DB::raw("SELECT `acu_name` ,AVG(TIMESTAMPDIFF(MINUTE, acu_at, acu_et)) as averageTime
FROM `active_user`
WHERE acu_at <= '$currentTime' GROUP BY `acu_name`"));
in this SQL result is coming when i get this through foreach method but if pass this through charts it's showing an error
$chart = Charts::create('bar', 'highcharts')
->title('Total Clients Average Using Time')
->elementLabel("Total")
->labels($time_difference->acu_name)
->values($time_difference->averageTime)
->responsive(false);
Error Message is :
I can't understand what is the issues please help me to find out the issue
and i attached my database structure and dummy data screen shots.
My php version is 7.3.2
Laravel version is 5.5
When you do DB::select() it gives you array having stdClass objects representing the found rows. So even if you expect one resultant row coming out of your DB::select() query, the result will be still inside an array.
So when you are doing following :
$currentTime = Carbon::today();
$time_difference = DB::select(DB::raw("SELECT `acu_name` ,AVG(TIMESTAMPDIFF(MINUTE, acu_at, acu_et)) as averageTime
FROM `active_user`
WHERE acu_at <= '$currentTime' GROUP BY `acu_name`"));
It is returning an array and inside that there are records matching.
You either need to do foreach() to loop through $time_difference array or do $time_difference[0]-> acu_name
Also, your DB::raw contains a user defined variable which is a danger for SQL injections.
Update :
Please check documentation where there are nice examples for the eloquent way of doing this.
To me it looks indeed strange that this specific error is being thrown. However we can see in you provided code that you store the following in your $time_difference variable:
DB::select(...);
Usually this returns an instance of Illuminate\Database\Query\Builder which is an object if I am not mistaking.
If you take a look into the source code you can see that this function does return $this which is an instance of the above mentioned.
What I can say that is missing is the execution of the query. Usually a select() is followed by a get() or a first() as shown in the documentation.
Another action you should undertake is to validate of anything has been returned after the execution of your query. You final code with some tweaks could look like:
$time_difference = DB::table('active_user')
->select([
'acu_name',
DB::raw('AVG(TIMESTAMPDIFF(MINUTE, acu_at, acu_et)) as averageTime'),
])
->where('acu_at', '<=', $currentTime)
->groupBy('acu_name')
->first(); // Be aware this will only return the first row. Not sure if this is what you inted to do.
if (is_null($time_difference)) {
// Do something when it has not been found.
}
$chart = Charts::create('bar', 'highcharts')
->title('Total Clients Average Using Time')
->elementLabel("Total")
->labels($time_difference->acu_name)
->values($time_difference->averageTime)
->responsive(false);

Laravel convert resultset to array

Database table SITE has many columns. One of them is site_id. I need all the site_ids as an array since it has to be fed to a method which accepts only a string array.
What I tried so far is:
$sites = DB::select('select site_id from site_tab');
$sites_arr = $sites->toArray();
But this doesn't produce the result I want. I need $sites_arr to be like ['A','B','C',...]
Please suggest a way to get this done. A solution based on Eloquent is also OK for me.
Thanks
Try this:
DB::table('site_tab')->pluck('site_id')->toArray();
reference pluck
referen toArray
If you open a manual, you will see that
The select method will always return an array of results
So, there's no need to use ->toArray(), as result is already an array.
To get values as array of names you can do:
$site_ids = DB::table('site_tab')->pluck('site_id');
Using ->toArray() here is optional, as you can iterate over $site_ids (which is a Collection) with a foreach too.

Laravel get single column result as string

Hello I would like to know is it possible to get column value as string. Instead of array in array:
Current query: Number::limit('1000')->get(['number'])->toArray()
The result at the moment is this:
Preferable result:
Before your toArray() call, add pluck('number'):
$result = Number::limit('1000')->get(['number'])->pluck('number')->toArray();
That's it! This will pluck just the number attributes from your result collection, and give you a single-level array.
The reason this works, is because you are getting a Collection back from get():
All multi-result sets returned by Eloquent are an instance of the Illuminate\Database\Eloquent\Collection object, including results retrieved via the get method or accessed via a relationship.
And the pluck method:
https://laravel.com/docs/5.1/collections#method-pluck
Update
Another, even more succinct method provided by #wunch in the comments:
$result = Number::limit('1000')->lists('number')->toArray();

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;

how to get the where clause in string format using CakePHP3 ORM?

In CakePHP3, there is a ORM that helps with building queries.
From the documentation, I can see that
$query = $articles->find(); // build a query that has not run yet
$query->where(['id' => 1]); // Return the same query object
So in this case, I want the string
WHERE `articles`.`id` = 1
After much googling, I found out that there is a way to return just the where clause of a query object.
$query->where(['id' => 1])->clause('where'); // Return the where clause in the form of a QueryExpression
More googling leads me to find out how to get the QueryExpression to spit out string representation
$query->where(['id' => 1])->clause('where')->sql($valueBinder); // Return the where clause in string format
Here is my problem. I don't know what the $valueBinder is supposed to look like. I don't know how to initialize it.
I am also happy not to use ValueBinder as long as I can get the where clause in string format using CakePHP 3 ORM and in the right SQL dialect. Please assume I am using MySQL.
Please advise.
EDIT
I tried to use $query->valueBinder() as the $valueBinder.
It is empty and does not contain the associated c:0 to the value 1.
To directly answer your question, you can get the SQL for any clause this way:
$binder = new \Cake\ORM\ValueBinder();
$query->clause('where')->sql($binder);
That will return the SQL with the correct placeholders, not with the values to be used. The values live in the $binder variable and are used for statement objects.
As I can see, you only wanted to preserve the internal structure of the where clause to pass it to another query in a different request. Your solution is fine, but I'd like to add that you can also encode a full conditions tree from an existing query:
$where = serialize($query->clause('where'));
$anotherQuery->where(unserialize($where)); // A query in another request
In any case, you need to be careful with what you are unserializing as taking it directly from user input will certainly lead to security problems.
You can choose to omit this param if you like. Please see http://api.cakephp.org/3.0/class-Cake.Database.Query.html#_sql
In addition, you can use the Query member function traverse($visitor, $parts) to isolate the where clause. $visitor is a function that takes a value and a clause. You define the behavior of $visitor. $parts is an array of clause names. I suggest passing array('where') into this param.
My workaround is that I store the conditions in json string format.
Using the same example, what I do is
$data['conditions'] = json_encode(['Articles.id' => 1]); // encode into JSON string
$this->DynamicRules->patchEntity($dynamicRule, $data); // use in edit action of DynamicRulesController
then when I need to reuse the conditions, I do:
$articlesTable = TableRegistry::get('Articles');
$query = $articlesTable->find(); // new query for Articles
$rule = json_decode($dynamicRule->conditions, true); // get back the conditions in associative array format
$query->where($rule); // re-assign the conditions back
This got me what I ultimately wanted.

Categories