I have a problem about service in Angular2/4.
I keep getting
ERROR SyntaxError: Unexpected token ' in JSON at position 0.
This is my backend using CI.
This is my controller book.php:
//get book from database
function list_book_get()
{
//call method get_list_book() in model m_book
$dataBook = $this->m_book->get_list_Book();
//if dataBook exist
if($dataBook != null) {
$output['status'] = true;
$output['data'] = $dataBook;
} else { // if dataBook not exist
$output['status'] = false;
$output['message'] = "empty";
}
//send response
$this->response(json_encode($output));
}
The model in CI:
function get_list_book() {
return $this->db->get('book')->result();
}
And this is my service in Angular 4:
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map' ;
#Injectable()
export class BookService {
constructor(private http: Http) {
}
books=[];
getBooks(){
return this.http.get("http://localhost/restserver/book/list_book.php")
.map(res => res.json());
}
}
That is my json from CI:
'{"status":true,"data":
[{"id":"1","title":"SAINS","author":"ERLANGGA","isbn":"089928778"},
{"id":"2","title":"Geography","author":"ERLANGGA","isbn":"089182372"},
{"id":"3","title":"Math","author":"Srilangka","isbn":"091283181"},
{"id":"4","title":"test","author":"test","isbn":"1283798127"},
{"id":"5","title":"AAAA","author":"BBB","isbn":"91092301290"},
{"id":"6","title":"BBB","author":"CCC","isbn":"01920192"}]}'
I assume that quotation mark (') in my json that make my apps error.
How to remove that quotations?
Proper way to send json reponse from CI Controller is :
function list_book_get()
{
...
return $this->output
->set_content_type('application/json')
->set_output(json_encode($output));
}
You are getting json in single quotes bcoz (means as string) , you
haven't defined the content type.
Related
Angular 6 :
import {Injectable} from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class GetData {
constructor( private http: HttpClient ) { }
post( ) {
data = [ {username : 'test',password : '1234' }];
return this.http.post('login.php' , data );
}
}
PHP : login.php
<?php
$username = $_POST['username'];
$password = $_POST['password'];
?>
How can i get data from Angular 6 that is [Object] into $username , $password
**
"$_POST" and "$_REQUEST" is not available for me.
**
Try this:
import {Injectable} from '#angular/core';
import { HttpClient,HttpParams } from '#angular/common/http';
#Injectable()
export class GetData {
constructor( private http: HttpClient ) { }
post( ) {
let data= new HttpParams()
.append("username", "test")
.append("password", "1234")
return this.http.post('login.php' , data );
}
}
For some reason Angular seems to send POSTs that end up in php://input instead of $_POST, and then you can json_decode them into an object and use them.
On the Angular side - I'm just tossing data at the server, I care not about the response... tried getting it going without the whole subscribe() thing but it wouldn't POST at all for me at that point... Note taht there is a private http: Http in the constructor for the TS file/component/class this is in...
postChatMessage(room: string, user: string, msg: string, timestamp: number) {
var cmsg = new ChatMessage(room, msg, user, timestamp);
return this.http.post(BASEURL + "/chat", cmsg)
.subscribe(
(v) => {},
response => {},
() => {}
);
}
The PHP on the back end that handles the POST that sends - yes, I'm being lazy and just storing the whole JSON string sent plus a few other things, but easier for me to deal with for a quick school thing -
if (($_SERVER['REQUEST_METHOD'] == "POST") &&
(strpos($_SERVER['REQUEST_URI'], "/json_service/chat") === 0)) {
$d = file_get_contents("php://input");
$d = json_decode($d);
$d->timestamp = time();
$q = "insert into json_chat values(?,?,?,?)";
$a = array(null, time(), $d->room, json_encode($d));
$res = executeQuery($q, $a);
print(json_encode(array($res[0]))); // boolean fwiw
exit;
}
I'm trying to handle this problem:
My app send JSON POST request with several information encoded in a Json. Example:
{"UserInfoA":{"1":123,"2":"hello","3":"bye","4":{"subinfo":1,"subinfo2":10}},
"UserInfoB":{"a":"12345678","b":"asd"}} // and so on...
each UserInfo have:
Its own entity (although some request may have information of more than one entity).
A controller to persist this Object on DB and then give back the ID on this DB.
So, to achieve this problem I did another controller like JsonHandler, which receive this request and then forward to each controller after gut this JSON into differents objects. Example:
public function getJson (Request $request){
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
$data = json_decode($request->getContent(), true);
}
if (!isset($data['UserInfoA'])){
return new JsonResponse('ERROR');
}
$uia = $data['UserInfoA'];
$idInfoA = $this->forward('Path::dataAPersist',array('data'=>$uia));
}
// same with userinfoB and other objects
return $idInfoA ;
This works perfectly but Is it correct? Should i use services instead?
EDIT : I need to response the ID in a Json and this->forward returns a Response, so i can't use JsonResponse and if a send directly $idInfoA just send the IDNUMBER not in a JSON, how can i do it?
To sum up : a Json listener that receive the information, work it and then dispatch to the corresponding controller. This listener, should be a controller, a service or another thing?
I recommend the use of symfony-bundles/json-request-bundle since it does the JsonRequestTransformerListener for you. You just need to recieve the request parameters as usual:
...
$request->get('some_parameter');
...
hi you have to use service to make the Transformation
class php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class JsonRequestTransformerListener {
public function onKernelRequest(GetResponseEvent $event) {
$request = $event->getRequest();
$content = $request->getContent();
if (empty($content)) {
return;
}
if (!$this->isJsonRequest($request)) {
return;
}
if (!$this->transformJsonBody($request)) {
$response = Response::create('Unable to parse request.', 400);
$event->setResponse($response);
}
}
private function isJsonRequest(Request $request) {
return 'json' === $request->getContentType();
}
private function transformJsonBody(Request $request) {
$data = json_decode($request->getContent(), true);
if (json_last_error() !== JSON_ERROR_NONE) {
return false;
}
if ($data === null) {
return true;
}
$request->request->replace($data);
return true;
}
}
And In Your Service.yml
kernel.event_listener.json_request_transformer:
class: You\NameBundle\Service\JsonRequestTransformerListener
tags:
- { name: "kernel.event_listener", event: "kernel.request",method: "onKernelRequest", priority: "100" }
Now You can call The Default request function to get Data
$request->request->all();
You can use symfony ParamConverter to to convert the json into any object you want and raise a meaningful Exception if anything goes wrong.
You can add custom ParamConverters and use them in your actions with annotation
I'm trying to develop an app that uses Angular on front and Laravel 5.0 at back.
In HTTP requests, I'm having a hard time getting errors.
This is my MenuController.php that gives my menus to Angular as JSON:
if($control){
$response->data = Menu::get()->toArray();
}
if(!$control) {
$response->error = 'Error!';
}
return json_encode($response);
And this is my menu.service.ts:
private menusUrl = '/api/menu';
constructor (private http: Http) {}
getMenus(): Observable<Menu[]> {
return this.http.get(this.menusUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
And this is the menu-index.component.ts:
errorMessage: string;
menus: Menu[];
mode = 'Observable';
constructor(private menusService: MenusService) { }
ngOnInit() { this.getMenus(); }
getMenus() {
this.menusService.getMenus()
.subscribe(
menus => this.menus = menus,
error => this.errorMessage = <any>error);
}
The part where I get my menus from Laravel works fine, but I couldn't get the error messages.
Hint: My Angular files are nearly exact copies of the ones that are presented in Angular HTTP Client tutorial. The main problem is how should I return my errors using Laravel so that Angular catches them.
I see a number of things you can improve:
You don't need to manually serialize your data carrier. Laravel handles that for you. All you need to do is return $response.
Your handle error should return the error message. The way chained promises work is that the callback to invoke next receives the return value from the former. So I believe it should be sufficient to return return errMsg.
I do not know if these improvements would resolve your issue, but it is certainly one step in the debugging process.
It turns out that I was not returning a proper error response. Here is the related part in the corrected version of MenuController.php:
if(!$control) {
$response['error'] = 'ERROR!';
return (new Response($response, 400))
->header('Content-Type', 'application/json');
}
I have below code that save the country information in Database. Below code works fine. There is no problem in that.
private function SaveChanges(\App\Http\Requests\CountryRequest $request) {
if($request['CountryID'] == 0) {
$Country = new \App\Models\CountryModel();
}
else {
$Country = $this->GetCountry($request['CountryID']);
}
$Country->Country = $request['Country'];
$Country->CountryCode = $request['CountryCode'];
$Country->save();
return redirect()->route($this->AllCountries);
}
Now, I decided to shift the working of above method inside a new class like below. Here I am reading the JSON data
class CountryData {
public function CreateCountry($CountryObject) {
$obj = json_decode($CountryObject);
$Country = new \App\Models\CountryModel();
$Country->Country = $CountryObject->Country;
$Country->CountryCode = $CountryObject->CountryCode;
$Country->save();
return true;
}
}
and the original function is changed like below. Sending the Request parameter in the form of JSON.
private function SaveChanges(\App\Http\Requests\CountryRequest $request) {
$data = array(
'Country' => $request['Country'],
'CountryCode' => $request['CountryCode'],
'CountryID' => $request['CountryID']
);
if($request['CountryID'] == 0) {
$result = (new \CountryData())->CreateCountry( json_encode($data) );
}
return redirect()->route($this->AllCountries);
}
Question: Is my approach correct to send converted request object to JSON object and reading in an another Class .
I am doing that so that I can create a new controller and call the CreateCountry from class CountryData to return JSON data for an Android App.
Well, I don't think it's a good approach. Your CountryData class acts as a service, so I think it hasn't have to know anything about JSON, that is part of the interface between your business logic and the external side of your system (Android app, web interface, etc.)
Your new Controller may receive JSON objects and answer with JSON objects, but it must convert the JSON received to your business classes, then pass them to your services, in this case CountryData (not a good name, though).
So the logic should be:
Controller:
- receive request data
- call service and save or whatever
- encode to JSON
- send the response in JSON format
So your business classes don't know anything about JSON.
A not fully code solution is provided as an idea, but it lacks error management, and more work to do. It's based on some Laravel 5 features. Also I don't know if you're using REST or what kind of request are you doing...
use App\Http\Controllers\Controller;
class CountryController() extends Controller {
public function store(\App\Http\Requests\CountryRequest $request) {
// TODO manage errors
$countryModel = $this->createOrUpdateCountry($request);
// Laravel way to response as JSON
return redirect()->json($this->country2Array($countryModel);
}
private function createOrUpdateCountry(\App\Http\Requests\CountryRequest $request) {
$countryId = $request['CountryID'];
if($id == 0) {
$countryModel = new \App\Models\CountryModel();
} else {
$countryModel = $this->GetCountry($countryId);
}
$countryModel->Country = $request['Country'];
$countryModel->CountryCode = $request['CountryCode'];
// You must have an initialised instance of CountryDAO
// TODO manage errors
$countryDAO->saveOrUpdate($countryModel);
return $countryModel;
}
private function country2Array($countryModel) {
$data = array(
'country' => $countryModel->Country,
'countryCode' => $countryModel->CountryCode,
'countryId' => $countryModel->CountryID
);
return $data;
}
}
/**
* Formerly CountryData
*/
class CountryDAO {
public function saveOrUpdate($countryModel) {
// TODO Manage errors or DB exceptions
// I'd put the DB save access/responsability here instead of in CountryModel
$countryModel->save();
return true;
}
}
First of you should not do any conversions to objects and so on.
Second, since the request object should be an array as shown on your example I suggest you to use the "fill" method of Laravel, instead of looping on hand all of the request elements.
Your code for saving the request should be as follows:
class CountryData {
public function CreateCountry($requestData) {
$Country = new \App\Models\CountryModel();
$country->fill($requestData);
$Country->save();
return true;
}
}
The "fill" method loops all of the array keys and tries to set them into the object instance if it has those keys as properties. If there are any extra fields, they are trimmed and you wont get any errors.
Cheers! :)
I'm trying to figure out how to convert a PHP SOAP client over to Groovy using groovy-wslite. The PHP code I have looks like this
<?php
define ('WSDL','https://….wsdl');
define ('EndPoint','https://…');
define ('URI','urn:ws.….com');
$client = new SoapClient(WSDL,array(
'location' => EndPoint,
'uri' => URI,
'trace' => TRUE,
));
try
{
$user="…";
$pass="…";
//parameters passed as array
$loginResult = $client->login(array("username"=>"$user", "password"=>"$pass")); //session ID and jsession returned from this call
print "<br>Logging In: Success!. <br>";
print "<br>The session id is {$loginResult->result->sessionId}<br>";
}
catch (SoapFault $err) {
print "failed!\n";
print "Login Error: ".$err->faultString."\n";
$loggedIN = false;
}
?>
Here is some example groovy code (that works) which I'm trying to fit my code into.
#Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='0.8.0')
import wslite.soap.*
def client = new SOAPClient('http://www.holidaywebservice.com/Holidays/US/Dates/USHolidayDates.asmx')
def response = client.send(SOAPAction:'http://www.27seconds.com/Holidays/US/Dates/GetMothersDay') {
body {
GetMothersDay('xmlns':'http://www.27seconds.com/Holidays/US/Dates/') {
year(2011)
}
}
}
Here is the code I started when I attempted to merge the two
#Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='0.8.0')
import wslite.soap.*
def client = new SOAPClient('<EndPoint>')
def response = client.send(SOAPAction:'login') {
body {
login('xmlns':'[what do I put here]') {
username("<user>"),
password("<pass>")
}
}
}
So I think I replace the SOAPClient with my EndPoint, but I kind of lose it when I get to the SOAPAction and body portions of the Groovy code.
Can anyone help me convert the PHP code to the Groovy-wslite equivalent?
After much trial and error I got the login working
#Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='0.8.0')
import wslite.soap.*
def client = new SOAPClient(<EndPoint>)
def response = client.send(SOAPAction:<EndPoint>) {
body {
login('xmlns':<URI>) {[
username(<user>),
password(<pass>)
]}
}
}