I have a JSON object that I need to post & save it using cakePHP 3.
First I have 4 tables as in this image
Let's say a supplier buys some products, so I need to fill a purchase record and the association table products_purchases, which will contain all the records of products bought during that one purchase.
I'll be using some JavaScript to dynamically generate some fields to be able to fill multiple products with quantities, prices.. during that purchase, and then store all the data in a JSON object.
So in the add.ctp view of purchase, I'll have this JSON object for exmaple :
$data = {
"reference": "V656413",
"supplier_id": 31,
"payment_id": 5,
"products_purchases": [
{
"product_id": 5566,
"purchase_id" 999,
"quantity": 4,
"price": 899
},
{
"product_id": 7865,
"purchase_id" 999,
"quantity": 6,
"price": 54
},{
"product_id": 434,
"purchase_id" 999,
"quantity": 8,
"price": 22
},
]
}
How can I POST this object using the form in the add.ctp file, and how can I handle it and save it as an entity with its associations in the PurchasesController?
The add method in the controller for now is as follow :
public function add()
{
$purchase = $this->Purchases->newEntity();
if ($this->request->is('post')) {
$purchase = $this->Purchases->patchEntity($purchase, $this->request->data);
if ($this->Purchases->save($purchase)) {
$this->Flash->success(__('The purchase has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The purchase could not be saved. Please, try again.'));
}
}
$this->set('_serialize', ['purchase']);
}
Thank you very much!
You have to manage proper associations with your models. visit below link where you can see how to save data with associations.
https://book.cakephp.org/3.0/en/orm/saving-data.html
Related
I'm struggling to properly organize my Redux Store and my React components to properly deal with two-way nested data.
Suppose I have a post model and a user model. Let's take an abstracted example:
const user = {
"id": "1",
"name": "user 1",
"posts": [...] // list of post objects
}
const post = {
"id": "1",
"title": "post 1",
"user": user
}
The problem is that I cannot load this data like this because it will cause an infinite recursion error. I have to omit either the posts from the user or omit the user from the posts.
Here's what I ideally need:
I need to have a single post page that displays the post user with all his info (id, name) and the user's list of posts with the post info (id, title) in the same screen all at once.
I use normalizr to normalize the data.
How would I go about loading the data?
As per Redux docs (https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape) you should avoid nesting objects.
The solution here would be to treat the data like it is a database. That means that you should store ids instead of objects.
In your example:
const user = {
"id": "1",
"name": "user 1",
"posts": ["1", "2", ...] // list of post objects IDs
}
const post = {
"id": "1",
"title": "post 1",
"userId": "1"
}
Normally you would only save post_ids in the user, and user_id in the post. normalizer schemas can be configured to deal with those relations.
What is the incentive of adding the user key in post? Having shared data within two related data structures is redundant. The only data you should have in post is the relevant data and the minimum amount of information you need to properly associate the user with his/her posts. I would imagine you would want to have the string name of the user in post, or an id number of the user inside each post object
const user = {
"id": "1",
"name": "user 1",
"posts": [...] // list of post objects
}
const post = {
"id": "1",
"title": "post 1",
"user": "user 1"
}
EDIT:
From your comment, I would make an array of all users. But with a post key that is only the ids of posts that are associated with that user. And another array of only posts. As before, have an identifier to correlate the two. After that, parse your frontend on an as needed basis.
const users = [
{ name: 'andrew', id: 10, postIds: [1,3,23,30]},
// ...more users
]
const posts = [
{ name: 'a post', id: 23, userId: 10 }
{ name: 'another post', id: 3, userId: 10 }
{ name: 'a third post', id: 2, userId: 3 }
// ...more posts
]
Technically, userId is optional, but it can be a nice-to-have to be able to identify a user when inspecting individual posts
EDIT:
Wow, I just scrolled down and saw nordus has the exact same proposal, before me. While it's nice to see we're on the same page, make sure he/she gets credit if you like the idea ;).
l am trying to retrieve all data in a firebase database . When l used this code <h1>{{ item | async | json }}</h1> depending on doc of angularfire2 object l got list of json response object in html
{
"type": "value",
"payload": {
"8D3sENaBcLaXoGNnh1MPuoyj5LP2": {
"-LWl294Hs6YjkvJE5pqi": {
"name": "ddd",
"title": "dd"
},
"-LWlEonKLWfOttzirqp7": {
"name": "sas",
"title": "ass"
},
"-LWlGvn81Kes2A-1UcC2": {
"name": "asa",
"title": "asass"
},
"-LWlK92A7gaRkKVrZSFU": {
"name": "ddd",
"title": "ddd"
},
"-LWla1PYxsIFKhaCXvtu": {
"name": "ff",
"title": "fdsf"
},
"-LWpfRJP8VdwG927wyXS": {
"name": "ali",
"title": "ali"
},
"-LWph3ei12KTNyirdnZb": {
"name": "ddddd",
"title": "daD"
}
},
"WUM2HBkGo8TFDeOjEqO1s3lCj1p1": {
"-LWlHlhyS9m3ECS3wIdk": {
"name": "qwqsasasa",
"title": "as"
},
"-LWlHmXZAJdSPZurO7ii": {
"name": "qwqsasasa",
"title": "as"
},
"-LWph-fv4JMtTk22aE5X": {
"name": "sssssssssssssssssssssssss",
"title": "sssssssssssssssssssssssss"
}
}
},
"key": "report"
}
l want to get from this list json object only title and name . l used this code but l got empty page in html no data to show !
<h1>{{ (item | async)?.name }}</h1>
<h1>{{ (item | async)?.title }}</h1>
main code
itemRef: AngularFireObject<any>;
item: Observable<any>;
ionViewWillLoad(){
this.fire.authState.subscribe(data => {
if(data && data.email && data.uid){
this.toastCtrl.create({
message : ` welcome ${data.email}`,
duration:2000
}).present()
this.itemRef = this.db.object('report');
this.item = this.itemRef.snapshotChanges();
}
})
}
The /report key in your database seems to hold a list of objects: specifically a list of reports for each user, so with two nested keys under /report. But your code is loading it as a single object. This leads to this HTML <h1>{{ (item | async)?.name }}</h1> essentially displaying /report/name, which doesn't exist in your database.
If you want to display the name and title of a single report, you need to know the keys of that report. For example to show the first report for the first user:
this.itemRef = this.db.object('report/8D3sENaBcLaXoGNnh1MPuoyj5LP2/-LWl294Hs6YjkvJE5pqi');
The first subkey 8D3sENaBcLaXoGNnh1MPuoyj5LP2 here is the UID of the user whose report you're showing and the -LWl294Hs6YjkvJE5pqi is the first report of that user.
If you want to display all reports for a user, you will need to again know the key of the user and pass it into the database. But since you then get back a list of reports, you'll also need to use the list service from AngularFire and loop over the results in your HTML template, so that it generates the elements for each report:
this.reports = this.db.list('report/8D3sENaBcLaXoGNnh1MPuoyj5LP2');
And:
<ul>
<li *ngFor="let report of reports | async">
{{ item.title }} - {{ item.name }}
</li>
</ul>
If you want to display a nested list of all reports for all users, you'd start with the same as just above, but now load the data for all users, and use another ngFor to loop over the users first.
Also see:
the AngularFire documentation on lists
this tutorial on building a CRUD application with AngularFire
So, I'm not super knowledge with MySQL relations, upserting and such. I'm looking for an explanation on how (if?) this is possible to do.
[
{
scheduledAt: '17:55',
league: { name: 'Champions League - Group Stage' }
},
{
scheduled_at: '19:45',
league: { name: 'Champions League - Group Stage' }
},
{
scheduled_at: '19:30',
league: { name: 'Primera B Metropolitana' },
},
{
scheduled_at: '21:00',
league: { name: 'Primera B Metropolitana' }
}
]
Say I wanted to insert this graph of data. The root objects are going into the fixtures table, and the league property is this relation in the Fixtures model.
{
league: {
relation: Model.BelongsToOneRelation,
modelClass: `${__dirname}/League`,
join: {
from: 'fixtures.league_id',
to: 'leagues.id'
}
}
}
So, currently if I use insertGraph to insert all this data. It's inserts into both the fixtures and leagues table and relates as you would expect.
{
"scheduled_at": "17:55",
"league": {
"name": "Champions League - Group Stage",
"created_at": "2018-10-03T13:02:03.995Z",
"id": 1
},
"league_id": 1
"created_at": "2018-10-03T13:02:04.042Z",
"id": 1
}
However if I insert the exact same league object, it will just create another duplicate league and fixture row with the next incremented ID (2 in this case).
Is it possible for it to find if a league exists with that name, and then use that row/ID as the league_id, like so:
{
"scheduled_at": "17.55",
"league_id": 1
"created_at": "2018-10-03T13:02:04.042Z",
"id": 2
}
Sorry if I've explained this horrendously. But I'm not so hot on the terminology so I don't know what I'm actually looking to do. I feel like this is a super easy thing, but maybe my structure or method is wrong.
I am trying to follow this example on how to setup a combo-box using dojo, but wondering how one can specify name and value programmatically. The example presented uses the same values for label and value - which is probably not one wants in most cases.
{
"identifier": "abbreviation",
"label": "name",
"items": [
{ "abbreviation": "AL", "name": "Alabama" },
... other 48 states here ...
{ "abbreviation": "WY", "name": "Wyoming" }
]
}
If you are asking how to replace the hard coded list in the example then here is what you have to do. In the above scenario items was used to specify the data which is an array (abbreviations and names) of values.
In your case you will need to get the data / object from your data source. Once you have that data/object expose it to the view. Once this has been done you can now do the following structure.
You store is really your items above however stateStore will be a java script array which contains the data from your data source.
stateStore = [{"abbreviation": "AL", "name": "Alabama"},
... other 48 states here ...,
{ "abbreviation": "WY", "name": "Wyoming" }]
// create FilteringSelect widget, populating its options from the store
var select = new dijit.form.FilteringSelect({
name: "stateSelect",
placeHolder: "Select a State",
store: stateStore
}, "stateSelect");
HTML
<div style="width:50%;float: left;">
<h1>dijit.form.Select</h1>
<label for="stateSelect">State:</label>
<div id="stateSelect"></div>
</div>
I'm a first time user of jqGrid, so far I went trough official examples, I'm interested in loading data into grid either using json.
I'm currently looking at, Loading data(JSON Data):
http://trirand.com/blog/jqgrid/jqgrid.html
Here is a bit of javascript that creates grid :
jQuery("#list2").jqGrid(
{
url : '<c:url value="${webappRoot}/getdetails" />',
datatype : "json",
colNames : [ 'id', 'Location', 'Country Code', 'Type', 'Interval',
'Version', 'Last Active', 'Last Login', 'NOTE' ],
colModel : [
{ name : 'id', width : 10 },
{ name : 'location', width : 75 },
{ name : 'countryCode', width : 50 },
{ name : 'type', width : 40 },
{ name : 'interval', width : 30 },
{ name : 'version', width : 45 },
{ name : 'lastactive', width : 50, align : "right" },
{ name : 'lastlogin', width : 50, sortable : false },
{ name : 'note', width : 50, sortable : false}
],
rowNum : 10,
rowList : [ 10, 20, 30 ],
pager : '#pager2',
width: gridWidth,
sortname : 'id',
viewrecords : true,
sortorder : "desc",
caption : "JSON Example"
});
jQuery("#list2").jqGrid('navGrid', '#pager2',
{ edit : false, add : false, del : false});
${webappRoot}/getdetails transforms path to my project like http://localhost/myProject/getdetails, I'm using spring MVC(it might be irrelevant).
When I look in firebug this generates this http request :
GET http://localhost/newProject/getdetails?_search=false&nd=1304638787511&rows=10&page=1&sidx=id&sord=desc
200 OK
135ms
Here is the response :
{
"id": 1,
"location": "office_2782",
"countryCode": "UK",
"quarter": "500",
"version": "v3.05",
"lastactive": "yesterday",
"lastlogin": "today",
"note": "no note",
"type": "read-only"
}
When I navigate to JSON tab it all seems same as this, any idea what I'm doing wrong?
I'm trying to load only one record for start, and I can't get it working, any help is appriciated.
First of all you are not the first person who has problems understanding how the JSON data should be constructed, what the parameters sent from jqGrid to the server mean and so on. The official jqGrid documentation doesn't contain enough introduction, so the first steps of the jqGrid usage can be a little more difficult than one expect.
The problem which exists in your JSON response from the server is that it contains only one item of data instead of an array (or list) of items representing the grid rows. The data should be at least
[
{
"id": 1,
"location": "office_2782",
"countryCode": "UK",
"quarter": "500",
"version": "v3.05",
"lastactive": "yesterday",
"lastlogin": "today",
"note": "no note",
"type": "read-only"
}
]
or better as
{
"total": 1,
"page": 1,
"records": 1,
"rows": [
{
"id": 1,
"location": "office_2782",
"countryCode": "UK",
"quarter": 500,
"version": "v3.05",
"lastactive": "yesterday",
"lastlogin": "today",
"note": "no note",
"type": "read-only"
}
]
}
or even as
{
"total": 1,
"page": 1,
"records": 1,
"rows": [
{
"id": 1,
"row": [ "1", "office_2782", "UK", "500", "v3.05",
"yesterday", "today", "no note", "read-only" ]
}
]
}
or
{
"total": 1,
"page": 1,
"records": 1,
"rows": [
[ "1", "office_2782", "UK", "500", "v3.05", "yesterday", "today",
"no note", "read-only" ]
]
}
The reason of such strange at the first glance JSON data is that jqGrid is designed to support paging, sorting and filtering/searching of data implemented on the server. So the parameters rows=10&page=1&sidx=id&sord=desc from the url sent to the server mean that jqGrid asks the server to get the first page (page=1) of the data with the page having 10 rows per page (rows=10). The data should be previously sorted by id (sidx=id) in the descending order (sord=desc). If you has small number of rows (under some hundert for example) you can use client based sorting, paging and filtering if you add loadonce:true parameter of the jqGrid, but the server based implementation allows you to work with really large dataset having many hundred thousands rows of data with very good performace.
I recommend you to read my this answer where I tried to explain how the additional elements of the server response "total", "page" and "records" will be used. The values of the parameters can be encoded in JSON either as numbers or as strings (on your taste).
If the user clicks on the column header of the 'location' column for example jqGrid will send new request to the server having sidx=location&sord=asc in the url. So it is important to understand, that the server can be asked to provide the data for the grid not once per grid, but many times and the request will contain some parameters chosen by the user who works with the jqGrid.
Defining of jsonReader (and sometimes additional jsonmap parameters for every column) you describe the structure of the server response. Using the information jqGrid read the response and fill the grid.
The demo shows that with the corresponding jsonReader you can read even your original JSON data.
The last advice for you from me would be to consider at the beginning to use loadError event handle which helps to inform the user about the errors reported by the server. In the answer I have shown how it can be implemented in the case of ASP.NET MVC. I don't use spring MVC myself so I can't give you direct examples of how to better implement the error reporting in spring MVC, but the main idea is the same in any server technology: in case of errors the server should respond with the response having an error HTTP status code. Inside of your implementation of the loadError event handle you decode the response and display the information about the error.