Eloquent filter on method - eloquent

I have 2 tables items and naws.
With
Item::where( 'items.item_type' , '=' , $pagetype)->get();
I retrieve the object perfect, but now i wan t to filter on area in the naws table.
How can i achieve that?
Model Item:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Item extends Model
{
protected $table = 'items';
public function naw()
{
return $this->hasOne('App\Naw');
}
}

Awnser:
return Item::with([
'naw' => function($query) use ($slug)
{
$query->whereArea($slug);
}
])->where( 'items.item_type' , '=' , $pagetype)->get();

Related

Using "With" and BelongsTo on a model which has a defined table name causes a NULL to be returned

What I am finding is that the "picker" data does not get returned when using "with" but does if I use the default lazy loading query. It seems it might be down to the fact that the "picker" table uses a table name of "users".
So I have the following tables.
USERS [id, name]
PRODUCTS [id, name, picker_id]
I have created the following models.
class User extends BaseModel {
protected $hidden = array('pivot');
public function roles() : \Illuminate\Database\Eloquent\Relations\BelongsToMany {
return $this->belongsToMany(Role::class);
}
}
class Product extends BaseModel {
public function picker() : \Illuminate\Database\Eloquent\Relations\BelongsTo {
return $this->belongsTo(Picker::class);
}
}
class Picker extends User {
protected $table = 'users';
public function products() : \Illuminate\Database\Eloquent\Relations\HasMany {
return $this->hasMany(Product::class, 'picker_id');
}
public function pickingSequence() : \Illuminate\Database\Eloquent\Relations\HasOne {
return $this->hasOne(PickingSequence::class);
}
protected static function boot() {
parent::boot();
static::addGlobalScope('status', function (\Illuminate\Database\Eloquent\Builder $builder) {
$builder->join('role_user', 'role_user.user_id', '=', 'users.id')
->where('role_user.role_id', '=', Role::PICKER);
});
}
}
The picker and user models are using the same table (users), however the picker model filters out users so only those that have the correct role of "picker" are found. Working great so far.
What I want to do is to get all products and their relevant pickers (a product has one picker, a picker has multiple products).
Product::with('picker')->get()
This returns NULL for "picker", yet if I do:
Product::first()->picker
This works so the relationship seems fine and returns:
array(6) { ["id"]=> int(5) ["name"]=> string(8) "Picker B"
["created_at"]=> NULL ["updated_at"]=> NULL ["user_id"]=>
int(3) ["role_id"]=> int(1) }
If I change the "product" model to add a debug message It shows the relationship is working:
class Product extends BaseModel {
public function picker() : \Illuminate\Database\Eloquent\Relations\BelongsTo {
debug($this->belongsTo(Picker::class)->first());
return $this->belongsTo(Picker::class);
}
}
I am using the same syntax using "with" on other queries without a problem just can't seem to see the issue.
By changing the "belongsTo" inside the "Product" class to the following:
return $this->belongsTo(User::class, 'picker_id');
This now works and returns the picker data but I am using the wrong model, the "picker" model extends the user model.

Yii2 Rest Controller and public variable

I have made a REST controller with Yii2 framework. When I try to retrieve a record from my database through an ActiveRecord model, JsonFormatter give me only real attributes. How can configure JsonFormatter to give me also public variable?
This is my code:
Controller
class MyController extends yii\rest\ActiveController
{
...
public function actionView($id)
{
$struct = \common\models\Struct::find()->where(['id' => '285'])->One();
if ($struct) {
return $struct;
}
return false;
}
}
Model
/**
* property string $id;
* property string $name;
*/
class Struct extends \yii\db\ActiveRecord
{
public $test;
...
public function afterFind()
{
parent::afterFind();
$this->test = 'ok';
}
}
result of request
{"id":1,"name": "ciccio"}
but if I print variable with print_r(), I have all object
\app\models\Struct object
(
[test] => ok
[_attributes:yii\db\BaseActiveRecord:private] => Array
(
[id] => 1
[name] => ciccio
)
)
How can I get the variable test property without add an empty field on my database table?
You can override the ActiveRecord::fields() method to add the custom field that is declared as the public property of the class. The fields() method returns the names of the columns whose values have been populated into this record.
Looking at your code you are trying to set the test property inside the afterFind() and want that value to be reflected against all rows when you call the Model::find() method. If that is correct then add the following inside your model:
public function fields() {
$fields = parent::fields();
$fields['test'] = 'test';
return $fields;
}
Now when you call the \common\models\Struct::find() it will return
{"id":1,"name": "ciccio","test":"ok"}
Try this:
keep all you showed and then Override getAttributes
public function getAttributes($names = null, $except = [])
{
return array_merge(['test'=>$this->test], parent::getAttributes($names, $except));
}
and in your controller isted of return like this: return $struct;
do it like this: return $struct->attributes;

How to use SUM() with hasMany result from Model in Laravel 5.6

