I have this function write in a CakePHP model:
public function getPeopleByName($name){
$this->unbindModel(array('hasMany' => array('OfficePersonTask')));
$options['fields'] = array("Person.id", "CONCAT(Person.first_name, ' ', Person.last_name) AS full_name");
return $this->find('all', $options);
}
This gave me the following json:
{
People:[
{
0:{
full_name:"Groucho Marx"
},
Person:{
id:"1"
}
},
{
0:{
full_name:"Giovanni Ferretti"
},
Person:{
id:"2"
}
}
]
}
I would that *full_name* will be part of Person group (actually is in a group called 0, all alone). How I can do that?
Use a virtual field in the model rather than a MySQL function in your find. There are some ways to query for data as you are trying to, but you have to account for data being returned in an indexed array rather than the normal associative.
Related
I have getCanSeeAttribute function in post model, and I try to get posts with pagination using filter()
$posts = Post::where(function ($query1) use ($users) {
$query1->where('posted_type', 'user')->whereIn('posted_id', $users);
})
->orWhere(function ($query2) use ($stores) {
$query2->where('posted_type', 'store')->whereIn('posted_id', $stores);
})
->with('likes', 'postable')
->withCount('comments', 'likes')
->latest()->paginate($paginate)->filter(function($post){
return $post->can_see == true;
});
The problem is when I use filter, it gets data attribute only, but I need all pagination attributes.
first_page_url": "http://localhost:8000/api/timeline?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "http://localhost:8000/api/timeline?page=1",
"next_page_url": null,
"path": "http://localhost:8000/api/timeline",
"per_page": 10,
"prev_page_url": null,
"to": 6,
"total": 6
can_see not column in table it is Accessor
First of all, I hope you know what are you doing. Assuming you need to get results that has can_see field set to true, you should rather use:
$posts = Post::where('can_see', true)
->where(function($q) {
$q->where(function ($query1) use ($users) {
$query1->where('posted_type', 'user')->whereIn('posted_id', $users);
})->orWhere(function ($query2) use ($stores) {
$query2->where('posted_type', 'store')->whereIn('posted_id', $stores);
})
})->with('likes', 'postable')
->withCount('comments', 'likes')
->latest()
->paginate($paginate);
As you see I additionally wrapped (where .. orWhere) in additional where closure to make sure valid query will be generated.
Otherwise you should use:
$posts = Post::where(function($q) {
$q->where(function ($query1) use ($users) {
$query1->where('posted_type', 'user')->whereIn('posted_id', $users);
})->orWhere(function ($query2) use ($stores) {
$query2->where('posted_type', 'store')->whereIn('posted_id', $stores);
})
})->with('likes', 'postable')
->withCount('comments', 'likes')
->latest()
->paginate($paginate);
$posts = $posts->setCollection($posts->getCollection()->filter(function($post){
return $post->can_see == true;
})
);
However it's very unlikely the 2nd way is better one in your case. Assuming you have 1 mln of matching records and then of them has can_see set to true, and the rest have it set to false, it would cause that you will get 1 mln of records from database and then you will filter only 10 of them what would be performance killer for your application.
You can add this following code, define after $post
$post->appends($request->only('posted_type'));
I have a controller that should return a list of categories. Each should also have a collection of sub-categories. Each sub-category should also have modules. The modules are of two types: the latest modules and most watched modules.
A SUMMARY STRUCTURE I WANT:
[
{
id: 1,
name: category 1,
sub_categories:
[
{
id: 1,
name: subcategory 1:
modules:
[
latestModules: [...],
mostViewedModules[...]
]
}
],
another sub-category object,
and another sub-category object
},
another category object,
and another category object,
]
My Controller
class SeriesController extends Controller
{
public function getSeries()
{
$categories = Category::with('SubCategories')->get();
$countCats = 0;
$countSubCats = 0;
collect($categories)->map(function ($category) use ($countCats, $countSubCats, $categories){
collect($category->subCategories)->map(function ($subCategory) use ($countSubCats, $categories) {
collect($categories[$countCats]->subCategories[$countSubCats])
->put('modules',
SubCategory::with('latestModules', 'mostViewedModules')
->where('id', $subCategory->id)->get()
);
$countSubCats++;
});
$countCats++;
});
return $categories;
}
}
My Category model
class Category extends Model
{
public function subCategories()
{
return $this->hasMany('App\SubCategory')
->orderby('name');
}
}
My Subcategory Model
class SubCategory extends Model
{
public function parentCategory(){
return $this->belongsTo('App\Category', 'category_id');
}
public function modules()
{
return $this->belongsToMany('App\Module', 'module_category', 'sub_category_id', 'module_id');
}
public function latestModules()
{
return $this->modules()
->orderBy('created_at', 'desc');
}
public function mostViewedModules()
{
return $this->modules()
->orderBy('views', 'desc');
}
}
My Module Model
class Module extends Model
{
public function subCategories()
{
return $this->belongsToMany('App\SubCategory', 'module_category', 'module_id', 'sub_category_id');
}
}
WHAT I WAS TRYING TO DO
1) Get all the categories via Eloquent Query
2) Collect the many categories and Map over them
3) For each ONE category i map over again to single it out into sub-categories
4) For each sub-category i run Eloquent query to return the related modules.
5) Then i put that result into categories original array by using PUT. I wanted to expand on the original $categories array by including the modules.
PROBLEM
I realize that the loop works and everything is fine, except that the global $categories variable does not update. Its like inside the loops its updated but once we exist the Map loops the value defaults to
Category::with('SubCategories')->get()
I want to query all the names starting with p (case insensitive).
Below is the query object and Organisation is my generated lb-service name
query = {
filter: {
order: 'updatedAt ASC',
where: {name: {ilike: 'P%'}}
};
Organisation.find({filter: query.filter})
You can use regex for this.
Organisation.find({name: {$regex: new RegExp('^P$', "i")}}).sort('updatedAt').all(function(res) {
//Do your action here..
});
dunno if this is possible at all.. I'm trying to query a large set of data with relations like so:
Parent::with([
'child' => function($query) {
$query->('published', '=', true);
$query->with('child.of.child', 'some.other.child');
$query->chunk(400, function($childs) {
// how is it now possible to add the $childs to the parent result??
});
}
]);
$parent = [];
Parent::with(
[
'childs' => function ($query) use (&$parent) {
$query->where('STATUS', '!=', 'DELETED');
$query->with('some.child', 'some.other.child');
$parent['models'] = $query->getParent()
->getModels();
$query->chunk(
400, function ($result) use ($query, &parent) {
$query->match($parent['models'], $result, 'child-relations-name');
});
}
])
->get();
Now $parent['models'] contains the tree with all the nested child relations... Dunno if this is the smartest way to do so, but it works for now.
Platform - Ext.net 2.1 in an MVC project. The data is coming back as json from a DirectMethod and I'm binding on the client.
I'm returning the results of a dataset with multiple tables with relationships defined between the tables. I want to bind the resulting data to a store to be used in a dataview. The first dataview that I'm filling, only uses the highest level of data. However, when the user selects a record in the dataview, I want to bind to another template in a different dataview to provide all levels of information.
Tables
Account
--- Addresses
(I'll skip the other table for now)
Here is the definition of my models and store:
#(Html.X().Model()
.Name("SearchResults.Models.Address")
.IDProperty("nafnmfuid")
.Associations(assoc => assoc.Add(new BelongsToAssociation() {Model = "SearchResults.Models.Account"}))
.Fields(
new ModelField("nafnmfuid", ModelFieldType.Int),
new ModelField("naftype"),
new ModelField("nafadd1"),
new ModelField("nafcity"),
new ModelField("nafstate"),
new ModelField("nafzip")
))
#(Html.X().Model()
.Name("SearchResults.Models.Account")
.IDProperty("nmfuid")
.Associations(assoc => assoc.Add(new HasManyAssociation() {Name = "Addresses", Model = "SearchResults.Models.Address", AssociationKey = "Addresses", PrimaryKey = "nmfuid", ForeignKey = "nafnmfuid"}))
.Fields(
new ModelField("nmfuid", ModelFieldType.Int),
new ModelField("AmfLastNamePrimary"),
new ModelField("AmfFirstNamePrimary"),
new ModelField("nmfid"),
new ModelField("naftype"),
new ModelField("nafadd1"),
new ModelField("nafcity"),
new ModelField("nafstate"),
new ModelField("nafzip")
)
)
#(Html.X().Store()
.ID("StoreSearchResults")
.ModelName("SearchResults.Models.Account")
.Reader(readers => readers.Add(Html.X().JsonReader()))
)
I tried returning the data as nested json as well as three objects in the json.
When I bind the data (on the client), I get the new field in the highest level (Account) called Addresses. However, the field is an empty array.
When I look at the RAW property of the Account record, I see all the nested data.
Here is the ext.js code that's generated by Ext.net
window.App.StoreSearchResults2 = Ext.create("Ext.data.Store", {
model:Ext.define("SearchResults.Models.Address", {
extend: "Ext.data.Model"
, fields:[ {
name:"nafnmfuid"
,type:"int"
}
, {
name:"naftype"
}
, {
name:"nafadd1"
}
, {
name:"nafcity"
}
, {
name:"nafstate"
}
, {
name:"nafzip"
}
]
,idProperty:"nafnmfuid"
,associations:[ {
type:"belongsTo"
,model:"SearchResults.Models.Account"
}
]
})
,storeId:"StoreSearchResults2"
,autoLoad:true
,proxy: {
type:'memory'
, reader: {
type:"json"
}
}
});
window.App.StoreSearchResults = Ext.create("Ext.data.Store", {
model:Ext.define("SearchResults.Models.Account", {
extend: "Ext.data.Model"
, fields:[ {
name:"nmfuid"
,type:"int"
}
, {
name:"AmfLastNamePrimary"
}
, {
name:"AmfFirstNamePrimary"
}
, {
name:"nmfid"
}
, {
name:"naftype"
}
, {
name:"nafadd1"
}
, {
name:"nafcity"
}
, {
name:"nafstate"
}
, {
name:"nafzip"
}
]
,idProperty:"nmfuid"
,associations:[ {
type:"hasMany"
,associationKey:"addresses"
,primaryKey:"nmfuid"
,model:"SearchResults.Models.Address"
,foreignKey:"nafnmfuid"
,name:"Addresses"
}
]
})
,storeId:"StoreSearchResults"
,autoLoad:true
,proxy: {
type:'memory'
, reader: {
type:"json"
}
}
});
The problem was that I was using the method loadData on the client to bind the data. Switching to loadRawData did the trick.