Thursday, May 30, 2013

AngularJS, PHP y SAP HANA

Ayer me di cuenta de que ha pasado un buen tiempo desde la ultima vez que escribi algo sobre SAP HANA...asi que decidi ponerme a pensar en algo intersante sobre lo cual escribir...revisando mis Feeds, me di cuenta de AngularJS El Super Heroico Framework MVW en JavaScript ...

Asi que...que tiene de bueno AngularJS? Bueno...de acuerdo con ellos...

Otros frameworks tratan con las deficiencias del HTML ya sea abstrayendo el HTML, CSS, y/o JavaScript o proveyendo una manera imperativa de manipular el DOM. Ninguna de estas formas trata con el problema de fondo, que es que el HTML no ha sido diseñado para vista dinamicas.

Asi que...en este blog, vamos a utilizar PHP para obtener informacion de SAP HANA, retornarla como un objeto JSON y presentarla en AngularJS.

Manos a la obra -;)

Primero...Cree un System DSN para mi conexion con SAP HANA...para poder llamarla desde PHP...

menu.php
<?php
$conn = odbc_connect("HANA_SYS","SYSTEM","********", SQL_CUR_USE_ODBC);
$query = "SELECT table_name from SYS.CS_TABLES_ where schema_name = 'SFLIGHT'";
$rs = odbc_exec($conn,$query);
$result = array();
while($row = odbc_fetch_array($rs)){
          $menu["table_name"] = $row["TABLE_NAME"];
          array_push($result,$menu);
}
echo json_encode($result);
?>

Este codigo va a permitirnos obtener todos los nombres de la tablas que se encuentran en el schema SFLIGHT...para que asi podamos mostrar una lista en la cual poder escoger una...

tables.php
<?php
$data = file_get_contents("php://input");
$objData = json_decode($data);
$data = $objData->data;
$conn = odbc_connect("HANA_SYS","SYSTEM","*********", SQL_CUR_USE_ODBC);
$query = "select column_name from SYS.CS_COLUMNS_ A inner join SYS.CS_TABLES_ B";
$query .= " on A.table_oid = B.table_oid where schema_name = 'SFLIGHT'";
$query .= " and table_name = '$data' and internal_column_id > 200 order by internal_column_id";
$rs = odbc_exec($conn,$query);
$result = array();
$fields = array();
$fields_array = array();
while($row = odbc_fetch_array($rs)){
          array_push($result,$row["COLUMN_NAME"]);
          $fields["FIELDS"] = $row["COLUMN_NAME"];
          array_push($fields_array,$fields);
}
sort($fields_array);
 
 
$content = array();
$table = array();
$query = "select * from SFLIGHT.$data";
$rs = odbc_exec($conn,$query);
array_push($content,$fields_array);
while($row = odbc_fetch_array($rs)){
          for($i=0;$i<count($result);$i++){
                    $table["$result[$i]"] = $row["$result[$i]"];
          }
          array_push($content,$table);
}
echo json_encode($content);
?>

Este codigo va a tener el nombre de una tabla como parametro y va a obtener los nombres de los campos y el contenido de la tabla...ambos scripts de PHP van a retornar un objeto JSON...

get_menu.js
function MenuCtrl($scope, $http) {
    $scope.url = 'menu.php';
        
        $http.post($scope.url).
        success(function(data, status) {
            $scope.status = status;
            $scope.data = data;
            $scope.tables = data;
        })
        .
        error(function(data, status) {
            $scope.data = data || "Request failed";
            $scope.status = status;        
        });
 
            $scope.gettable = function() {
                      $scope.url = 'tables.php';
        $http.post($scope.url, { "data" : $scope.table}).
        success(function(data, status) {
            $scope.status = status;
            $scope.data = data;
                              $scope.contents = data;
        })
        .
        error(function(data, status) {
            $scope.data = data || "Request failed";
            $scope.status = status;        
        });
    };
}

Este codigo simplemente va a leer los objetos JSON generados por los scripts de PHP...la primera parte para la lista y la segunda para los campos de la tabla y su contenido...

Finalmente...tenemos nuestro HTML que llama al script de AngularJS para hacer la magia...

main.html
<!DOCTYPE html>
<html ng-app>
<head>
<title>Angular.JS, PHP and SAP HANA</title>
    <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
    <script src="http://code.angularjs.org/angular-1.0.0.min.js"></script>
    <script src="get_menu.js"></script>
</head>
<body ng-controller='MenuCtrl'>
<div align="center">
          <H1>AngularJS, PHP and SAP HANA</H1>
          <form>
                    <label>Choose table:</label>
                    <select ng-model="table">
                              <option ng-repeat="table in tables" value='{{table.table_name}}'>{{table.table_name}}
                    </select>
                    <button type="submit" class="btn" ng-click="gettable()">Get Table</button>
          </form>
          <br/>
          <table border="1" ng-show="contents.length">
                    <tr ng-repeat="(key, value) in contents" ng-show="$first">
                              <th ng-repeat="values in value")>{{values.FIELDS}}</th>
                    </tr>
                    <tr ng-repeat="(key, value) in contents" ng-show="!$first">
                              <td ng-repeat="values in value")>{{values}}</td>
                    </tr>
          </table>
</div>
</body>
</html>

El codigo es simple...va a leer los objetos JSON y simplemente utiliza repetidores para leer la informacion y colocarla tanto en la lista como en la tabla.

Aqui hay algunas imagenes de la aplicacion ejecutandose...




Ahora...se habran dado cuenta de que los campos estan ordenados! Y no en el order original...bueno...este es mas un problem de JavaScript que de AngularJS...por lo menos eso es lo que he investigado...pero...a quien le importa finalmente?...la informacion esta completa y eso es lo que importa -;)

Otra cosa que hay que tener en cuenta...es que AngularJS no es particularmente veloz...para algunas tablas grandes...va a lanzar una excepcion por tiempo de ejecucion...aun cuando SAP HANA va a devolver la informacion bastante rapido...y de seguro PHP va a crear los objetos JSON tambien velozmente...yo pienso que el problema central es que AngularJS va a ordenar las columnas, leer cada linea y luego construir la tabla...o...quizas porque soy un principiante en AngularJS -:P

De cualquier modo...esta fue mi primera experiencia con AngularJS...y debo decir...me diverti mucho! -:D La curva de aprendizaje es bastante rapida y AngularJS provee muchas caracteristicas interesantes que lo convierten en una gran alternativa para el desarrollo web -;)

Nos vemos en el siguiente blog -}:)

Saludos,

Blag.

No comments: