I have defined relatioships in models but how can i write complex queries in Eloquent way - sql

I have a query in existing application now i need to update query in eloquent way i have the following structure of my relationships how can i write the following query in eloquent way
Controller Query that i want to change in eloquent way
foreach ($data['Divisions'] as $sections) {
$SecQry1 = "SELECT sections.id, sections.division_id, sections.code, sections.name ,specifications.description
from specifications inner JOIN sections on specifications.section_id=sections.id where specifications.status='active'
AND specifications.manufacturer_id = $user->id AND sections.division_id=" . $sections->id . " group by sections.id";
$SectionsDivision1 = DB::select($SecQry1);
foreach ($SectionsDivision1 as $key => $selectionDiv) {
array_push($selectionDiv_array1, $selectionDiv);
}
}
class Specification extends Model {
protected $table = 'specifications';
public function section()
{
return $this->belongsTo('App\Section');
}
}
class Section extends Model {
protected $table = 'sections';
public function specifications()
{
return $this->hasMany('App\Specification', 'section_id');
}
public function division()
{
return $this->belongsTo('App\Division');
}
}
class Division extends Model {
protected $table = 'divisions';
protected $fillable = array('name', 'description', 'code','status');
public function sections()
{
return $this->hasMany('App\Section', 'division_id');
}
}
0 => {#1063 ▼
+"id": 1
+"division_id": 1
+"code": "03 01 00"
+"name": "Maintenance of Concrete"
+"description": null
}
]

You dont need relations for this specific query, you could use Laravel Eloquent with join like so:
$SectionsDivision1 = Specification::join('sections', 'specifications.section_id', '=', 'sections.id')
->where([
'specifications.status' => 'active',
'specifications.manufacturer_id' => $user->id,
'sections.division_id' => $sections->id
])->select('sections.id', 'sections.division_id', 'sections.code', 'sections.name', 'specifications.description')
->groupBy('sections.id');
I hope it helps

Related

Laravel Eloquent populates collection with id 1 always

