QueryException in laravel 5.6 - php

I have converted an sql into laravel query so I came with this below.
DB::table('posts')
->select('posts.*', DB::raw('GROUP_CONCAT(l.name ORDER BY l.id) as location_name'))
->join('locations as l', "posts.location_ids", "=", "l.id")
->whereRaw('FIND_IN_SET(l.id, posts.location_ids) > 0')
->where("posts.status", 'active')
->groupBy('posts.id')
->get();
But it gives me an error.
SQLSTATE[42000]: Syntax error or access violation: 1055 'laraveltest.posts.title' isn't in GROUP BY (SQL: select `posts`.*, GROUP_CONCAT(l.name ORDER BY l.id) as location_name from `posts` inner join `locations` as `l` on `posts`.`location_ids` = `l`.`id` where FIND_IN_SET(l.id, posts.location_ids) > 0 and `posts`.`status` = active group by `posts`.`id`)
When I run this query into any mysql tool, it returns row without any fail. why laravel giving me errors?

This is a setting in laravel/mysql for laravel look in config/database.php.
Set strict mode to false
'connections' => [
'mysql' => [
'strict' => false,
]
Laravel is not giving you the error it's just actually enforcing MYSQL rules. PHPMYADMIN and other tools don't force it so that's why you don't get the error.

The reason laravel is so good, is because you can get rid of writing huge database queries like this.
You should take some time out to really site down and read the documentation for laravel and how eloquent works. You will be surprised how quickly you pick it up, i promise.
Now for a situation such as your self, you have two models.
Post Model
Location Model
In your Posts model you would create a relationship like so
public function location()
{
return $this->belongsTo(Location::class);
}
and in your Location model you would now define a relationship like so
public function post()
{
return $this->hasMany(Post::class);
}
Now in your posts_table you need to ensure you have a location_id integer column.
Now what you can do is get the Location instance you want for example:
//This will give you the row where id = 1
$location = Location::find(1);
Now you can easily do this to access all the posts with that location:
foreach($location->posts as $post){
//Do whatever you want here $post is the object
echo $post->title
}
And the relationship works on the inverse, example:
$post = Post::find(1);
Now because this post belongs to only 1 location you can call it like so
echo $post->location->column_name_in_location_table
Hope this helps kick start your journey to learning laravel!

Related

Eloquent - Call to undefined relationship

I have a users table and a permissions table. It's a many-to-many relationship so I also have a users_permissions table with a user_id & module_permission_id column.
The user model has the following relationship:
public function permissions()
{
return $this->belongsToMany(Permission::class, 'users_permissions', 'user_id', 'module_permission_id');
}
When I run my query, the result contains an empty permissions array.
User::with('permissions');
If I echo the query in the with, I get the error: Call to undefined relationship [] on model [App\Models\User]
User::with(['permissions', function($q) {
echo $q->toSql();
die();
}]);
The rest of the query works, it's just trying to get permissions which is failing.
In my case it was a coding convention issue related to camelCase vs. snake_case:
In the Model there was
public function getPermissions()
and in the query there was
User::with(['get_permissions'])
When I changed this to
User::with(['getPermissions'])
it started to work, although I'd say the Laravel way would be to use snake_case instead.
This confused me for a couple of days since frameworks like Symfony and AngularJs has a mixed conventions that somewhere you need to write parameters in snake_case and somewhere else in camelCase. I didn't find any documentation on Laravel site how they handle this, so I tried it the Straight Way and it seemed to be the case here :)
Maybe you just forgot the ->get() after User::with('permissions')->get() ?
https://laravel.com/docs/5.0/eloquent#eager-loading
Slapping this here for anyone who may be trying to refactor from an eager load that selects columns to an eager load with a scoped query.
You HAVE to move the selecting of columns into the scoped query, trying to select columns with the usual colon notation will fail and throw the undefined relationship error.
For example going from this eager load that selects a pivot table column, and a column from the permissions table User:with('permissions:permission_tag:tag_set_id,permission_name') to a scoped query that selects the same columns but also orders the results looks like this
User::with([
'permissions' => function ($query) {
$query->select('permission_tag:tag_set_id', 'permission_name');
$query->orderBy('permission_name');
},
]);
Notice I pulled out the : notation and it lives right in the scoped query.

Laravel Querying Views

I have a view like this:
CREATE VIEW orders_sales AS
SELECT code, SUM(quantity) * SUM(sale_price) as product_total, shop_id
FROM `orders`
GROUP BY code, product_id
I am trying to query it like this:
$data = DB::table('orders_sales')->get();
I am getting the following error:
SQLSTATE[42000]: Syntax error or access violation: 1055
'pakishops2.orders.shop_id' isn't in GROUP BY (SQL: select * from
orders_sales)
I am able to query it in phpmyadmin like select * from orders_sales but it wont query with Laravel.
enter image description here
EDIT:
I have changed view name to view_saleorders, still no luck
Go to the config/database.php file and check if the option strict is set to true.
Set it to false and you query will work.
Try alternative now,
Create model with that name as laravel standard,
like
class ViewOrders extends Eloquent
Add namespaces required inside model if any.
then create class variable as
protected $table = 'your-view-name';
And now check data by getting like,
ViewOrders::all();
And check if you are getting data.
add strict => false in config/database.php.
If this is set to true then it'll add the ONLY_FULL_GROUP_BY when querying.
Alternative to be more specific with modes,
'modes' => [
'NO_ZERO_DATE',
'ONLY_FULL_GROUP_BY',
],
Sorry to revive an old post, but your view is wrong. You need to match your columns to your GROUP BY clause.
Either change shop_id to product_id, or product_id to shop_id.
-- This is wrong.
CREATE VIEW orders_sales AS
SELECT code, SUM(quantity) * SUM(sale_price) as product_total, <!shop_id!>
FROM `orders`
GROUP BY code, <!product_id!>