I Try to Get result using this Model
use Illuminate\Database\Eloquent\Model;
use DB;
class Customer_Bones extends Model
{
protected $table = 'customer_bones';
protected $primaryKey = 'customer_bones_id';
protected $fillable = array(
'created_at',
'deleted',
'system_user',
'customer_id',
'bones_id'
);
public $timestamps = false;
public function getBonusCustomers(){
return $this->hasMany('App\Models\Bonus_Item','customer_bones_id');
}
public function getCustomer(){
return $this->hasOne('App\Models\Customer','customer_id');
}
}
My Controller function is this
return Customer_Bones::with(array(
'getCustomer' => function($query)
{
$query->select('customer_name','customer_id');
},
'getBonusCustomers' => function($query)
{
$query->select(DB::raw('sum(bonus_quantity) as bonusQuantity'));
}))
->get();
I want to get sum of the bonus_quantity column that belongs to Bonus_Item Table with customer_name from customer table and some other details from customer_bones table. I had Tried above method but bonusQuantity return me null.
Can I use DB::raw('sum(bonus_quantity) as bonusQuantity') inside the select clause like above to get summation of bonus_quantity column, along with other details or is there any other method?
You could use withCount with raw expression in callback to get the required sum like
Customer_Bones::with(['getCustomer' => function($query){
$query->select('customer_name','customer_id');
}
])->withCount(['getBonusCustomers as bonusQuantity' => function($query) {
$query->select(DB::raw('SUM(bonus_quantity)'));
}
])->get();
Or you could define a new mapping in your model which returns sum per customer_bones_id
public function getBonusCustomersSum(){
return $this->hasOne('App\Models\Bonus_Item','customer_bones_id')
->select('customer_bones_id',DB::raw('sum(bonus_quantity) as bonusQuantity'))
->groupBy('customer_bones_id');
}
Customer_Bones::with(['getCustomer' => function($query){
$query->select('customer_name','customer_id');
}
, 'getBonusCustomersSum'])
->get();
Laravel use multiple where and sum in single clause

Calling child relations from model in laravel

I want to fetch the categories with products and images. I have following relation:
Product Model
class Product extends Model
{
public function productCategory() {
return $this->belongsToMany('ProductCategory');
}
public function addtionalImages() {
return $this->hasMany('ProductImage');
}
}
Product Category Model
class ProductCategory extends Model
{
public function product() {
return $this->hasMany('Bazar\Models\Product', 'product_catid')
->orderBy('id', 'DESC')->limit(10);
}
}
This is how i am using eager loading:
$categories = ProductCategory::select('product_categories.*')
->with(['product'])->Paginate(20);
This returns the category and products not the additionalImage, images are related to products not with the categories, I tried ->with(['product', 'addtionalImages']) but no success, can anyone let me know what i missed? or how do i achieve?
SOLVED
I solved it, and posting the answer so it helps to others.
$categories = ProductCategory::select('product_categories.*')
->with(['product', 'product.addtionalImages'])->Paginate(20);
With use of product.addtionalImages i can access the methods of related relation.
Portfolio Model:
public function getCats(){
return $this->hasMany(RelPortfolioCategory::class,'portfolioID','id');
}
controller:
public function portfolioDetail($slug){
$db = Portfolio::where('slug' , $slug)->with('getCats')->firstOrFail();
$dbRelated = RelPortfolioCategory::whereIn('categoryID' , $db->getCats->pluck('categoryID'))->whereNot('portfolioID' , $db->id)
->with('getPortfolioDetail')->get();
return view('portfolioDetail' , compact('db' , 'dbRelated'));
}

Zend framework data mappers + paginator

I mostly use zend_db_table with a paginator, the problem is that it will return zend_db_rows instead the domain objects from my datamapper.
Let's say :
class Content_Model_ArticleMapper {
/*
* #param Zend_Db_Select $select
* #return Zend_Paginator
*/
public function getPaginator($select = null){}
}
I can hack it by overriding _loadAndReturnRow method in a custom rowset
However this is pretty ugly as I don't have a Zend_Db_Row anymore when I query the table.
And loose the methods too like save which I don't want to replicate on the domain object.
:
class Content_Model_DbTable_Rowset_Articles extends Zend_Db_Table_Rowset {
protected function _loadAndReturnRow($position)
{
if (!isset($this->_data[$position])) {
require_once 'Zend/Db/Table/Rowset/Exception.php';
throw new Zend_Db_Table_Rowset_Exception("Data for provided position does not exist");
}
// do we already have a row object for this position?
if (empty($this->_rows[$position])) {
$this->_rows[$position] = new Content_Model_Article($this->_data[$position]);
}
// return the row object
return $this->_rows[$position];
}
}
So my question how do you do this nicely ? :) Do you write custom Paginator adapters?
You can set a rowClass in your DbTable like
DbTable
class Content_Model_DbTable_Article extends Zend_Db_Table_Abstract {
protected $_name = 'article';
public function init() {
$this->setRowClass('Content_Model_Article');
}
}
Domain Model
class Content_Model_Article extends Zend_Db_Table_Row {
//for example
public function getAuthorFullName() {
return $this->author_firstname . ' ' . $this->author_lastname;
}
}
Now rows in your rowset are instances of Content_Model_Article and you can use the Zend_Paginator_Adapter_Iterator.
Using Paginator
$articleTable = new Content_Model_DbTable_Article();
$articleRowset = $articleTable->fetchAll();
$paginator = new Zend_Paginator(Zend_Paginator_Adapter_Iterator($articleRowset));
//now you can loop through the paginator
foreach($paginator as $article) {
echo $article->getAuthorFullName();
}