I have a project on laravel 5.
I wrote an SQL to select games from database, and after executing it, I got models collection, where every model has id = 1.
This is my query:
select * from `games` left join `game_vendors` on `games`.`vendor_id` =
`game_vendors`.`id` where `game_vendors`.`name` != 'some_vendor' and
`games`.`id` not in (1,2,3,4,5,6,7,8,9,10,11,12);
checked this query in mysql terminal - all is fine, id's are correct, but on postman or in the browser, I got this
array(2021) {
[0]=>
array(32) {
["id"] => int(1)
[1]=>
array(32) {
["id"] => int(1)
...
...
...
[24]=>
array(32) {
["id"] => int(1)
Model class contains this:
class Game extends Model {
protected $table = 'games';
public function vendor()
{
return $this->hasOne('App\GameVendor', 'vendor_id', 'id');
}
Use Laravel Eloquent Relationship and "WHERE NOT IN"
Update Model as
class Game extends Model {
protected $table = 'games';
public function vendor()
{
return $this->hasOne('App\GameVendor', 'vendor_id', 'id')->where('name', '!=' ,'some_vendor');
}
And use Eloquent as
$games = Game::whereNotIn('id',[1,2,3,4,5,6,7,8,9,10,11,12])->get();
foreach($games as $game){
$game->vendor->name
}

How to validate two dimensional array in Yii2

How to validate two dimensional array in Yii2.
passenger[0][name] = bell
passenger[0][email] = myemail#test.com
passenger[1][name] = carson123
passenger[1][email] = carson###test.com
how to validate the name and email in this array
Thanks
Probably the most clean solution for validating 2-dimensional array is treating this as array of models. So each array with set of email and name data should be validated separately.
class Passenger extends ActiveRecord {
public function rules() {
return [
[['email', 'name'], 'required'],
[['email'], 'email'],
];
}
}
class PassengersForm extends Model {
/**
* #var Passenger[]
*/
private $passengersModels = [];
public function loadPassengersData($passengersData) {
$this->passengersModels = [];
foreach ($passengersData as $passengerData) {
$model = new Passenger();
$model->setAttributes($passengerData);
$this->passengersModels[] = $model;
}
return !empty($this->passengers);
}
public function validatePassengers() {
foreach ($this->passengersModels as $passenger) {
if (!$passenger->validate()) {
$this->addErrors($passenger->getErrors());
return false;
}
}
return true;
}
}
And in controller:
$model = new PassengersForm();
$model->loadPassengersData(\Yii::$app->request->post('passenger', []));
$isValid = $model->validatePassengers();
You may also use DynamicModel instead of creating Passanger model if you're using it only for validation.
Alternatively you could just create your own validator and use it for each element of array:
public function rules() {
return [
[['passengers'], 'each', 'rule' => [PassengerDataValidator::class]],
];
}
You may also want to read Collecting tabular input section in guide (unfortunately it is still incomplete).

Laravel 5 joining multiple tables

I am having real problems joining tables in Laravel.
I can join 2 tables but as soon as I try to join a third, i get no data
class Main extends Model
{
protected $table = 'main';
protected $primaryKey = 'id';
public function test()
{
return $this->hasOne('App\Models\Test', 'id', 'id');
}
public function row()
{
return $this->hasOne('App\Models\Row', 'id', 'id');
}
}
class Test extends Model
{
protected $table = 'test';
protected $primaryKey = 'id';
public function main()
{
return $this->belongsTo('App\Models\Main', 'id', 'id');
}
public function rows()
{
return $this->hasMany('App\Models\Row', 'id', 'id');
}
}
class Row extends Model
{
protected $table = 'row';
protected $primaryKey = 'id';
public function main()
{
return $this->belongsTo('App\Models\Main', 'id', 'id');
}
public function rows()
{
return $this->belongsTo('App\Models\Test', 'id', 'id');
}
}
I've added this to my Main model to run a query. This will output the 2 tables
public function scopeGetPart($query, somefield)
{
return $query->with('test.main')
->where('somefield', somefield);
}
This works when i run it through phpMyAdmin. I want to write this the Laravel way
SELECT * FROM
main
INNER JOIN test ON
main.id = test.id
INNER JOIN row ON
main.id = row.id
AND main.my_field = row.my_field
WHERE somefield = 103288
Without running your code, have you tried $main->with('test.rows')? This should fetch the tests of a main instance with the rows of the test.
I gave up with Eloquent as it was causing problems and used this instead which works how i wanted
DB::table('main')
->join('test', 'main.id', '=', 'test.id')
->join('row', function ($join) {
$join->on('main.id', '=', 'row.id')
->whereRaw('main.my_field= row.my_field');
})
->where('somefield', '103288');

Phalcon query builder can't get joined table data

I have 2 table 'sanpham' and 'danhmuc'. I use phalcon query builder to get data from 2 tables.
$laytin = $this->modelsManager->createBuilder()
->from("sanpham")
->innerJoin('danhmuc','sanpham.danhmuc=danhmuc.sodanhmuc')
->where('sanpham.sosanpham = '.$id.'')
->getQuery()
->getSingleResult();
$breadcrumbs = array('/' => Tool::getTranslation()->_('trangchu'),"/Loai-san-pham/".$laytin->tendep."/".$laytin->sodanhmuc => $laytin->tendanhmuc,'' => $laytin->tieudesanpham );
The query runs, but $laytin->tendep, $laytin->sodanhmuc, $laytin->tendanhmuc in 'danhmuc' table doesn't display. Every column in 'sanpham' table (such as: $laytin->tieudesanpham) displays properly.
You can add specific columns with:
$this->modelsManager->createBuilder()->columns('danhmuc.tend‌​ep, danhmuc.sodanhmuc')
With this method you will have to add each column you want in your output. QueryBuilder docs.
Another method is to query the Sanpham model.
For example:
class Sanpham extends \Phalcon\Mvc\Model
{
public static function findSomething($something)
{
// this is your actual query, it replaces the queryBuilder
return self::query()
->where('sanpham.sosanpham = :id:', ['id' => $something])
->innerJoin('danhmuc', 'sanpham.danhmuc = danhmuc.sodanhmuc')
->execute()->getFirst();
}
public function initialize()
{
// define the relation to danhmuc
$this->belongsTo('danhmuc', 'danhmuc', 'sodanhmuc');
}
}
class Danhmuc extends \Phalcon\Mvc\Model
{
public function initialize()
{
// there are other options besides "hasMany", like "hasOne".
// this is your relation to sanpham
$this->hasMany('sodanhmuc', 'sanpham', 'danhmuc');
}
}
class YourController extends \Phalcon\Mvc\Controller
{
public function testAction()
{
// get your first record in Sanpham matching "12345"
$sanpham = Sanpham::findSomething(12345);
// from your Sanpham object, get the related danhmuc object.
// this works because we defined the relations (belongsTo and hasMany)
$danhmuc = $sanpham->getRelated('danhmuc');
// now you have access to the values of danhmuc via the $danhmuc variable
$breadcrumbs = [
'/' => Tool::getTranslation()->_('trangchu'),
"/Loai-san-pham/" . $danhmuc->tendep => $danhmuc->tendanhmuc,
'' => $danhmuc->tieudesanpham,
];
}
}
Check the Phalcon model docs for more info on this.

Laravel : How to get the first record of each collections in a 'with' function query

I want to get a collection of all artists with their latest image only.
The following code returns a collection of all artists but with only one image associated with the first artist.
$data = Artist::with(['images' => function($q){
$q->first();
}])
->get();
return $data;
My models:
class Artist extends Model {
public function images()
{
return $this->belongsToMany('App\Image');
}
}
class Image extends Model {
public function artists()
{
return $this->belongsToMany('App\Artist');
}
}
You can set in you modal:
public function FirstImage()
{
return $this->hasOne('image');
}
then:
$data = Artist::with('FirstImage')->get();