Laravel/Eloquent - Order By a Model's Relationship Without Using Table Names

I have a Person eloquent model that belongsTo an Address. My Laravel version is 4.2.5 and I am using PostgreSQL.
class Person extends Eloquent {
public function address() {
return $this->belongsTo('Address');
}
}
My aim is to get a collection of Person resources that are sorted by the address_1 field of their related Address model.
I can accomplish this by referencing table names as show below, but I want to do it instead with Eloquent relationships, since I do not want to deal with tables for abstraction purposes.
Person::join('addresses', 'persons.id', '=', 'addresses.person_id')
->orderBy('address_1', 'asc')->get();
I have attempted the following Eloquent method without success.
Person::with('address')->whereHas('address', function($q)
{
$q->orderBy('address_1', 'asc');
})->get();
This query fails with the error message:
Grouping error: 7 ERROR: column \"addresses.address_1\" must appear in the
GROUP BY clause or be used in an aggregate function
In response to this, I tried adding this line above the orderBy statement which causes the query to succeed, but the ordering has no effect on the resulting Person collection.
$q->groupBy('address_1');
I would much appreciate a solution where I do not have to reference table names if it is possible. I have exhausted all resources on this subject, but surely this is a common use case.
Here you go:
$person = new Person;
$relation = $person->address();
$table = $relation->getRelated()->getTable();
$results = $person->join(
$table, $relation->getQualifiedForeignKey(), '=', $relation->getQualifiedOtherKeyName()
)->orderBy($table.'.address_1', 'asc')
->get();

Yii - Joining multiple tables using active record

I am currently working on a YII application, which I must admit is my first attempt. I am having difficulty mastering the active record component of YII. In particular I would like to join three tables using with().
My mysql tables are as follows:
video_specific
- id (primary key)
- random_id
- user_id
- video_link
- quality (enum, high,low)
video_details
- video_id
- upvote_count
- downvote_count
- timestamp
ladder_videos
- ladder_id
- video_id
ladder_specific
- id
- random_id
- name
- description
- ladder_type
- status
- video_count
Thus after using the gii tool I was give models with the following relationships. Please note that I did not create a model for the ladder_videos table.
In videoSpecific model
'ladderSpecifics' => array(self::MANY_MANY, 'LadderSpecific',
'ladder_videos(video_id, ladder_id)'),
'videoDetails' => array(self::HAS_ONE, 'VideoDetails', 'video_id')
In ladderSpecific model
'videoSpecifics' => array(self::MANY_MANY, 'VideoSpecific',
'ladder_videos(ladder_id, video_id)')
With these relations I thought I could right the following query
$ladders = LadderSpecific::model()->with(
array('videoSpecifics'=>array('select'=>'id,video_link,random_id',
'join'=>'videoDetails')))->findAll();
But I get the following error
CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: Syntax error or
access violation: 1064 You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'videoDetails'
at line 1. The SQL statement executed was: SELECT `t`.`id` AS `t0_c0`, `t`.`random_id` AS
`t0_c1`, `t`.`name` AS `t0_c2`, `t`.`description` AS `t0_c3`, `t`.`ladder_type` AS
`t0_c4`, `t`.`status` AS `t0_c5`, `t`.`video_count` AS `t0_c6`, `videoSpecifics`.`id` AS
`t1_c0`, `videoSpecifics`.`video_link` AS `t1_c3`, `videoSpecifics`.`random_id` AS `t1_c1`
FROM `ladder_specific` `t` LEFT OUTER JOIN `ladder_videos` `videoSpecifics_videoSpecifics`
ON (`t`.`id`=`videoSpecifics_videoSpecifics`.`ladder_id`) LEFT OUTER JOIN `video_specific`
`videoSpecifics` ON (`videoSpecifics`.`id`=`videoSpecifics_videoSpecifics`.`video_id`)
videoDetails
Any ideas why?? Please limit your answers to active record, and not DAO or query builder. Thanks
It would help to review how relations work in Yii.
http://www.yiiframework.com/doc/guide/1.1/en/database.arr
When querying the model, Yii automatically generates the query to fetch the relational data, so you don't have to supply it.
You must therefore supply the name given to your relation.
$ladders = LadderSpecific::model()->with('videoSpecifics')->findAll();
SO the answer was to update the ladderSpecific relations. So once you update them they should like this:
public function relations(){
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'ladderDetails' => array(self::HAS_ONE, 'LadderDetails', 'ladder_id'),
'videoSpecifics' => array(self::MANY_MANY, 'VideoSpecific', 'ladder_videos(ladder_id, video_id)'),
array(self::HAS_ONE, 'VideoDetails', 'video_id'),
);
}
Once you have updated this relation you can do this:
$ladders = LadderSpecific::model()->with(
array('videoSpecifics.videoDetails'=>
array(
'order'=>'videoDetails.upvote_count - videoDetails.downvote_count DESC',
'limit'=>'1'
)))->findAll(array('order'=>'name',));
The only issue is for some reason I can not limit the number of records returned. Once I figure that out I will update my answer. If you have a better way of doing it let me know.

How to run a query in Laravel 4 using eloquent

I have read the documentation but I can't quite figure out how to run the following query in Laravel 4
SELECT
COUNT(*)
FROM
acl a,
routes r
WHERE
(a.user_id = 1 OR
a.group_id IN(SELECT group_id FROM user_group_junction WHERE user_id = 1)) AND
r.route = 'protected' AND
a.routes_id = r.id;
So how would I run the query in Laravel 4 using eloquent?
Yes each table has a model and relationships are defined
Based on my selected answer the following is what I came up with (And works)
Acls::join('routes','routes.id','=','acl.routes_id')
->where('routes.route','=','protected')
->Where(function($in_parenthesis) use($user_id){
$in_parenthesis->whereIn('acl.group_id',function($where_in) use($user_id){
$where_in->select('group_id')
->from('user_group_junction')
->where('user_id','=',$user_id);
})
->orWhere('acl.user_id','=',$user_id);
})
->count();
Methods called on Eloquent models pass through to the Illuminate\Database\Eloquent\Builder class, which itself extends from the Illuminate\Database\Query\Builder class. This means that all the things you can do with the query builder, you can also do with Eloquent models. The exception being that you don't need to define the table.
So for example if you wanted to perform a join and a where like you've done above, you would just do:
$query = Acl::join('routes', 'acl.routes_id', '=', 'routes.id')
->where('routes.route', '=', 'protected');
$results = $query->get();
Obviously this isn't your whole query, but you can figure out the rest.

Categories