call RPGLE program from SQL within PHP / Zend Framework - php

We have an AS400 RPGLE program created within the library LMTLIB, which is called ARTEST.
It has a single numeric inout parameter, which just returns 2
$myVar = "1";
$db = Zend_Registry::get('config')->resources->multidb->as400;
$abstractAdapter = new Zend_Db_Adapter_Db2($db);
//Gives the message "Invalid bind-variable position 'myVar'"
$sql = 'CALL QSYS.QCMDEXC(\'CALL LMTLIB.ARTEST PARM(?)\', 0000000026.00000)';
//Gives the message "Token PARM was not valid. Valid tokens: ( INTO USING. SQLCODE=-104"
$sql = 'CALL LMTLIB.ARTEST PARM(?)';
//Gives the message "ARTEST in LMTLIB type *N not found. SQLCODE=-204"
$sql = 'CALL LMTLIB.ARTEST (?)';
$stmt = new Zend_Db_Statement_Db2($abstractAdapter, $sql);
$stmt->bindParam('myVar', $myVar, 4, 1);
$stmt->execute();
Now, i can kind-of understand why the third SQL statement would fail with the "not found" message... because it is not a table / file, but rather an RPGLE program.
The thing thats irritating, is that if i remove the (?), and simply put in (1)... the SQL call appears to be successful, and the RPGLE program shows it had been called. However, I'm then not able to see what the response from the program was.
Thanks in advance for any help!

Generally, the database manager uses the CALL statement to invoke a stored procedure. When it does that, it looks for a stored proc whose parameter signature matches the signature of the CALL.
If there's no stored proc with that name and signature, the database manager tries to call a program. Again, there's a parameter matching process that happens.
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/db2/rbafzmstcallsta.htm
I suggest creating a stored procedure so you can get the parameters matched properly.

IBM RPGLE can interface with the Zend framework through webservice calls.
Scott Klement goes over some of the basics of this here.
Depending on your application, this may be the best way to interface with RPG code. Webservices can be made to call many RPG programs and iSeries tables, and return a catered result set. Zend would see this the same as any other RESTful call, which could be handled by your models.

Related

Laravel and stored procedures SQL

I have a stored procedure that client has made.
Now I have to access it and process data in my laravel app.
I have no problems with connecting to SQL but the problems starts when passing in parameters.
Here is my code:
$connections = DB::connection('sqlsrv')
->select(EXEC [stored].[procedure].[here] $param1, $param2);
The error I got back is:
The active result for the query contains no fields
I have searched for many hours in forums and here is what I have found:
$connections = DB::connection('sqlsrv')
->select(DB::raw('EXEC [stored].[procedure].[here] $param1, $param2'));
Error I got back is:
The active result for the query contains no fields.
I have installed SQL driver and OBDC driver.
Any help would be much appreciated
Don't know if this will help but this answer suggests you put your DB::raw around just the params instead of the EXEC stored.proc.name.
So instead of
$connections = DB::connection('sqlsrv')->select(DB::raw('EXEC [stored].[procedure].[here] $param1, $param2'));
Try
$connections = DB::connection('sqlsrv')->select('EXEC stored.proc.name' . DB::raw($param1, $param2));
OK. So I found out the issue.
It turns out the client sent me over a variable with xml.
As far as I figured out from Microsoft docs then you cant pass xml as a varable because if you call the SP from an application it is gonna pass it as an array and application cant parse xml into array directly. You have to do it on your own.
What can be done instead is to pass xml as a value of an array and then take it from there.

Adding Raw Query Parameters to SolrQuery requests

