Zend_Config_Xml - zend-framework

So i will list my problems here, please help
First of all, i use Zend_Http_Client to call to an url:
$client = new Zend_Http_Client('http://mydomain.com/Statistics.aspx?activity=top');
$response = $client->request('POST');
$response = $response->getRawBody();
Then i get an Xml document structure for $response when i print it out:
[?xml version='1.0' encoding='UTF-8'?]
[root]
[member]
[username>gh_MXH[/username]
[money]129300[/money]
[/member]
[member]
[username]sonhothiet_MXH[/username]
[money]107400[/money]
[/member]
[/root]
After that, i use Zend_Config_Xml:
$xmlReader = new Zend_Config_Xml($response);
$xml = $xmlReader->toArray();
But all i get is just only the first element of the array when i print out $xml:
Array
(
[member] => Array
(
[username] => gh_MXH
[money] => 129300
)
)
Please show me how to get all the elements so that i can do the looping like:
foreach($xml as $key => $value){
echo $value['username'] . 'has' . $value['money'];
}
And one more question, when i wrote:
$xml = new Zend_Config_Xml($response, 'root');
It appears an error saying: Section 'root' cannot be found in. Really need your help. Thank you and sorry for bad English.

Don't use Zend_Config_Xml to parse standard XML docments, it is for config files. PHP can easily do this natively:
$xml = simplexml_load_string($response);
foreach($xml->member as $member){
echo $member->username . 'has' . $member->money;
}

Related

Replace Contents of Request Object in Slim Middleware

I'm encrypting a header value and params of the request object. In the middleware.. I decrypt the values and would I like replace the values.
Tried the below. Doesnt seem to be working.
new \Slim\Http\Request($method, $uri, $headers, $cookies, $serverParams, $body)
For - $response = $next($request, $response); I tried the below
$response = $next(new \Slim\Http\Request($request->getMethod(),$request->getUri(), $arr, $request->getCookieParams(), $request->getServerParams(), $request->getBody()), $response);
Any help would be very much appreciated.
Try this to replace the header value:
$value = $response->getHeaderLine('MyHeader');
// ...
$response = $response->withHeader('MyHeader', $value);

How correctly to use the snippet() function?

My first Sphinx app almost works!
I successfully save path,title,content as attributes in index!
But I decided go to SphinxQL PDO from AP:
I found snippets() example thanks to barryhunter again but don't see how use it.
This is my working code, except snippets():
$conn = new PDO('mysql:host=ununtu;port=9306;charset=utf8', '', '');
if(isset($_GET['query']) and strlen($_GET['query']) > 1)
{
$query = $_GET['query'];
$sql= "SELECT * FROM `test1` WHERE MATCH('$query')";
foreach ($conn->query($sql) as $info) {
//snippet. don't works
$docs = array();
foreach () {
$docs[] = "'".mysql_real_escape_string(strip_tags($info['content']))."'";
}
$result = mysql_query("CALL SNIPPETS((".implode(',',$docs)."),'test1','" . mysql_real_escape_string($query) . "')",$conn);
$reply = array();
while ($row = mysql_fetch_array($result,MYSQL_ASSOC)) {
$reply[] = $row['snippet'];
}
// path, title out. works
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
print( $output . "<br><br>");
}
}
I have got such structure from Sphinx index:
Array
(
[0] => Array
(
[id] => 244
[path] => DOC7000/zdorovie1.doc
[title] => zdorovie1.doc
[content] => Stuff content
I little bit confused with array of docs.
Also I don't see advice: "So its should be MUCH more efficient, to compile the documents and call buildExcepts just once.
But even more interesting, is as you sourcing the the text from a sphinx attribute, can use the SNIPPETS() sphinx function (in setSelect()!) in the main query. SO you dont have to receive the full text, just to send back to sphinx. ie sphinx will fetch the text from attribute internally. even more efficient!
"
Tell me please how I should change code for calling snippet() once for docs array, but output path (link), title for every doc.
Well because your data comes from sphinx, you can just use the SNIPPET() function (not CALL SNIPPETS()!)
$query = $conn->quote($_GET['query']);
$sql= "SELECT *,SNIPPET(content,$query) AS `snippet` FROM `test1` WHERE MATCH($query)";
foreach ($conn->query($sql) as $info) {
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
print("$output<br>{$info['snippet']}<br><br>");
}
the highlighted text is right there in the main query, dont need to mess around with bundling the data back up to send to sphinx.
Also shows you should be escaping the raw query from user.
(the example you found does that, because the full text comes fom MySQL - not sphinx - so it has no option but to mess around sending data back and forth!)
Just for completeness, if REALLY want to use CALL SNIPPETS() would be something like
<?php
$query =$conn->quote($_GET['query']);
//make query request
$sql= "SELECT * FROM `test1` WHERE MATCH($query)";
$result = $conn->query($sql);
$rows = $result->fetchAll(PDO::FETCH_ASSOC);
//build list of docs to send
$docs = array();
foreach ($rows as $info) {
$docs[] = $conn->quote(strip_tags($info['content']));
}
//make snippet reqest
$sql = "CALL SNIPPETS((".implode(',',$docs)."),'test1',$query)";
//decode reply
$reply = array();
foreach ($conn->query($sql) as $row) {
$reply[] = $row['snippet'];
}
//output results using $rows, and cross referencing with $reply
foreach ($rows as $idx => $info) {
// path, title out. works
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
$snippet = $reply[$idx];
print("$output<br>$snippet<br><br>");
}
Shows putting the rows into an array, because need to lopp though the data TWICE. Once to 'bundle' up the docs array to send. Then again to acully display rules, when have $rows AND $reply both available.

Send file to Restful service in codeception

I would like to test restful API test for file uploading.
I try to run:
$I->sendPOST($this->endpoint, $postData, ['file' => 'example.jpg']);
and I would like it to behave the same as user sent example.jpg file in file input with name file but it doesn't seem to work this way. I'm getting:
[PHPUnit_Framework_ExceptionWrapper] An uploaded file must be an array or an instance of UploadedFile.
Is it possible to upload file using REST plugin in codeception? Documentation is very limited and it's hard to say how to do it.
I'm also testing API using Postman plugin to Google Chrome and I can upload file without a problem using this plugin.
I was struggling with the same problem recently and found out that there is another way to solve the issue without using Symfony's UploadedFile class. You only need to pass the array with file data in the same format as if it were the $_FILES array. For example, this code works perfectly well for me:
$I->sendPOST(
'/my-awesome-api',
[
'sample-field' => 'sample-value',
],
[
'myFile' => [
'name' => 'myFile.jpg',
'type' => 'image/jpeg',
'error' => UPLOAD_ERR_OK,
'size' => filesize(codecept_data_dir('myFile.jpg')),
'tmp_name' => codecept_data_dir('myFile.jpg'),
]
]
);
Hope this helps someone and prevents from inspecting the framework's source code (which I was forced to do, as the docs skip such an important detail)
After testing it seems to make it work we need to use UploadedFile object as file.
For example:
$path = codecept_data_dir();
$filename = 'example-image.jpg';
// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);
$mime = 'image/jpeg';
$uploadedFile = new \Symfony\Component\HttpFoundation\File\UploadedFile($path . $filename, $filename, $mime,
filesize($path . $filename));
$I->sendPOST($this->endpoint, $postData, ['file' => $uploadedFile]);
['file' => 'example.jpg'] format works too, but the value must be a correct path to existing file.
$path = codecept_data_dir();
$filename = 'example-image.jpg';
// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);
$I->sendPOST($this->endpoint, $postData, ['file' => $path . $filename]);
The below worked for myself,
On server:
$uploadedResume= $_FILES['resume_uploader'];
$outPut = [];
if (isset($uploadedResume) && empty($uploadedResume['error'])) {
$uploadDirectory = 'uploads/users/' . $userId . '/documents/';
if (!is_dir($uploadDirectory)) {
#mkdir($uploadDirectory, 0777, true);
}
$ext = explode('.', basename($uploadedResume['name']));
$targetPath = $uploadDirectory . md5(uniqid()) . '.' . end($ext);
if (move_uploaded_file($uploadedResume['tmp_name'], $targetPath)) {
$outPut[] = ['success' => 'success', 'uploaded_path' => $targetPath];
}
}
return json_encode($output);
Sorry for the long description code :P
On Testing side:
//resume.pdf is copied in to tests/_data directory
$I->sendPOST('/student/resume', [], ['resume_uploader' => codecept_data_dir('resume.pdf') ]);
#Yaronius's answer worked for me after I removed the following header from my test:
$I->haveHttpHeader('Content-Type', 'multipart/form-data');

Mojolicious wildcard placeholders and question mark

The wildcard placeholder (*) is said to match absolutely everything.
But I'm afraid that it doesn't...
I have a webservice with the following method:
get '/*param' => sub {
my $self = shift;
my $param = $self->stash('param');
$self->app->log->debug($param);
}
When i query my service with: http://localhost:3000/search
then the method logs "search" which is ok
but
when i query my service with: http://localhost:3000/search?page=1
then the method also logs "search" which is not ok IMO
I also tried replacing
get '/*param' => sub {
with
get '/:param' => [param => qr/.*/] => sub {
but the result is the same.
Does anybody know of a way around this?
Or should I file this as a bug?
Regards,
Lorenzo
UPDATE
for people with the same problem, I've worked around this issue like this:
get '/*path' => sub {
my $self = shift;
my $path = $self->stash('path');
my #params = $self->param;
if (scalar #params > 0) {
$path .= '?';
foreach my $param (#params) {
$path .= $param . '=' . $self->param($param) . '&';
}
$path = substr($path, 0, length($path) - 1);
}
$self->app->log->debug($path);
}
?page= its not url.
Its param.
So no any bugs here.
you have 'search' in $param.
And $page=1 in stash.
I think Korjavin is right, that's expected behavior. Looks like "page=1" as a parameter and should be in $stash->param('page'). See GET-POST-parameters in ::Lite
If it does not work, maybe renaming the "param" placeholder to something else helps? Maybe it's a name-clash.
The request parameters wouldn't be in the stash.
They're in
$self->req->params
So
my $params = $self->req->params->to_hash;
$self->app->log->debug(Dumper $params);
Should allow you to see the information you're after

How can I change the hostname in a URL using Perl?

I have some URLs like http://anytext.a.abs.com
In these, 'anytext' is the data that is dynamic. Rest of the URL will remain same in every case.
I'm using the following code:
$url = "http://anytext.a.abs.com";
my $request = new HTTP::Request 'GET', $url;
my $response = $ua->request($request);
if ($response->is_success)
{
function......;
}
Now, how can I parse a URL that has dynamic data in it?
Not sure but is this close to what you're after?:
for my $host qw(anytext someothertext andanother) {
my $url = "http://$host.a.abs.com";
my $request = new HTTP::Request 'GET', $url;
my $response = $ua->request($request);
if ($response->is_success)
{
function......;
}
}
Something like this maybe?
Otherwise, you can use the URI class to do url manipulation.
my $protocol = 'http://'
my $url_end = '.a.abs.com';
$url = $protocol . "anytext" . $url_end;
my $request = new HTTP::Request 'GET', $url;
my $response = $ua->request($request);
if ($response->is_success)
{
function......;
}
I think this is probably enough:
# The regex specifies a string preceded by two slashes and all non-dots
my ( $host_name ) = $url =~ m{//([^.]+)};
And if you want to change it:
$url =~ s|^http://\K([^.]+)|$host_name_I_want|;
Or even:
substr( $url, index( $url, $host_name ), length( $host_name ), $host_name_I_want );
This will expand the segment sufficiently to accommodate $host_name_I_want.
Well, like you would parse any other data: Use the information you have about the structure.
You have a protocol part, followed by "colon slash slash", then the host followed by optional "colon port number" and an optional path on the host.
So ... build a little parser that extracts the information you are after.
And frankly, if you are only hunting for "what exactely is 'anytext' here?", a RegEx of this form should help (untested; use as guidance):
$url =~ m/http\:\/\/(.*).a.abs.com/;
$subdomain = $1;
$do_something('with', $subdomain);
Sorry if I grossly misunderstood the problem at hand. Please explain what you mean with 'how can I parse a URL that has dynamic data in it?' in that case :)