How can I get result of find() as model name array? - cakephp-3.0

How can I get result of find() as model name array?
For now, main table is getting as field name, but other joined tables are stored in model name array.
class ArticleMainsTable extends Table {
$this->belongsTo(
'TopicMasters', [
'className' => 'TopicMasters',
'foreignKey' => 'topic_id'
]
);
function get() {
return $this->find('all', ['contain' => 'TopicMasters'])->first()->toArray();
}
}
It returns like following structure.
['id'] // From ArticleMainTable.
['title'] // From ArticleMainTable
....
['topic_master'] // There is another layer and it contains fields of
For fields of ArticleMainTable, I want to access same layer as TopicMasterTable.
So, ['article_main']['id'] like that.
How can get main table data same as joined tables structure?

Related

How can I compare 2 columns in the same table but not in the same row with Laravel?

I want to display the values of columns with the same menu_id and the same menu_parentid. However, the array is empty when I execute in Postman. I want the values of columns with common menu_id and menu_parentid displayed in an array.
Controller
public function showMenu()
{
return [
'menus' => Menu::whereColumn('menu_parentid', 'menu_id')
->distinct()
->get()
->map(function ($item) {
return [
'menu_id' => $item->menu_id,
'menu_name' => $item->menu_name,
'menu_icon' => $item->menu_icon,
];
})
];
}
When I test on Postman, I get the following
{
"menus": []
}
Screenshot of database
I think you're going about this the wrong way. Instead of doing a query like that, you can make a relationship of the model with itself to get the $menu->children and then perform the array mapping the way you like. I don't want to write it out and guess how you like it to be displayed, so can you elaborate how you would like the array to be structured? Is it like this?:
"menus": [
[parent_id1, child_id1],
[parent_id1, child_id2],
[parent_id2, child_id3]
];
Or is it a different structure where the parent id's are all mixed with the children? I can only give you hints without you clarifying your structure.
You can you have to select a One to many relation in model.
public function childs()
{
return $this->hasMany(Menu::class, 'menu_parentid', 'menu_id');
}
Then, you can select items with this query,
Menu::with('childs')->distinct()->get();

Yii2 Restful. How can i receive data from 3 tables

I want to receive data like this:
categories
----category1
----category2
topProducts
----product1
--------photo1
--------photo2
----product2
--------photo1
--------photo2
I need get all categories and top x products.
Each product has two photos.
How can i do this by using yii2 restful?
Thanks.
the query shold look something like this
Category::find()
->with(['subcategories','topProducts', 'topProducts.images'])
->all();
you can use joinWith if you absolutely want a single query
if you retrieve your data with an ActiveController, you need to specify extraFields to the Category model. (here's a rest-specific usage example - rest of the guide should prove usefull as well)
Category model:
public function extraFields() {
return ['subcategories', 'topProducts'];
}
// product relation
public function getTopProducts(){
return $this->hasMany(Product::className(), ['category_id' => 'id'])
// ->order()->where() // your criterias
->limit(10);
}
// subcategories
public function getChildren(){
return $this->hasMany(Category::className(), ['id' => 'parent_id']);
}
Product model:
public function extraFields() {
return ['iamges'];
}
public function getImages(){
return $this->hasMany(Image::className(), ['product_id' => 'id'])
}
ps. since you haven't posed any code or table structure, all relations in my example are based on standard naiming convention

Inserting JSON to DB Using Model in Laravel

I'm trying to use the model create option and this is my array:
$result = array(
'match_id' => $input['id'],
'score' => $input['score'],
'result' => $input['result'],
'headline' => NULL,
'article' => $input['report'],
'tries' => $input['try'],
'try_amount' => $input['tryquant'],
'conversions' => $input['conv'],
'conv_amount' => $input['convquant'],
'penalties' => $input['pens'],
'pen_amount' => $input['penquant'],
'dropgoals' => $input['dgs'],
'dg_amount' => $input['dgquant']
);
Result::create($result);
The contents of some of these are arrays themselves. eg:
$input['penquant'] = [
"4"
]
When I run my code, it saves the data to the DB simply as Array and throws up the following error:
ErrorException in helpers.php line 703: preg_replace(): Parameter mismatch, pattern is a string while replacement is an array
Can someone tell me what I'm doing wrong and how to fix it?
Shouldn't have rushed, forgot to use json_encode.
The best is to use mutators and accessors in your model.
example of mutator
// convert pen_amount from snake case to studly case
// The set...attribute (the ... is you field name which is in studly case) helps transform the data before you save it
// into the database
public function setPenAmountAttribute($value)
{
$this->attributes['pen_amount'] = serialize($value);
}
example of an accessor is
// convert pen_amount from snake case to studly case
// the get...Attribute (the ... is you field name which is in studly case) helps you convert the data back to it original state
public function getPenAmountAttribute($value)
{
return unserialize($value);
}
You can use accessors and mutators for all your fields that you want to save as array. This is elegant. No need to manually use json_encode and decode in your controllers.

Yii2 Model search query

How can I add where condition to my Articles model so that slug(From category model) is equal to $slug?
And this is a function that Gii generated:
public function getCategory()
{
return $this->hasOne(Categories::className(), ['id' => 'category_id']);
}
Here's my code:
public function specificItems($slug)
{
$query = Articles::find()->with('category');
$countQuery = clone $query;
$pages = new Pagination(['totalCount' => $countQuery->count(),'pageSize' => 12]);
$articles = $query->offset($pages->offset)
->limit($pages->limit)
->all();
return ['articles' => $articles,'pages' => $pages];
}
Your SQL query should contain columns from both article and category table. For that you need to use joinWith().
$result = Articles::find()
->joinWith('category')
->andWhere(['category.slug' => $slug])
->all();
Where 'category' is then name of your category table.
However, in your code you deviate from certain best practices. I would recommend the following:
Have both table name and model class in singular (Article and article). A relation can be in plural, like getCategories if an article has multiple categories.
Avoid functions that return result sets. Better return ActiveQuery class. If you have a query object, all you need to get the actual models is ->all(). However, you can further manipulate this object, add more conditions, change result format (->asArray()) and other useful stuff. Returning array of results does not allow that.
Consider extending ActiveQuery class into ArticleQuery and implementing conditions there. You'll then be able to do things like Article::find()->joinWith('category')->byCategorySlug('foo')->all().

Complex AR query, where clause one column equal to another column's value?

I've written up the AR query below, but have one problem with a where clause. On the Payout model there is a comp_builder_id and there's also a comp_builder_id on a ContractLevel.
I want to add a where clause to this query to get the data where the Payout model's comp_builder_id is equal to the ContractLevel model's comp_builder_id.
payouts = Payout.includes(:comp_builder => {
:contract_levels => {
:transmittal => [
{:appointment_hierarchies => :child},
:appointment_cases
]
}
})
.includes(:product)
.includes(:payor)
.where(products: { :id => self.product.id })
.where(appointment_cases: { :case_id => self.id })
.where(transmittals: { :id => appointment_case.transmittal_id })
.where(contract_levels: { :transmittal_id => appointment_case.transmittal_id,
:appointment_id => Transmittal.find(appointment_case.transmittal_id).low,
:comp_builder_id => # ? payout's comp builder id ? })
How can this be done in Active Record? In the last few where clauses I'm referencing different variables, those can be ignored as this query is just a snippet.
You can pass a string into the where statement:
User.include(:parent).where('users.parent_id = parents.id')
Basically if you know what you want the where statement to look like in raw SQL then you can just pass it in as a string into the where statement.
That is the only way I know of to make complex where statements in ActiveRecord.
Just make sure to remember that you need to reference the column names, not the model names.