Use RAW Eloquent Queries with Slim PHP - php

I am working on a project with SlimPHP and Eloquent.
I am trying to run a RAW SQL query within a Model's method, like this:
/models/Form.php
<?php
namespace models;
class Form extends \Illuminate\Database\Eloquent\Model {
protected $table = 'forms';
public function getResponses($form_id)
{
// HERE
$select = \Illuminate\Support\Facades\DB::select('select 1');
return 1;
}
}
I am using Capsule to bootstrap the ORM.
The code above gives me:
Fatal error: Call to a member function select() on a non-object in
/vagrant/vendor/illuminate/support/Illuminate/Support/Facades/Facade.php
on line 208
Documentation is of very help in this case, could you shed some light on this?
thanks

Read the setup instructions on github closely and make sure you follow them correctly.
With Capsule you should use Illuminate\Database\Capsule\Manager or as DB "Facade".
$select = \Illuminate\Database\Capsule\Manager::select('select 1');
I usually import it and define an alias:
use Illuminate\Database\Capsule\Manager as DB;
// ...
$select = DB::select('select 1');

Plus if you need to do raw query, it may help to call setAsGlobal() after bootEloquent() like this
$capsule->addConnection($sqliteDb);
$capsule->bootEloquent();
$capsule->setAsGlobal(); // <--- this

In Slim 4,
we can use $this->getConnection()->select($sql);
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model{
protected $table = 'products';
public $timestamps = false;
protected $fillable = ["name", "price", "quantity", "supplier", "image", "category"];
public function getProductsByCategory(){
$sql = 'SELECT p.id,
p.name,
p.price,
p.quantity,
p.supplier,
p.image,
p.category,
(SELECT IF(COUNT(*) >= 1, TRUE, FALSE) FROM favorite f WHERE f.user_id = 1 AND f.product_id = p.id) AS isFavourite,
(SELECT IF(COUNT(*) >= 1, TRUE, FALSE) FROM carts c WHERE c.user_id = 1 AND c.product_id = p.id) AS isInCart
FROM products p';
return $this->getConnection()->select($sql);
}
}

Related

How to use orderby on element that was joined with Laravel Eloquent method WITH

The problem is that the query can't find the specific_method(specific_method, specific_model,SpecificModel,specificMethod etc...), that should been joined with the method WITH from Laravel Eloquent. Any ideas how to solve it?
My code:
//SpecificModel
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SpecificModel extends Model {
protected $guard_name = 'web';
protected $table = 'SpecificTable';
protected $guarded = ['id'];
public function specificMethod(){
return $this->belongsTo('App\Models\AnotherModel','AnotherModel_id');
}
}
//AnotherModel
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class AnotherModel extends Model {
protected $guard_name = 'web';
protected $table = 'AnotherTable';
protected $guarded = ['id'];
}
//Query method
$model = app('App\Models\SpecificModel');
$query = $model::with('specificMethod:id,title');
$query = $query->orderBy('specific_method.title','desc');
return $query->get();
//Error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column
'"specific_method.title"' in 'order clause' (SQL: select * from
`SpecificModel` where `SpecificModel`.`deleted_at` is null order by
`specific_method`.`title` desc)
This happens because the belongsTo relationship does not execute a join query as you expect it to (as you can see from the error you get). It executes another query to get the related model(s). As such you will not be able to order the original model by related models columns.
Basically, 2 queries happen:
Fetch the original model with SELECT * from originalModel ...*
Fetch the related models with SELECT * from relatedModel where in id (originalModelForeignKeys)
Then Laravel does some magic and attaches the models from the 2nd query to the correct models from the first query.
You will need to perform an actual join to be able to order the way you want it to.

How can I implement SUM() in Laravel relations?

Here is my query which works as well:
SELECT sum(r.rating) as rank,b.* FROM books as b
LEFT JOIN ranks as r ON b.id = r.book_id
WHERE 1
GROUP BY (b.id)
ORDER BY rank DESC
Now I want to do the same in Laravel. Here is what I've tried:
// Book model
class Book extends Model
{
public function ranks()
{
return $this->hasMany(Rank::class)->sum("rating");
}
}
// Controller
$obj = new Book;
$get = $obj->ranks()->orderBy('rating', 'desc')->get();
It throws this error:
Call to a member function groupBy() on integer
Any idea how can I fix this problem?
public function ranks() {
return $this->hasMany(Rank::class)
->select('book_id', \DB::raw('sum(`rating`) as `rank`'))
->groupBy('book_id');
}
$books = Book::with('ranks')->get();
$sortedBooks = $books->sortByDesc(function($book) {
return $book->ranks->sum('rank');
});

Convert MySQL query to Laravel (5.5) Query Builder