I'm using SolrClient with SolrQuery object, but I need to add RawQueryParameters to it:
How is this done? I'm fairly new to Solr requests and I could not find such option in the documentation.
So far I have this:
$SolrQuery = new \SolrQuery();
$SolrQuery->setStart($this->offset);
$SolrQuery->setRows($this->limit);
$SolrQuery->setQuery($request);
$SolrQuery->addField('*')->addField('units:[subquery]');
$SolrQuery->addParam('units.q', '{!terms%20f=id%20v=$row.unit_ids}');
When running toString() on this object, I get:
start=0&rows=2147483647&q=type:address&fl=*,units:[subquery]&units.q={!terms%20f=id%20v=$row.unit_ids}
what is the correct query. This works fine in CLI, but gives exception when executed in PHP as $queryResponse = $SolrClient->query($SolrQuery);:
Exception: while invoking units:[subquery] on doc=SolrDocument{id=stored,indexed,tokenized,omitNorms,indexOptions=DOCS
EDIT: Solution was to use addParam() without urlcoded request. Spaces go through just fine!
You can get the active parameters by calling ->toString() on the SolrQuery object - since SolrQuery inherits from SolrModifiableParams, you can call addParam directly on the query object to add custom parameters. This lets you add any parameter you want to the request. Be careful to add the parameter verbatim, since SolrQuery should handle necessary escaping for you.
If you still see an error, you can check the logging on the Solr server (under Admin -> Logging). If the log level is set to INFO, Solr will log all requests so you can see what Solr actually got. Any exceptions should also be present in this log if they're generated on the Solr side.
The Solr extension will usually throw exceptions as the class SolrClientException, which can be useful to determine the source of the error. A list of exception messages are also available in the extension source if you need to debug further.

PDO sets server response code?

I'm making an ajax query to a framework that we use. I am unable to set the server response code except by setting it where the PDO execute method is called.
The pattern works like this:
An ajax query runs, posting to a file, action.php, that validates inputs. If inputs are valid, we call a function in the business logic (application.php), which then calls the underlying PDO insert/save method. If we get a good save, we return TRUE in our action.php function.
In my ajax call, I have a .done() function that confirms the save took place by checking xhr.status. I want to set xhr.status to 201 when we have a successful save, by calling http_response_code(201);. This works if I actually do so in the PDO layer, right after the execute() method, but I can't get it to work anywhere else. Obviously, that is not the right place to set a response code.
Sorry the question is so abstract. Here is a little example of the code that isn't working:
$resInfo = new ResInfo();
if($resInfo = saveResident()){
http_response_code(201);
}
return true;
The response code is not set here. Instead, it is set in the PDO method that saveResident() calls.
Anyone else ever have a similar issue?
EDIT:
I realized that saveResident() returns a copy of the saved object rather than a boolean, so I needed to separate the call to it from persisting the saved object:
if(saveResident()){
$resInfo = saveResident();
http_response_code(201);
}
If you say:
it works within saveResident()
saveResident() runs successfully.
And not right after in that if statement.
I would guess that saveResident returns false, an empty array or nothing at all. $resInfo is not used after all.

How to route every mysql query through a function?

I have developed a project under which several sql query have been used. Now I want to monitor some query in order increase security. So I want every query to be passed through a function first. As there are too many queries so I can not go back and edit every file and query. Is there a way that I can trap into queries before they are sent to mysql server?
There are four ways to accomplish this depending on what you are using, the last being the much more reliable.
The General Query Log
MySQL provides a mechanism to log just about everything that the mysqld process is doing, via the general query log. As you described in your question you probably do not have persistent connections, so you will need to either:
Enable the MySQL general query log when the mysqld process is started, with the --log[=file_name]
Set a global/session variable with SET GLOBAL general_log = 'ON'.
Fore more information about the general query log, see the MySQL 5.1 reference manual.
Using sed (or manually!)
This technique involves creating a a new function, and renaming all of the mysqli_* function calls to call another function.
Presuming your newly created function is named proxy_query(), you can use sed to traverse through all files and change them automatically:
sed i '.bck' 's/mysqli_query/proxy_query/'
The -i paramater specifies that the file should be edited in place, and that a copy should be made of the original file and have a .bck extension appended.
The runkit extension
I must admit that I'm being naive here, and that I haven't used this particular extension before - but it is possible to rename functions with this PECL extension.
The requirements for this extension can be found here, and note that it is not bundled with PHP.
As with above, you can create a proxy function where all calls will go through. Let's assume it's also called proxy_query. Usage would go something like this:
// rename the function (a very bad idea, really!)
runkit_function_renam('mysqli_connect', 'proxy_super');
function mysqli_query($query, $resultmode = MYSQLI_STORE_RESULT)
{
// do something with the SQL in $query
// .. and call mysqli_query, now proxy_super
return proxy_super($query, $resultmode);
}
I have to note here that this method is highly discouraged. You shouldn't ever need to set default PHP functions.
Using Pdo/OO-mysqli
This is the simplest technique, and probably the most reliable as well. If you're using Pdo already, you can simply extend the \Pdo class. A similar approach could be used with MySQL Improved(mysqli):
class MyPdo extends \Pdo
{
public function query($query [, ... ])
{
// do something with $query
return parent::query($query [, ... ]);
}
}
Also note here, that this will only work if you are using Pdo, and if you are able to change the instantiation of the Pdo object, to overwrite it to your own class: MyPdo.
For more information about the \Pdo class, and it's children, see the manual.
If you want to monitor incoming queries using SQL profiler can be an excellent way to gather information on what's going on inside SQL without passing it all through a single function or procedure.

Any Javascript and PHP AJAX Interface generation suggestions, like thrift?

I am basically looking for Apache Thrift, but to talk between JavaScript over Ajax and PHP.
I know Thirft generates both, but to my knowledge the JavaScript code must talk over JSONProtocol, of which the protocol isn't yet wrote in PHP.
Are there any other alternatives that can suggested?
If you are unfamiliar with Thrift, this is a simple(ish) definition of what i need:
Consider this as the generic interface definition language (IDL), where I setup a User object, an AuthenticationResult result object, and method named UserCommands.Authenticate();
struct User {
1: number id,
2: string firstName,
3: string lastName
}
struct AuthenticationResult {
1: number currentTime,
2: User user
}
service UserCommands {
AuthenticationResult Authenticate(1:string username, 2:string password)
}
I run a program or something, it creates JS and PHP libraries based on the above.
Then, in JS, I could call (with helpful typehinting).
var myAuthResult = UserCommands.Authenticate('myUser', 'myPass');
alert ("My first name is : " + myAuthResult.user.firstName);
And in PHP, I would setup a method in a UserCommands class like this:
function Authenticate($username, $password) {
$myUser = new User();
$myUser->firstName = "Fred";
$myUser->lastName = "Thompson";
$myAuthResult = new AuthenticationResult ();
$myAuthResult->currentTime = date("U");
$myAuthResult->user = $myUser;
return $myAuthResult;
}
The benefits are that PHP can return native objects and JS can expect to receive its own native objects.
Type hinting for available methods are provided through out, with expected params and return results.
Any thoughts would be appreciated!
First of all, there're json_encode and json_decode functions in php.
Secondly, there's a serialize/unserialize for native php types
I don't understand, though, which you mean under "... of which the protocol isn't yet wrote in PHP."
Also, there's a Haxe langauge, which can be "compiled" into both PHP and JavaScript (and some other languages)

Categories