I’m working on an application integrating mapquest maps and using the mapquest API.
At this moment I want to achieve the following: the registered user has to input latitude and longitude information, and in the database this information has to be stored as geometry type field. Conversely, a user looking at their account should see the latitude and longitude information that was entered.
In an earlier simplified codebase I achieved this directly in the MySQL query, by using the MySQL functions AsText and GeomFromText. But now I’m on CodeIgniter and need to do the conversion in PHP
Is there anything equivalent in PHP to MySQL's AsText and GeomFromText functions?
It appears that the PHP unpack function is what is needed to extract the coordinate information.
MySQL stores the geometry fields in the WKB (Well Known Binary) format. The unpack function is able to extract that information when provided the proper format specifier. The following code is from a test script which successfully extracted the desired information.
Please note that my format for unpack differs slightly from that of the reference. This is because the WKB string wasn't retrieved from MySQL with the AsWKB() function, so it contains extra padding.
<?php
$padding = 0;
$order = 1;
$gtype = 1;
$lon = -73.91353;
$lat = 42.80611;
$bindata = pack('LcLd2', $padding, $order, $gtype, $lat, $lon);
printf("Packed: %s\n\n", bin2hex($bindata));
$result = unpack('Lpadding/corder/Lgtype/dlatitude/dlongitude', $bindata);
var_dump($result);
?>
References MySQL and ESRI Network.
I, too, am trying to extract geometry field data.I am using the MySQLi class to retrieve rows of data and display it according to field type.
While I haven't yet figured out how to decode the geometry field data, I can view it by using the bin2hex function. A point stored using GeomFromText('POINT(-73.91353 42.80611)')
using bin2hex gives me a 50 character string value of
0000000001010000008d7a8846777a52c0417dcb9c2e674540
A partial list of field type numbers can be found here.
I hope that this helps you! If I discover more, I'll pass it on here.
Related
I want to read mysql POINT column and convert it into WKT. As you know data format of GEOMETRY in MySQL is WKB so to convert with GeoPHP you should:
$wkb_reader = new WKB();
$geometry = $wkb_reader->read($val,FALSE);
$wkt_writer = new WKT();
$wkt = $wkt_writer->write(oGeometry);
Where $val is an BLOB (array of bytes).
It face with error (while reading data):
Exception: Only NDR (little endian) SKB format is supported at the moment
EDIT:
Here is the same problem but the $val may be a point
As you know MySQl (and MariDB) store geometry data as follow:
MySQL stores geometry values using 4 bytes to indicate the SRID followed by the WKB representation of the value. For a description of WKB format, see Well-Known Binary (WKB) Format.
See MySQL documents for more information.
So, first 4 bytes are SRID and must removed from data. You could convert any Geo data (from my MySQL) as follow:
$data = unpack("lsrid/H*wkb", $val);
$wkb_reader = new WKB();
$geometry = $wkb_reader->read($data['wkb'], TRUE);
$wkt_writer = new WKT();
$wkt = $wkt_writer->write($geometry);
return $wkt;
More info: https://stackoverflow.com/a/45089036/635891
Selecting from database field that has Geometry type returns weird string to PHP.
Is there in PHP some kind of class that can convert that string to something usable? Or I have to convert all my sql queries (ex using AsText(geo_field)) ?
You can use brick/geo for this purpose. It can read all geometries (Point, LineString, Polygon, etc.) as typed objects that you can interact with:
You can select using ST_AsText() from your database, then:
$polygon = Polygon::fromText('POLYGON ((0 0, 0 3, 3 3, 0 0))');
echo $polygon->area(); // 4.5
If you're using Doctrine, the library comes with mapping types that do the job for you.
Disclaimer: I'm the author.
I recently switched from MySQL to PostgreSQL. I have one problem left however.
Previously, I would store small images in the BLOB format in MySQL.
PostgreSQL doesn't know such thing as a BLOB.
I tried using BYTEA field type instead. This actually inserts an large (hexadecimal?) string I guess, but now I'm stuck trying to get this string back to displaying an actual image in PHP..
Any ideas? Thanks in advance.
Here is a piece of code I use to save the image in the database:
$data = bin2hex(file_get_contents('php://input'));
if (!empty($data)) {
$sql = "UPDATE asset SET data = X'%s' WHERE uuid = '%s'";
$args = array($data, $asset_uuid);
}
psql (9.1.3) and php 5.3.6 are used
Bytea is a byte array. It's not a bit pattern. See section 4.2.1.5 of PostgreSQL Lexical Structure.
The correct way to enter bytea is '\x...' with hex values. So what you want is SET data = '\x%s'.
You might also want to look into prepared statements with pg_prepare.
Edit: I was able to insert a (text) file into a bytea with this:
$source = file_get_contents( 'hello.php' );
$insert = pg_prepare( $conn, '', 'insert into t (name, data) values($1,$2)' );
pg_execute( $conn, '', array( 'hello.php', $source ) );
3rd Edit: This works fine to insert the file into the database. However, the pgsql driver in PHP is quite impolite. The only way to retrieve the actual data back is using the old bytea escape mechanism, as detailed here: pg_unescape_bytea.
pg_query('SET bytea_output = "escape";');
$result = pg_query( 'select data from t' );
while ( $row = pg_fetch_row( $result ) ) {
echo pg_unescape_bytea( $row[0] );
}
I'm sorry about how annoying this is. The PostgreSQL interface in PHP can do with some major overhaul for binary values.
To insert bytea contents with the pg_* API, the binary value should always be run through the pg_escape_bytea() function, even if it's passed to the pg_execute or pg_query_params functions.
This is because the pg_* layer doesn't "know" that a particular parameter has binary contents, and it does not implement any real support for parameter types anyway. So the text representation must be used. It can either be in the escape form or the hex form, it doesn't matter to the PG server, and it's independant of the value of bytea_output, which is meaningful only for values read from the server.
Example:
$esc=pg_escape_bytea("\000\001\002");
pg_query_params('INSERT INTO some_table(some_col) VALUES($1)', array($esc));
To read bytea contents with the pg_* API, the value must be run through pg_unescape_bytea() after the fetch. Assuming the client library is not older than 9.0 (libq.so.5.3 or higher), it can decode the contents whether it's in hex form or escape form and it will autodetect it. Only with an older library would it be necessary to force bytea_output to escape for it to decode properly, either dynamically with SET or statically for the whole database (ALTER DATABASE SET bytea_output=escape) or in postgresql.conf for the whole instance.
Example:
$p=pg_query("SELECT some_col FROM some_table WHERE...");
$r=pg_fetch_array($p);
$contents = pg_unescape_bytea($r[0]);
Both answers posted here gave me some thoughts, but none were 100% of the answer.
So, I will explain in this answer what I did to get it to work.
When displaying the image, I used this:
header('Content-Type: image/jpeg');
$data = pack("H*", pg_unescape_bytea($data));
echo $data;
I'm running PHP 5.3.8, in PHP 5.4.0 it turns out you can use hex2bin instead of pack.
When adding the image to the database, I used this:
$data = pg_escape_bytea($data); // Escape input for PostgreSQL
$sql = "UPDATE asset SET data = '%s'WHERE uuid = '%s'";
I'm glad it is working now. Thank you both Daniel and Johann!
I just want to know how can I add the data type here? Google Charts requires data type when I use this code:
Im getting an error from google charts that it datatype needs to be defined...please help. Thanks!
while($r = mysql_fetch_assoc($query)) {
$google_JSON = "{cols: [";
$column = array_keys($r);
foreach($column as $key=>$value){
$google_JSON_cols[]="{id: '".$key."', label: '".$value."'}";
}
$google_JSON .= implode(",",$google_JSON_cols)."],rows: [";
$google_JSON_rows[] = "{c:[{v: '".$r['id']."'}, {v: ".$r['count']."}]}";
}
// you may need to change the above into a function that loops through rows, with $r['id'] etc, referring to the fields you want to inject..
//pass it into google charts data
echo $google_JSON.implode(",",$google_JSON_rows)."]}";
I haven't done any PHP in ages so I'm not going to offer to provide any patches to your code but the data type goes in the array elements of the cols hash reference i.e., where you create {id:"key", label: "value"} you need to add 'type: "number"' or 'type: "string"' etc. How you determine whether it is a number of a string by referring back to your query is not going to be that simple. You could look at the column type via whatever metadata the mysql module provides for the column but most charts require number types for the series and string/number types for the x-axis values. You could always set the first column to string or number and the other columns to number but it would depend on the sort of chart you are creating.
BTW, I'm surprised you cannot create the structure natively in PHP and then convert to JSON rather than building the JSON string up like this - you can in Perl quite easily.
I was trying to export database query to CSV and the need arised to use different decimal comma. It seems impossible to change the decimal comma in MySQL, so I tried in PHP:
setlocale(LC_NUMERIC, "cs_CZ");
But it seems that all the database functions like mysql_fetch_row and mysql_fetch_assoc are retrieving data of type string instead of double:
$res = mysql_query("select 50/3");
$row = mysql_fetch_row($res);
var_dump($row); // $row[0] is of type "string"
So in general PHP already doesn't have data of type double, but only strings!
So is there some general, clean way to specify output of the decimal point?
I ended up converting the strings using str_replace('.', ',', $row[0]) but this is ugly for two reasons:
you have to know which field is of type double
it's a dirty string job.
I don't know which database client/driver you're using but there is something like mysql_field_typeDocs which gives you the type based on it's offset, like 0.
This should do the job to find out if a certain column needs re-formatting or not.
To reformat, there is number_formatDocs.
With these you can do the conversion automatically.
Edit: Regarding your comments:
If you want to get PHP datatypes mapped, consider using the MySQL Native DriverDocs. Use it together with PDO:
Advantages of using mysqlnd for PDO
mysqlnd returns native data types when using Server-side Prepared Statements, for example an INT column is returned as an integer variable not as a string. That means fewer data conversions internally. Source
So depending of what you try to achieve, use the right tool.
See as well the multiple options you have when fetching data from a PDO StatementDocs.
// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
Try
number_format($row[0], 2, ",", ".");
That should change the format of the number. (german format)