CakePHP find / paginate with hasMany Field as implode() - cakephp

I have two models Model A and Model B. Model A hasMany Model B.
So now I want to build a paginated table in a View about Model A. And there I want a column, where a specific field of Model B is shown as comma separated list.
Imagine Model A is named Group and Model B is named User.
Group hasMany User
Now I want a table of the groups like
id | name | user
1 | first group | User 1, User 2, User 3
But I donĀ“t want to use a foreach within the View, it should be a string already in the array.

You can use the Model::afterFind() callback and build the string in your model and add it to the result set. In the view just use it like echo h($result['Model']['your_field_list']).

Related

In MongoDB/React what is the best practice for filtering data?

I came here today with a theoretical question. (hint: it will be long and tough, but to fully understand the problem I think I have to write every important detail. If you read it to the end huge thanks for you, you're not the hero we deserved but the hero we needed)
Story time: I'm currently building an online shop from 0. It has the same principles as an ebay: users can create advertisment for their used products. The problem is that I want to create a filtering feautre.
What is my MongoDB data structure?
My page has products with different attributes, by this I mean that the products have varying categories and values. To imagine here is an example
Product A:
Creator:User1
Category:Car
Type:BMW
Color:Red
Product B:
Creator:UserB
Category:Electronics
Type:Phone
Producer:Apple
To be more complex each user can define maximum 3 more extra category and value for each product. So for example User1 adds 2 new category and the final product will be:
Product A:
Creator:User1
Category:Car
Type:BMW
Color:Red
Number of seats:4
Fuel type: Gasoline
Because of the above mentioned when a user adds a new product there will be two type of categories: the static ones which are predefined by me(Category,Type,Color -> in car's case) and the dynamic ones which the user adds (Number of seats, Fuel Type or anything else).
Overall: My final data structure in mongoDB is not static, since there are some added categories. Because of this I have a Product collection and each document looks like the above mentioned example
How are the items shown?
I have a main page. When I populate it I make a call with $skip and a $limit attribute set to 8, so for the first time I only query 8 products. If a user clicks on a Load More button it will load another 8 product and so on.
FINALLY: My actual question ...
So at this point I guess you understand everything related to the business logic so it's time for my question: if I want to filter these dynamic products, but i don't know what is the best practice for it?
My idea:
First create a mongoDB collection named Categories. Each main category will be a document in it and we will store static and dynamic categories and values
ex:
category:car
predefined:[{type:[BMW,Mustang,Ferrari]},{color:[red,green,blue]}]
userdefiend:[{number of seats:[2,4,5,6]},{fuel type:[Gasoline,Air,Diesel]}]
We load the the values in the main page if a user clicks a specific value ex:BMW we set a limit to 8 and go through on our Product collection and get the 8 items which has a Type:BMW. If he selects another option ex: color:Red we loop again through the collection but now with two criteria: Type:BMW and color:Red.
Idea2: Create a Category collection again with this structure
categoryType:predefined
mainCategory:Car
categoryName:Type
BMW:[prodA, prodC,prodD]
Ferrari:[prodD,prodE]
...values:products which contains
categoryType:userdefined
mainCategory:Car
categoryName:Number of seats
4:[prodA, prodD],
5:[prodE]
If a user selects from Type category the BMW we load the products from the BMW fields [prodA,prodC,prodD]. If the user selects Number of seat category with a value 4 we load the [prodA, prodD] and on the webpage we use a filter with our actual products so it remains only [prodA,prodD]. And from our actual list we use findById for the specific products.
I think that these are not the best options from any perspective, but I am really confused.
What do you guys think how should I structure my categories/products to have an efficent read/write/update complexity?
Anyways thank you for reading this and if you made it until here I'm curious about your idea. Have a nice day
UPDATE:
The filtering functionality
To don't have any confusion this is my filtering idea: When a user selects a main category for example Car or Electronics I want to show only the relevant filtering categories and options. Filtering categories in Car's case are Type and Color.
I want these filtering options to have pre-poupulated options. By this I mean, that if a filtering category is Type, and there are 2 Products which has Type:BMW and Type:Ferrari I want to show these values as options for filtering. And I don't want to hardcode these options, for example I hardcoded Type:Laborghini and I have no products with type Laborghini.
By the end if a user clicks to a Type:BMW I will filter all of my products based on that criteria.
My filtering side menu will look like this:
Type: BMW,Ferrari (these values exists in my database)
Color:Red,Black,Grey,Yellow
And for user-added categories I will build a searchbar, if a user selects a userdefiened category I want to add to the filtering categories so the overall look would look like this:
Type: BMW,Ferrari (these values exists in my database)
Color:Red,Black,Grey,Yellow
Number of seats:4,6,7 (number of seats category is added by user, 4,6,7 are the existing values to this category)
You could structure Your data like having a generic Products collection. Having both
Product A:
Creator:User1
Category:Car
Type:BMW
Color:Red
Product B:
Creator:UserB
Category:Electronics
Type:Phone
Producer:Apple
rows. Whenever you show the filter component, you can select the available categories by using an Aggregate (https://stackoverflow.com/a/43570730/1859959)
This would generate search boxes like "Creator", "Category", "Type", "Color", "Producer".
The data itself would be as generic as possible.
When the user wants to add a new product, it starts out from a template, like "Car" or "Electronics". The Templates collection gives him the initial values, which should be included. So it would be like:
{Car: [{type:[BMW,Mustang,Ferrari]},{color:[red,green,blue]}],
Electronics: ... }
Selecting a Car would generate the "type" and "color" input boxes. Saving the form would insert the new row into Products.

How "filter" a input select with table data in cakephp

I have a doubt with Cakephp 3 querys/filters.
I have a database with tables: Groups, Users, Posts and Relations.
Groups contains : id and name
Users contains : id, name and group_id
Relations contains : id, user_id, group_id
Posts contains : id, title, message, user_id, group_id
So, when a user gonna add a post, I need to make a "filter" which display in field " group_id " ONLY groups that is registered to him in relations.
-
Well, to explain I made a example:
Groups:
id | name
1 - SEO
2 - P1
3 - P2
4 - P3
Users:
id | name | group_id
1 - John - 1 (SEO)
2 - Mariah - 2 (P1)
3 - Peter - 3 (P2)
Relations:
id | user_id | group_id
1 - 1 (John) - 2 (P1)
2 - 1 (John) - 3 (P2)
That is, table relations is saying: John can make posts for groups P1 and P2.
My problem is right here.
In " VIEW ADD POST", how I filter the results of input select 'groups' for display only groups is registered for the logged user.
And other, I need to make a Validator also, right?
PS: Sorry for my english, I'm learning.
It is like that you are asking about passing the logged in user to the model layer, If I am right then you just need to read and use Footprint plugin.
Footprint: CakePHP plugin to allow passing currently logged in user to model layer
When this plugin is loaded and configured for postsTable, then you will simply modify the posts query with beforeFind event using the passed logged in user.

CakePHP getting data from multiple table

Let's say I have 2 table.
One is floor, another is shop.
Inside floor table :
id, floor_name
Inside shop table:
id, name, floor_id.
Meanwhile, the association is:
one floor hasMany shop, one shop hasOne floor.
ok , the question is ..
How can I get the floor_name data directly while I'm only able to get the floor_id in my view ?
Example: I display all of the shop data as
$shop['Shop']['name'], $shop['Shop']['floor_id'],
which in my /shops/main
I want the $shop['Shop']['floor_id'] field display the $floor['Floor']['floor_name'] data ? possible ?
Kampung,
You should have below mentioned association in you tables:
Floor hasMany Shops
Shop belongsTo Floor
Now in your controller when you will fetch data about your shop then you will get floor data automatically.
$shops=$this->Shop->read(null, $id);
Now $shops will contain two array
['Shop']=>array(.......)
['Floor']=>array(........)
so now to display the floor name, you need to use $shop['Floor']['floor_name'] instead of $floor['Floor']['floor_name']
Define a hasMany Floor relationship in your Shop model. In your Floor model, define a belongsTorelationship to Shop. This will allow your associated data to be retrieved.
When retrieving your data via $this->Shop->find('first', $arg), where $arg is your search option array, define the following
$arg['contains'] = array('Floor.name');
Now, you should get what you want.

CakePHP saving data in multiple tables

I have shop struct like
1: Shop has many Categories
2: Categories have 1 to many Sizes and Products
3: Each product belongs to exactly one Category
4: As Sizes belongs to Categories so each product belonging to a category will have same sizes.
Now my problem is in Product add form.
I have form the contains product's input fields and a selectbox to select the Category.
As soon as I select a category, an Ajax request will be created, which return sizes as inputbox assigned to the selected category. The input boxes will be used to enter the price
for each size of the product. (As the input fields will be generated in Ajax, how may i use the form helper?)
Now I want that on clicking the save button, the product information should be stored in product table, and the prices should be saved in
Product_Prices table which contains product_id, size_id, price columns.
How should i name my inputboxs? and how should i call the save method so that the informations are properly saved?
To save one-size
//$this->Form->create('Product');
$this->Form->input('category_id');
To save many-size
//$this->Form->create('Shop');
$this->Form->input('category_id');
or use checkbox instead list
$this->Form->input('category_id', array('multiple' => 'checkbox'));
If you want to save property of another model together with you main model you add model name (alias) as prefix and use saveAssociated() or saveAll().
echo $this->Form->input('ProductPrice.price');
see: http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveall-array-data-null-array-options-array

How to render view with Backbone Marionette

I'm using Backbone.Marionette and need to render a view of employees and their respective departments. I want it to look something like so:
Department 1
***
Employee1
Employee2
Employee3
Department 2
***
Employee4
Employee5
Employee6
Employee7
Employee8
Department 3
***
Employee9
Employee10
My collection looks like this:
Employee1 / Department1
Employee2 / Department1
Employee3 / Department1
Employee4 / Department2
Employee5 / Department2
etc.
As the department changes I need to render the department heading.
Which combination of view types would I use. Collection view, Composite view. Would I need to put logic in the view/template?
The end result can be broken down fairly easily, to determine what view types to use.
You have a collection of Departments that you want to render. A CollectionView would handle this, allowing each department to be rendered on it's own.
The department itself has complex needs. It needs to show a header (the department name) and some detail - a list of employees. This sounds like a collection view with a wrapper template... a CompositeView.
Each department's composite view then needs to render a list of employees. THe employee information seems fairly simple, so an ItemView would suffice.
The end result would be:
CollectionView
- CompositeView (department)
- ItemView (employee)
... Of course your actual data structure doesn't work very well for this layout because you have the relationship inverted where employee knows what department it belongs to. You'll either need to invert the data / relationship so that departments know what employees they have on the server / returned JSON, or do some client side filtering and grouping to get to that result.

Resources