If I try to create a record with something like
var myObject = App.ModelName.createRecord( data );
myObject.get("transaction").commit();
the id of myObject is never set.
This says that id generation should be handled by EmberData (first response). So what should be happening? Where is the new id determined. Shouldn't there be a callback to the API to get valid id?
ID is the primary key for your record which is created by your database, not by Ember. This is JSON structure submit to REST post, notice no ID.
{"post":{"title":"c","author":"c","body":"c"}}
At your REST Post function you must get the last insert ID and return it back with the rest of the model data to Ember using this following JSON structure. Notice the ID, that is the last insert ID. You must get that last insert ID manually using your DB api.
{"post":{"id":"20","title":"c","author":"c","body":"c"}}
This is my sample code for my REST post. I coded this using PHP REST Slim framework:
$app->post('/posts', 'addPost'); //insert new post
function addPost() {
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
//logging json data received from Ember!
$file = 'json1.txt';
file_put_contents($file, json_encode($data));
//exit;
foreach($data as $key => $value) {
$postData = $value;
}
$post = new Post();
foreach($postData as $key => $value) {
if ($key == "title")
$post->title = $value;
if ($key == "author")
$post->author = $value;
if ($key == "body")
$post->body = $value;
}
//logging
$file = 'json2.txt';
file_put_contents($file, json_encode($post));
$sql = "INSERT INTO posts (title, author, body) VALUES (:title, :author, :body)";
try
{
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("title", $post->title);
$stmt->bindParam("author", $post->author);
$stmt->bindParam("body", $post->body);
$stmt->execute();
$insertID = $db->lastInsertId(); //get the last insert ID
$post->id = $insertID;
//prepare the Ember Json structure
$emberJson = array("post" => $post);
//logging
$file = 'json3.txt';
file_put_contents($file, json_encode($emberJson));
//return the new model back to Ember for model update
echo json_encode($emberJson);
}
catch(PDOException $e)
{
//$errorMessage = $e->getMessage();
//$data = Array(
// "insertStatus" => "failed",
// "errorMessage" => $errorMessage
//);
}
}
With some REST adapters, such as Firebase, you can define the id as a variable of the record you are going to create.
App.User = DS.Model.extend({
firstName: DS.attr('string')
});
var sampleUser = model.store.createRecord('user', {
id: '4231341234891234',
firstName: 'andreas'
});
sampleUser.save();
JSON in the database (Firebase)
"users": {
"4231341234891234": {
"firstName": "andreas"
}
}
Related
I need to validate shipping information entered when goods are dispatched. (I am having a nightmare using Cake!)
Each shipping company has a different format for their tracking references. I have written some regex to validate, and these are stored in my database.
All the validation for CakePHP happens in the model so I cannot use $this to retrieve the correct regex.
The regex is available in the view; is there anyway to use this to validate before the form is submitted?
I am currently sending the data through an ajax call
Controller
public function editTracking() {
$this->autoRender = false;
if ($this->request->is('ajax')) {
if($this->GoodsOutNote->save($this->request->data['GoodsOutNote'])){
$this->GoodsOutNote->save($this->request->data['GoodsOutNote']);
print_r($this->request->data['GoodsOutNote']['tracking_details']);
}else{
print_r($errors = $this->GoodsOutNote->validationErrors);
}
}
}
View
<?php echo $this->Form->create('GoodsOutNote',array(
'action'=>'editTracking','default' => false)); ?>
<fieldset>
<?php
echo $this->Form->input('id',array(
'default'=>$goodsOutNote['GoodsOutNote']['id']));
echo $this->Form->input('tracking_details',array(
'default'=>$goodsOutNote['GoodsOutNote']['tracking_details']));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit'));
$data = $this->Js->get('#GoodsOutNoteEditTrackingForm')->serializeForm(array(
'isForm' => true, 'inline' => true));
$this->Js->get('#GoodsOutNoteEditTrackingForm')->event('submit',
$this->Js->request(
array('action' => 'editTracking', 'controller' => 'goods_out_notes'),
array(
'update' => '#tracking_details,#GoodsOutNoteTrackingDetails',
'data' => $data,
'async' => true,
'dataExpression'=>true,
'method' => 'PUT'
)
)
);
echo $this->Js->writeBuffer();
?>
In the view, I can use $goodsOutNote['ShippingMethod']['valid_regex'] to access the correct format but I am lost as to how I can pass this to the form.
I have fixed this using the following approach.
In my controller, I retrieve the full record that I am about to edit. I can then validate the input using preg_match(). I would really appreciate any comments on this - is there a better approach?
public function editTracking() {
$this->autoRender = false;
if ($this->request->is('ajax')) {
$id = $this->request->data['GoodsOutNote']['id'];
$options = array('conditions' => array('GoodsOutNote.' . $this->GoodsOutNote->primaryKey => $id));
$goodsOutNote = $this->GoodsOutNote->find('first', $options);
$trackingRef = $this->request->data['GoodsOutNote']['tracking_details'];
$regex = "/".$goodsOutNote['ShippingMethod']['valid_regex']."/";
if(preg_match($trackingRef,$regex)){
if($this->GoodsOutNote->save($this->request->data['GoodsOutNote'])){
$this->GoodsOutNote->save($this->request->data['GoodsOutNote']);
print_r($trackingRef);
}
else{
print_r($errors = $this->GoodsOutNote->validationErrors);
}
}
else {
print_r($errors = $trackingRef.'is not valid');
}
}
}
I am trying to implement Tags to my posts. the user will input the tags in a textbox separated by commas.
public function addAction() {
$entityManager = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
$article = new Article;
$form = new ArticleForm();
$form->setHydrator(new DoctrineHydrator($entityManager,'CsnCms\Entity\Article'));
$form->bind($article);
$request = $this->getRequest();
if ($request->isPost()) {
$post = $request->getPost();
$form->setData($post);
if ($form->isValid()) {
$this->createTags($article, $post["Tags"]);
$this->prepareData($article);
$entityManager->persist($article);
$entityManager->flush();
return $this->redirect()->toRoute('csn-cms/default', array('controller' => 'article', 'action' => 'index'));
}
}
return new ViewModel(array('form' => $form));
}
in the above code i have added a class called createTags that i am planning to split the inputted tags into an array and create a new tag entity for each and then store the new tag entities in a array in the article object. Is this the correct way I should be doing this?
No, you wont be able search your pages based on tag if you store them in an array. you need to have a separated db table with columns like id,tag,pageId so you can properly search the pages with tag names.
Sorry if the question want that detailed was just wondering if I should use a filter instead (I think this would work but dont know if it is good practice)
In the end I just use the processData function
public function prepareData($article, $post) {
$separator = ",";
if($post['tagsString'] != "")
{
//Link Tags
$array = array_unique(explode($separator, $post['tagsString']));
foreach ($array as $tagString) {
$tag = $this->getEntityManager()->getRepository('Cms\Entity\Tag')->findOneBy(array('tag' => $tagString));
$link = new \Cms\Entity\LinkTagToArticle($article, $tagString, $tag);
$this->getEntityManager()->persist($link);
}
}
}
I have a User entity and in the edit Action I present a form to edit the user. I would like to have a password field available. If the password is blank, then I would like to update all field except the password, and if something is entered then all fields would be updated.
Here is my controller action.
public function editUserAction() {
$id = (int) $this->params()->fromRoute('id', 0);
if (!id) return $this->redirect()->toRoute('index', array('action' => 'users));
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$form = new UserForm($objectManager);
$user = $objectManager->find('Application\Entity\User', $id);
$form->bind($user);
if ($this->request->isPost()) {
$form->setData($this->request->getPost());
if ($form->isValid()) {
$data = $this->request->getPost();
if ($data->user['password'] == '') {
// how to save all but one field
}
else {
$objectManager->persist($user);
$objectManager->flush();
}
}
}
}
use the remove method:
vendor/zendframework/zendframework/library/Zend/Form/Fieldset.php
remove Remove a named element or fieldset
Parameters:
string
$elementOrFieldset
PHPDoc not found
Returns:
Type:
FieldsetInterface
if ($data->user['password'] == '')
{
$form->remove('password');
$objectManager->persist($user);
$objectManager->flush();
}
Everything else works fine except for the location. The actual city/state does not come across. Instead the word Array is displayed. My field type in the database is text but I've tried every field type through mysql. The HTML file is JSON where it comes to the field names. I am very new at this so any help is appreciated.
This is my php file:
<? ob_start(); ?>
<?php
define('FACEBOOK_APP_ID', '');
define('FACEBOOK_SECRET', '');
// No need to change function body
function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
error_log('Unknown algorithm. Expected HMAC-SHA256');
return null;
}
// check sig
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
if ($_REQUEST) {
$response = parse_signed_request($_REQUEST['signed_request'],
FACEBOOK_SECRET);
/*
echo "<pre>";
print_r($response);
echo "</pre>"; // Uncomment this for printing the response Array
*/
$name = $response["registration"]["name"];
$email = $response["registration"]["email"];
$gender = $response["registration"]["gender"];
$prosecutor = $response["registration"]["prosecutor"];
$location = $response["registration"]["location"];
// Connecting to Database
$con = mysql_connect("my_hosting_site","Database","password");
if (!$response)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("Database", $con);
mysql_query("INSERT INTO my_table (name, email, gender, prosecutor, location)
VALUES ('$name', '$email', '$gender', '$prosecutor', '$location')");
mysql_close($con);
}
$URL="https://www.facebook.com";
header ("Location: $URL");
?>
<? ob_flush(); ?>
Facebook
Basically, it's an array.
[location] => Array
(
[name] => Delhi, India
[id] => 1.1604xxxxxx286E+14
)
Use this for getting location stored in your db, like I have written below:
$location = $response["registration"]["location"]["name"];
I have been following this tutorial. Basically I want to take an address from a table I have and place that address on a google map. The tutorial seems pretty straight forward, create the table places, put the behavior in and model and what not.
Just kind of confused how I'd actually use that with my existing tables. I've read through the section in the cookbook about behaviors but am still a little confused about them. Mostly about how I'd integrate the tutorial into other views and controllers that aren't within place model?
first you need to add latitude / longitude coordinates to your address table...
you can do that with a writing parser around this google maps api call:
http://maps.google.com/maps/api/geocode/xml?address=miami&sensor=false
once your addresses contain the coordinates, all you need is to pass the coordinates
to a javascript google maps in your view, just copy the source :
http://code.google.com/apis/maps/documentation/javascript/examples/map-simple.html
here is a cakephp 2.0 shell to create latitude / longitude data
to run: "cake geo"
GeoShell.php :
<?php
class GeoShell extends Shell {
public $uses = array('Business');
public function main() {
$counter = 0;
$unique = 0;
$temps = $this->Business->find('all', array(
'limit' => 100
));
foreach($temps as $t) {
$address = $this->geocodeAddress($t['Business']['address']);
print_r($address);
if(!empty($address)) {
$data['Business']['id'] = $t['Business']['id'];
$data['Business']['lat'] = $address['latitude'];
$data['Business']['lng'] = $address['longitude'];
$this->Business->save($data, false);
$unique++;
}
}
$counter++;
$this->out(' - Processed Records: ' . $counter . ' - ');
$this->out(' - Inserted Records: ' . $unique . ' - ');
}
public function geocodeAddress($address) {
$url = 'http://maps.google.com/maps/api/geocode/json?address=' . urlencode($address) . '&sensor=false';
$response = #file_get_contents($url);
if($response === false) {
return false;
}
$response = json_decode($response);
if($response->status != 'OK') {
return false;
}
foreach ($response->results['0']->address_components as $data) {
if($data->types['0'] == 'country') {
$country = $data->long_name;
$country_code = $data->short_name;
}
}
$result = array(
'latitude' => $response->results['0']->geometry->location->lat,
'longitude' => $response->results['0']->geometry->location->lng,
'country' => $country,
'country_code' => $country_code,
'googleaddress' => $response->results['0']->formatted_address,
);
return $result;
}
}