Error in Laravel 5.2 Eloquent - cannot be converted to String - php

I am very new to Laravel and am going through the tutorials and am stuck on something.
I have a complex query that I need to reuse with one parameter change in the where clause. I added this as a query scope in my Model and then call it from my corresponding Controller. When I try to return the data though I am getting this error:
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string
Here is the query scope:
public function scopeCrosstab($wellID)
{
return static::select('sampleDate', \DB::raw("
max(if(chemID=1, pfcLevel, ' ')) as 'PFOA', max(if(chemID=1, noteAbr, ' ')) as 'PFOANote'
"))
->leftJoin('SampleNote', 'WellSample.noteID', '=', 'SampleNote.noteID')
->where('wellID', '=', $wellID)
->groupBy('sampleDate');
}
Here is the Controller code:
public function smith()
{
$wellSamples = WellSample::crosstab(2);
return $wellSamples->get();
//return view('pages.wellsample', compact('wellSamples'));
}
I have tried many different permutations of the code with quotes, with double quotes etc. If I hard code the value in the query scope it works, but I need to be able to make it dynamic.

Scope methods take at least one parameter, the first of which must be $query. You then build off of the query variable that is passed to your scope method. Like this:
public function scopeCrosstab($query, $wellID)
{
return $query->select('sampleDate', \DB::raw("
max(if(chemID=1, pfcLevel, ' ')) as 'PFOA', max(if(chemID=1, noteAbr, ' ')) as 'PFOANote'
"))
->leftJoin('SampleNote', 'WellSample.noteID', '=', 'SampleNote.noteID')
->where('wellID', '=', $wellID)
->groupBy('sampleDate');
}

Related

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'role_not' ERROR

I am trying to display users other than super_admin so I used whereRoleNot Function in my controller to hide super_admin .
My User Model:
public function scopeWhereRole($query, $role_name){
return $query->whereHas('roles', function($q) use($role_name){
return $q->whereIn('name', (array)'$role_name');
});
} //end of scopeWhereRole
public function scopeWhereRoleNotIn($query, $role_name){
return $query->whereHas('roles', function($q) use($role_name){
return $q->whereNotIn('name', (array)'$role_name');
});
} //scopeWhereRoleNotIn end
And User controller index method:
public function index()
{
//
$users= User::whereRoleNot('super_admin')->paginate(3);
return view('dashboard.users.index', compact('users'));
} //end of index
The core issue is that you had a typo when using your scope, but due to the way you named your scope, it was still a valid where{column} clause.
Laravel has dynamic functions, like where{column}($search) that constructs a simple where clause for the {column} value and $search value provided. Take your example:
$users = User::whereRoleNot('super-admin');
whereRoleNot tries to create a where clause for the column, in your case, role_not (dynamically constructed from the string RoleNot), and your database table does not have this column.
Simply use a normal where clause:
$users = User::where('role', '!=', 'super_admin')->paginate(3);
Edit: If you want to use a scope, I'd suggest you change the name a bit:
public function scopeRoleIn($query, $role_name){
return $query->whereHas('roles', function($q) use($role_name){
return $q->whereIn('name', (array)$role_name); // Don't use `'` here
});
}
public function scopeRoleNotIn($query, $role_name){
return $query->whereHas('roles', function($q) use($role_name){
return $q->whereNotIn('name', (array)$role_name); // Don't use `'` here
});
}
Then, use your scope as follows:
// $users = User::roleIn('super-admin')->paginate(3); // Etc...
$users = User::roleNotIn('super-admin')->paginate(3);
You may use scopeWhere..., but that naming potentially conflicts with Laravel's dynamic where{column} clauses, so you should avoid it.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'role_not'
ERROR
It's because Laravel is expecting that you have a column 'role_not' in your User table considering that your local scope was named scopeWhereRoleNotIn, remove the prefix scope and it's final name will become WhereRoleNotIn yet you are calling the scope name as WhereRoleNot. Now you know why column 'role_not' is the error because Laravel is expecting that you were not already using local scope.
Now, to call this local scope, your query should look like this
public function index()
{
$users= User::whereRoleNotIn('super_admin')->paginate(3);
return view('dashboard.users.index', compact('users'));
}
Even if 'where' is a reserved keyword it will still works
It's jut a matter of you missed to call the exact name of your local scope that is why Laravel is treating it as an where clause for your query builder.
please read docs local scope

Using a Laravel model method in an Eloquent query

This is for Laravel 5.2. I have a method defined as follows in my Users model:
public function name()
{
return "$this->name_first $this->name_last";
}
I'm trying to figure out how to use that as part of a query, but it seems like it isn't possible for a somewhat obvious reason: the database doesn't know anything about the method and that makes perfect sense. However, the concept of what I'm trying to achieve makes sense in certain contexts, so I'm trying to see if there's a way to accomplish it naturally in Eloquent.
This doesn't work, but it represents what I'm trying to accomplish:
public function index(Request $request)
{
$query = new User();
if(Request::has('name')) {
$query = $query->where('name', 'LIKE', '%' . Request::input('name') . '%');
}
return $query->get();
}
In short, the database only knows about name_first and name_last, but I'd like to be able to search (and sort) on name without storing it. Maybe storing the concatenated name is no big deal and I should just do it, but I'm also trying to learn.
I agree with Bogdan, The issue of having spaces either in the first or the last name makes querying on the individual columns difficult, so this is probably the way to go. Code reuse can be increased by defining it as a custom scope:
https://laravel.com/docs/5.2/eloquent#local-scopes
// class User
public function scopeOfFullNameLike($query, $fullName)
{
return $query->whereRaw('CONCAT(name_first, " ", name_last) LIKE "%?%"', [$fullName]);
}
// ...
User::ofFullNameLike('john doe')->get();
That would mean you should be concatenating the column value at the database level. Which means you could use CONCAT and a whereRaw clause:
$query->whereRaw('CONCAT(name_first, " ", name_last) LIKE ?', ['%' . Request::input('name') . '%']);
Or as an alternative if you want the full name to be selected as part of the result, you could concatenate within the select and use having instead of where to be able to use a column alias:
$query->select('*', DB::raw('CONCAT(name_first, " ", name_last) as name'))
->having('name', 'LIKE', '%' . Request::input('name') . '%');
Not the most compact solutions, but things involving MySQL functions need some raw SQL to work with the Query Builder.

Automatic object append

I created a class which generates queries based on arguments I feed it via PHP object chaining. Select, insert, update and delete all define $this->query so nothing is left over from previous calls.
Here is an example, keeping in mind that where() might be succeeded by order(), limit(), etc.
$tQuery->select('id', 'users')
->where('email', '=', $email)
->end();
All end() does is append a ; to the SQL statement and returns it as a string, so it seems a bit intrusive using it in every single call.
public function end()
{
$this->query .= ';';
return $this->query;
}
Is there a way (magic method or otherwise) I can automatically do this each time I call the class so I don't require this method every time?
$tQuery->select('id', 'users')
->where('email', '=', $email);
i.e. "You're not asking me for any more methods, I'll just return what I have with a ; at the end"
I guess that the result of end() is used by some pdo to execute the final query. This means, you need a string-presentation of your query-object in the end. Here, php's type-casting may come in handy. There is a magic method available for objects when using them as string, __toString()
Consider this example:
<?php
echo $tQuery->select('id', 'users')
->where('email', '=', $email)
->end();
Now, add a __toString() method to your class:
public function __toString()
{
return $this->end();
}
And you may rewrite the above to
<?php
echo $tQuery->select('id', 'users')
->where('email', '=', $email);
This works for any object that is used in a string-context, e.g. this also triggers __toString():
<?php
$sqlString = (string)$tQuery->select('id', 'users')
->where('email', '=', $email);

Undefined Variable Multiple Query Scopes Laravel

This work perfect:
public function scopeHBO($query)
{
return $query ->where('network', '=', "hbo");
}
Call in Controller: It Works!
$events = Schedule::HBO()->orderBy('searchdate')->get();
When I add another Query Scope like so:
public function scopeHBO($query)
{
return $query
->where('network', '=', "hbo")
->where('searchdate', '>=', 'NOW()');
}
OR:
public function scopeDate($query)
{
return $query->where('searchdate', '>= ', 'NOW()');
}
Then call in the controller:
$events = Schedule::HBO()->Date()->orderBy('searchdate')->get();
I get an error: Undefined variable: event. I tried with with Raw MySql in the same model and it works. Whenever i add a query scope, does not matter what it is.. i get that same error Undefined variable: event.
NOW() is a function, so you need to use a raw query:
where('searchdate', '>=', DB::raw('NOW()'))
Then you can use the scopes. (Do note that I think scopeDate must be called as date(), not Date() - not 100 % sure on that though.)
This sounds less like a generic problem with Laravel, and more like a problem with you specific application.
My guess (which is a wild guess), is that adding that second where clause in your scope method
return $query
->where('network', '=', "hbo")
->where('searchdate', '>=', 'NOW()');
ended up creating a SQL query that returned 0 rows. Then, somewhere in your other code you're doing something like
foreach($events as $event)
{
//...
}
//referencing final $event outside of loop
if($event) { ... }
As I said, this is a wild guess, but the problem doesn't seem to be your query code, the problem seems to be the rest of your code that relies on the query returning a certain number of, or certain specific, rows/objects.

Only query "Where" if there is a value in Laravel eloquent

I have a search query that needs to be done. However, a search doesn't always have all values set, like in this case.
$aEvents = DB::table('events')
->where('client_id', '=', $client_id);
The question is, how can I make this where statement depend on the value of $client_id. So if the value is empty I don't want the Where statement to occur.
Also, I do not want to write several complete queries with if statements in PHP. To many variables. Ideally I'd like something like this:
$aEvents = DB::table('events')
->(($client_id != "") ? where('client_id', '=', $client_id) : "");
Using eloquent is (really!) nice and save, but I'm not yet up to speed with if statements in std Class objects I guess. Any help is appreciated.
You may try something like this:
$query = DB::table('events');
if(!empty($client_id)) {
$query->where('client_id', $client_id);
}
$aEvents = $query->get(); // Call this at last to get the result
If you are passing client_id to the server via a form/query string(user input) then you may try something like this:
if($client_id = Input::get('client_id')) {
$query->where('client_id', $client_id);
}
Update: For pagination try this:
$aEvents = $query->paginate(10); // For 10 per page
So you may call links() method in your view if you pass it like this:
return View::make('viewName')->with('aEvents', $aEvents);
In the view for pagination links:
$aEvents->links()
You can also use query scopes in the model for this purpose. Scopes allow you to easily re-use query logic in your models. In the model Event, you can add the following query scope:
public function scopeClientID($query, $client_id)
{
if ($client_id != '') {
return $query->where('client_id', '=', $client_id);
} else {
return $query;
}
}
Then from your controller or wherever you're calling it from, you can do the following:
$aEvents = Event::clientID($client_id);
If you want to get all the results, then you can do:
$aEvents = Event::clientID($client_id)->get();
Or if you want pagination, you can do:
$aEvents = Event::clientID($client_id)->paginate();
You can also chain it with other methods like you'd do in a eloquent query.
You can read more about model query scopes at http://laravel.com/docs/eloquent#query-scopes

Categories