I have a problem tying to convert the following MySQL query to the Laravel (5.5) Eloquent query builder.
$start = '2018-01-22'; // Some random starting point for the Query
$query = "SELECT * FROM cdr c WHERE soort=3 AND con_duur > 0 AND con_duur
>= (select kortbel_seconden from queue q where q.queue_id=c.queue_id) AND `start_tijd >= '$start'";`
I have the following Models:
// CDR Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CDR extends Model
{
protected $table = 'cdr';
protected $primaryKey = 'cdr_id';
public function Queue()
{
return $this->hasOne('App\Models\Queue', 'queue_id', 'queue_id');
}
}
// Queue Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Queue extends Model
{
protected $table = 'queue';
protected $primaryKey = 'queue_id';
public function cdr()
{
return $this->belongsTo('App\Models\CDR', 'queue_id', 'queue_id');
}
}
So far I have the following code in my Controller:
App\Models\CDR::with('queue')
->where('soort', '3')
->where('con_duur', '>', '0')
->where('start_tijd', '>=' , $start)
->where('con_duur', '>=', ' ') // this is where the sub select from the `queue` table should be : (select kortbel_seconden from queue q where q.queue_id=c.queue_id)
->get();
I’m stuck at the point of the sub select, is there a way to do this with Laravel’s Query Builder?
Thanks!
Consider this code:
DB::table('cdr AS c')
->select("*")
->where('c.soort','=',3)
->where('c.con_duur','>',0)
->where('c.con_duur','>=',function($query){
$query->select('kortbel_seconden')
->from('queue AS q')
->where('q.queue_id', '=', 'c.queue_id');
})
->where("c.start_tijd",">=",$start)
->get();
This part of the query:
->where('c.con_duur','>=',function($query){
$query->select('kortbel_seconden')
->from('queue AS q')
->where('q.queue_id', '=', 'c.queue_id');
})
is used to achieve the below part of the query:
`c`.`con_duur` >=
(SELECT
kortbel_seconden
FROM
queue q
WHERE q.queue_id = c.queue_id)
The above query results can be achieved by the following query as well through join:
DB::table('cdr AS c')
->select("c.*")
->join('queue AS q', 'q.queue_id', '=', 'c.queue_id')
->where('c.soort','=',3)
->where('c.con_duur','>',0)
->where('c.con_duur','>=','q.kortbel_seconden')
->where("c.start_tijd",">=",$start)
->get();
For more details you can visit:
https://laravel.com/docs/5.5/queries#where-clauses

Get username with queryBuilder join using FOSUserBundle

I use FOSUserBundle, and I need to get the user names who wrote comments on my post.
I use function createQuery to get the post comments, and add this join to trying to get the names:
<?php
namespace CommentsBundle\Entity;
use FOS\UserBundle\Entity\User;
/**
* CommentsRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class CommentsRepository extends \Doctrine\ORM\EntityRepository
{
public function getPostComments($planId)
{
$arrPlanComments = array();
$query = $this->getEntityManager()->createQuery(
'SELECT
c.id,
c.fkUser,
c.fkReply,
c.comment,
c.createdAt,
c.likes,
c.unlikes
FROM CommentsBundle:Comments c
INNER JOIN UserBundle:User u
WITH (c.fkUser = u.id)
WHERE
c.fkPlan = :planId
ORDER BY c.createdAt DESC'
)->setParameter('planId', $planId);
try
{
$arrPlanComments = $query->getArrayResult();
}
catch(\Doctrine\ORM\NoResultException $ex)
{
echo $ex->getMessage();
}
return $arrPlanComments;
}
}
I have extended the FOSUserBundle to my custom bundle named 'UserBundle', and it works fine, but I don't know how to add the relationship with this entity.
I am having this error when i add the join relationship:
[Semantical Error] line 0, col 164 near 'UserBundle:User': Error: Class 'UserBundle\Entity\User' is not defined.
What is wrong?
According to the documentation, you have to create own class for User entity, which will extend one provided by FOSUser. It seems like you haven't done that. That's what your error message probably indicates.

Yii CDbCriteria Join

How I can write the query
SELECT *
FROM doc_docs dd
JOIN doc_access da
ON dd.id=da.doc_id
AND da.user_id=7
with CDbCriteria syntax?
You actually cant completely write that since you have to apply the criteria to an activerecord model to obtain the primary table, but assuming you have a DocDocs model you can do it like this:
$oDBC = new CDbCriteria();
$oDBC->join = 'LEFT JOIN doc_access a ON t.id = a.doc_id and a.user_id = 7';
$aRecords = DocDocs::model()->findAll($oDBC);
Although it might be a lot easier if you give your DocDocs model a relation with doc_access, then you don't have to use the dbcriteria:
class DocDocs extends CActiveRecord
{
...
public function relations()
{
return array('access' => array(self::HAS_MANY, 'DocAccess', 'doc_id');
}
...
}
$oDocDocs = new DocDocs;
$oDocDocs->id = 7;
$aRecords = $oDocDocs->access;
Should give you a fairly good idea how to start...

Categories