Issue to connect to a third party website - php

I have this website [click to see]
[1]: http://www.forumjeep.ca/connect.php and as you can see, its only codes that we see. I'm trying to see the third party website but its not working. I'm able to login with the credentials, but im stuck from there. Here's the code i'm using thanks to Hanshenrik . Any help possible ?
<?php
declare(strict_types = 1);
const USERNAME = '???';
const PASSWORD = '???';
header ( "content-type: text/plain;charset=utf8" );
require_once ('hhb_.inc.php');
$hc = new hhb_curl ( '', true );
$html = $hc->exec ( 'https://app.cfe.gob.mx/Aplicaciones/CCFE/Recibos/Consulta/login.aspx' )->getStdOut ();
$domd = #DOMDocument::loadHTML ( $html );
$inputsRaw = getDOMDocumentFormInputs ( $domd, true ) ['aspnetForm'];
$inputs = array ();
foreach ( $inputsRaw as $tmp ) {
$inputs [$tmp->getAttribute ( "name" )] = $tmp->getAttribute ( "value" );
}
assert ( isset ( $inputs ['__VIEWSTATE'], $inputs ['__EVENTVALIDATION'] ) );
$inputs ['ctl00$PHContenidoPag$UCLogin2$LoginUsuario$UserName'] = USERNAME;
$inputs ['ctl00$PHContenidoPag$UCLogin2$LoginUsuario$Password'] = PASSWORD;
hhb_var_dump ( $inputs );
$html = $hc->setopt_array ( array (
CURLOPT_URL => 'https://app.cfe.gob.mx/Aplicaciones/CCFE/Recibos/Consulta/login.aspx',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query ( $inputs )
) )->exec ()->getStdOut ();
// hhb_var_dump($html) & die();
$domd = #DOMDocument::loadHTML ( $html );
$xp = new DOMXPath ( $domd );
$loginErrors = $xp->query ( '//*[(contains(#style,"color:Red") or contains(#color,"Red")) and not(contains(#style,"hidden"))]' );
foreach ( $loginErrors as $tmp ) {
echo "login error!! ";
var_dump ( $tmp->textContent );
}
if (0 === $loginErrors->length) {
echo "login success!";
}
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false): array {
// :DOMNodeList?
$forms = $domd->getElementsByTagName ( 'form' );
$parsedForms = array ();
$isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool {
$parent = $decendant;
while ( NULL !== ($parent = $parent->parentNode) ) {
if ($parent === $ele) {
return true;
}
}
return false;
};
// i can't use array_merge on DOMNodeLists :(
$merged = function () use (&$domd): array {
$ret = array ();
foreach ( $domd->getElementsByTagName ( "input" ) as $input ) {
$ret [] = $input;
}
foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) {
$ret [] = $textarea;
}
foreach ( $domd->getElementsByTagName ( "button" ) as $button ) {
$ret [] = $button;
}
return $ret;
};
$merged = $merged ();
foreach ( $forms as $form ) {
$inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array {
$ret = array ();
foreach ( $merged as $input ) {
// hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) );
if ($input->hasAttribute ( "disabled" )) {
// ignore disabled elements?
continue;
}
$name = $input->getAttribute ( "name" );
if ($name === '') {
// echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL;
continue;
}
if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) {
// echo "this input does not belong to this form.", PHP_EOL;
continue;
}
if (! array_key_exists ( $name, $ret )) {
$ret [$name] = array (
$input
);
} else {
$ret [$name] [] = $input;
}
}
return $ret;
};
$inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax.
$hasName = true;
$name = $form->getAttribute ( "id" );
if ($name === '') {
$name = $form->getAttribute ( "name" );
if ($name === '') {
$hasName = false;
}
}
if (! $hasName) {
$parsedForms [] = array (
$inputs
);
} else {
if (! array_key_exists ( $name, $parsedForms )) {
$parsedForms [$name] = array (
$inputs
);
} else {
$parsedForms [$name] [] = $tmp;
}
}
}
unset ( $form, $tmp, $hasName, $name, $i, $input );
if ($getOnlyFirstMatches) {
foreach ( $parsedForms as $key => $val ) {
$parsedForms [$key] = $val [0];
}
unset ( $key, $val );
foreach ( $parsedForms as $key1 => $val1 ) {
foreach ( $val1 as $key2 => $val2 ) {
$parsedForms [$key1] [$key2] = $val2 [0];
}
}
}
return $parsedForms;
}

The problem is that you are setting the content type header to text/plain
header ( "content-type: text/plain;charset=utf8" );
What you need to do is set it to text/html
header ( "content-type: text/html; charset=utf8" );
I would, however, suggest you re-evaluate how you notify the user of a successful login if you wish to dump HTML after, as this
login success!<!DOCTYPE html PUB...
is not good at all.
Try and keep everything you want to render inside the tags, and keep those tags inside your tags.
Good luck!

Related

Log In to Google Account through Curl

I am trying to get this script to work:
https://github.com/aaronpk/Google-Voice-PHP-API
Google's recently changed their way to log in to your account. What would be the steps to login through cURL to Google?
It will throw this now when trying to post to the form on this page (https://accounts.google.com/signin/challenge/sl/password):
Type: Exception
Message: Could not parse for GALX or gxf token. Inputs from page: array ()
without checking that code specifically, here's the code i use to login to gmail, using hhb_curl (and note: initially i pretended to be an iPhone, because it was easier to login via the mobile login page than the desktop login page, but eventually i ported it to the desktop version, but there's still some mobile-version-residue in the code. also, sometimes gmail will randomly ask you to verify your recovery email when using this method, thus the $recoveryEmailChallengeAnswer variable. it doesn't happen everytime, but google notice that something is "off" with the login, and thus asks for recovery email verification randomly. my code handles that situation transparently.):
function loginGmail(string $username, string $password, string $recoveryEmailChallengeAnswer, bool $requestHtmlVersion = true): \hhb_curl {
$hc = new hhb_curl ( '', true );
$hc->setopt_array ( array (
CURLOPT_TIMEOUT => 20, // i just have a shitty connection :(
CURLOPT_CONNECTTIMEOUT => 10
) );
if (0) {
$hc->setopt_array ( array (
CURLOPT_USERAGENT => 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1'
) );
}
$html = $hc->exec ( 'https://gmail.com' )->getStdOut ();
$domd = #DOMDocument::loadHTML ( $html );
$inputs = getDOMDocumentFormInputs ( $domd, true, false ) ['gaia_loginform'];
// hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ) & die();
$loginUrl = $domd->getElementById ( "gaia_loginform" )->getAttribute ( "action" );
$inputs ['Email'] = $username;
$html = $hc->setopt_array ( array (
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
CURLOPT_URL => $loginUrl
) )->exec ()->getStdOut ();
$domd = #DOMDocument::loadHTML ( $html );
$inputs = getDOMDocumentFormInputs ( $domd, true, false ) ['gaia_loginform'];
// hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs );
$loginUrl = $domd->getElementById ( "gaia_loginform" )->getAttribute ( "action" );
$inputs ['Passwd'] = $password;
try {
$starttime = microtime ( true );
$html = $hc->setopt_array ( array (
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
CURLOPT_URL => $loginUrl
) )->exec ()->getStdOut ();
} finally{
// hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs, (microtime ( true ) - $starttime) ) & die ();
}
$domd = #DOMDocument::loadHTML ( $html );
$xp = new DOMXPath ( $domd );
$loginErrors = $xp->query ( '//span[contains(#class,"error-msg")]' );
$loginErrorText = '';
foreach ( $loginErrors as $tmp ) {
$tmp = trim ( $tmp->textContent );
if (strlen ( $tmp )) {
$loginErrorText .= ' - ' . $tmp;
}
}
$authChallenge = $domd->getElementById ( "challengePickerList" );
if (NULL !== $authChallenge) {
// gotdammit... got an auth challenge page, asking you to choose a challenge
$loginErrorText .= ' - got an auth challenge page, asking you to choose a challenge: ' . trim ( $authChallenge->textContent );
// TODO: automatically select "provide recovery email" here instead of throwing a login error exception.
} else {
if (false !== stripos ( $html, 'Enter recovery email' ) && NULL !== ($authChallenge = $domd->getElementById ( "challenge" ))) {
// got an auth challenge for providing recovery email..
// luckily, we can automatically recover from this.
$inputs = getDOMDocumentFormInputs ( $domd, true, false ) ['challenge'];
assert ( array_key_exists ( 'email', $inputs ) );
$inputs ['email'] = $recoveryEmailChallengeAnswer;
$url = $authChallenge->getAttribute ( "action" );
if (! parse_url ( $url, PHP_URL_HOST )) {
$url = 'https://' . parse_url ( $hc->getinfo ( CURLINFO_EFFECTIVE_URL ), PHP_URL_HOST ) . $url;
}
$html = $hc->setopt_array ( array (
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
CURLOPT_URL => $url
) )->exec ()->getStdOut ();
$domd = #DOMDocument::loadHTML ( $html );
$xp = new DOMXPath ( $domd );
// TODO: detect incorrect recovery email supplied error here.
}
}
unset ( $authChallenge );
if (! empty ( $loginErrorText )) {
throw new \RuntimeException ( 'errors loggin in: ' . $loginErrorText );
} else {
// logged in! :D
}
if ($requestHtmlVersion) {
// now we need to enable HTML view, it's a <form> POST request, but we can't use getDOMDocumentFormInputs (bug?)
$found = false;
foreach ( $domd->getElementsByTagName ( "form" ) as $form ) {
if (false === stripos ( $form->textContent, "Gmail's basic HTML view, which doesn't require JavaScript" ) && $xp->query ( "./input[#value='Load basic HTML']", $form )->length === 0) {
continue;
}
$found = true;
$url = $form->getAttribute ( "action" );
if (! parse_url ( $url, PHP_URL_HOST )) {
$url = $hc->getinfo ( CURLINFO_EFFECTIVE_URL ) . $url;
}
// hhb_var_dump ( $url ) & die ();
$inputs = [ ];
foreach ( $form->getElementsByTagName ( "input" ) as $input ) {
$name = $input->getAttribute ( "name" );
if (empty ( $name )) {
continue;
}
$inputs [$name] = $input->getAttribute ( "value" );
}
// hhb_var_dump ( $inputs ) & die ();
break;
}
if (! $found) {
$str = 'failed to find HTML version request form!';
// hhb_var_dump ( $str, $hc->getStdErr (), $hc->getStdOut (), $inputs ); // & die ();
throw new \RuntimeException ( $str );
}
$html = $hc->setopt_array ( array (
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query ( $inputs ),
CURLOPT_URL => $url
) )->exec ()->getStdOut ();
}
hhb_var_dump ( $hc->getStdErr (), $hc->getStdOut (), $inputs ); // & die ();
return $hc;
}
function rightTrim($str, $needle, $caseSensitive = true) {
$strPosFunction = $caseSensitive ? "strpos" : "stripos";
if ($strPosFunction ( $str, $needle, strlen ( $str ) - strlen ( $needle ) ) !== false) {
$str = substr ( $str, 0, - strlen ( $needle ) );
}
return $str;
}
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false, bool $getElements = true): array {
// :DOMNodeList?
if (! $getOnlyFirstMatches && ! $getElements) {
throw new \InvalidArgumentException ( '!$getElements is currently only implemented for $getOnlyFirstMatches (cus im lazy and nobody has written the code yet)' );
}
$forms = $domd->getElementsByTagName ( 'form' );
$parsedForms = array ();
$isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool {
$parent = $decendant;
while ( NULL !== ($parent = $parent->parentNode) ) {
if ($parent === $ele) {
return true;
}
}
return false;
};
// i can't use array_merge on DOMNodeLists :(
$merged = function () use (&$domd): array {
$ret = array ();
foreach ( $domd->getElementsByTagName ( "input" ) as $input ) {
$ret [] = $input;
}
foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) {
$ret [] = $textarea;
}
foreach ( $domd->getElementsByTagName ( "button" ) as $button ) {
$ret [] = $button;
}
return $ret;
};
$merged = $merged ();
foreach ( $forms as $form ) {
$inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array {
$ret = array ();
foreach ( $merged as $input ) {
// hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) );
if ($input->hasAttribute ( "disabled" )) {
// ignore disabled elements?
continue;
}
$name = $input->getAttribute ( "name" );
if ($name === '') {
// echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL;
continue;
}
if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) {
// echo "this input does not belong to this form.", PHP_EOL;
continue;
}
if (! array_key_exists ( $name, $ret )) {
$ret [$name] = array (
$input
);
} else {
$ret [$name] [] = $input;
}
}
return $ret;
};
$inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax.
$hasName = true;
$name = $form->getAttribute ( "id" );
if ($name === '') {
$name = $form->getAttribute ( "name" );
if ($name === '') {
$hasName = false;
}
}
if (! $hasName) {
$parsedForms [] = array (
$inputs
);
} else {
if (! array_key_exists ( $name, $parsedForms )) {
$parsedForms [$name] = array (
$inputs
);
} else {
$parsedForms [$name] [] = $tmp;
}
}
}
unset ( $form, $tmp, $hasName, $name, $i, $input );
if ($getOnlyFirstMatches) {
foreach ( $parsedForms as $key => $val ) {
$parsedForms [$key] = $val [0];
}
unset ( $key, $val );
foreach ( $parsedForms as $key1 => $val1 ) {
foreach ( $val1 as $key2 => $val2 ) {
$parsedForms [$key1] [$key2] = $val2 [0];
}
}
}
if ($getElements) {
return $parsedForms;
}
$ret = array ();
foreach ( $parsedForms as $formName => $arr ) {
$ret [$formName] = array ();
foreach ( $arr as $ele ) {
$ret [$formName] [$ele->getAttribute ( "name" )] = $ele->getAttribute ( "value" );
}
}
return $ret;
}

PHP Login using CURL not working

I want to login website bukalapak.com, but I have problem I just got blank page after execute this php, here my code :
var_dump(login_bukalapak());
function login_bukalapak(){
$data_login = array(
'user_session[username]' => 'myusername',
'user_session[password]' => 'mypassword'
);
$url = "https://www.bukalapak.com/user_sessions";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$cookie = 'cookies.txt';
$timeout = 30;
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout );
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS,$data_login);
$result = curl_exec($ch);
/*$url = "https://www.bukalapak.com/products/new?from=dropdown";
curl_setopt ($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);*/
curl_close($ch);
return $result;
}
I confuse I just have return blank, how the correct answer to make it run well and return successfully login ?
Thanks.
you're doing many things wrong here.
1: their login system use application/x-www-form-urlencoded encoding for the login POST request body, but your code try to login using multipart/form-data encoding.
2: their login system requires you to have a pre-existing cookie session before logging in, but your code does not obtain a cookie session prior to sending the login request.
3: they use a CSRF token scheme to protect their login, where you need to fetch the csrf token from the page, and add it to your login post fields before sending the login request, called authenticity_token (it's in their html as <input type="hidden" name="authenticity_token" value="<TOKEN>" />), your code makes no attempt to fetch and extract this token prior to logging in.
4: there is a bunch of login parameters you're missing, namely utf8, user_session[remember_me], comeback, button, and as i said previously, authenticity_token - not all of these parameters may be required, or perhaps all of them are, but at least some of them (authenticity_token) is 100% sure to be required, just add them all, unless you wanna waste time figuring out which parameters are required and which is not, it's probably not worth the effort.
5: your code lacks error checking, curl_setopt returns bool(false) if there was a problem setting your settings, and curl_exec returns bool(false) if there was a problem during the transfer
with that in mind, here is a sample implementation in hhb_curl that i think would work with a real username/password:
<?php
require_once ('hhb_.inc.php');
$hc = login_bukalapak ( "foo#bar.com", "password" );
var_dump ( $hc->exec ( 'https://www.bukalapak.com/' )->getStdOut () );
function login_bukalapak(string $username, string $password): \hhb_curl {
$hc = new hhb_curl ( '', true );
$html = $hc->exec ( 'https://www.bukalapak.com/' )->getStdOut ();
$domd = #DOMDocument::loadHTML ( $html );
$data_login = getDOMDocumentFormInputs ( $domd, true, false ) ['new_user_session'];
// var_dump ( $data_login ) & die ();
assert ( isset ( $data_login ['user_session[username]'], $data_login ['user_session[password]'] ), 'username/password field not found in login form!' );
$data_login ['user_session[username]'] = $username;
$data_login ['user_session[password]'] = $password;
$url = "https://www.bukalapak.com/user_sessions";
$html = $hc->setopt_array ( array (
CURLOPT_URL => 'https://www.bukalapak.com/user_sessions',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query ( $data_login )
) )->exec ()->getStdOut ();
//var_dump ( $html );
$domd = #DOMDocument::loadHTML ( $html );
$xp = new DOMXPath ( $domd );
$loginErrorEles = $xp->query ( '//*[contains(#class,"__error") and not(contains(#class,"hidden"))]' );
$loginErrors = '';
foreach ( $loginErrorEles as $loginError ) {
if (empty ( $loginError->textContent )) {
continue;
}
$loginErrors .= trim ( $loginError->textContent );
}
if (! empty ( $loginErrors )) {
throw new RuntimeException ( 'failed to log in: '.$loginErrors);
}
// assuming logged in successfully
// note that its highly unreliable, they sometimes say "wrong username/password", and someitmes not, seemingly randomly.
return $hc;
}
function getDOMDocumentFormInputs(\DOMDocument $domd, bool $getOnlyFirstMatches = false, bool $getElements = true): array {
// :DOMNodeList?
if (! $getOnlyFirstMatches && ! $getElements) {
throw new \InvalidArgumentException ( '!$getElements is currently only implemented for $getOnlyFirstMatches (cus im lazy and nobody has written the code yet)' );
}
$forms = $domd->getElementsByTagName ( 'form' );
$parsedForms = array ();
$isDescendantOf = function (\DOMNode $decendant, \DOMNode $ele): bool {
$parent = $decendant;
while ( NULL !== ($parent = $parent->parentNode) ) {
if ($parent === $ele) {
return true;
}
}
return false;
};
// i can't use array_merge on DOMNodeLists :(
$merged = function () use (&$domd): array {
$ret = array ();
foreach ( $domd->getElementsByTagName ( "input" ) as $input ) {
$ret [] = $input;
}
foreach ( $domd->getElementsByTagName ( "textarea" ) as $textarea ) {
$ret [] = $textarea;
}
foreach ( $domd->getElementsByTagName ( "button" ) as $button ) {
$ret [] = $button;
}
return $ret;
};
$merged = $merged ();
foreach ( $forms as $form ) {
$inputs = function () use (&$domd, &$form, &$isDescendantOf, &$merged): array {
$ret = array ();
foreach ( $merged as $input ) {
// hhb_var_dump ( $input->getAttribute ( "name" ), $input->getAttribute ( "id" ) );
if ($input->hasAttribute ( "disabled" )) {
// ignore disabled elements?
continue;
}
$name = $input->getAttribute ( "name" );
if ($name === '') {
// echo "inputs with no name are ignored when submitted by mainstream browsers (presumably because of specs)... follow suite?", PHP_EOL;
continue;
}
if (! $isDescendantOf ( $input, $form ) && $form->getAttribute ( "id" ) !== '' && $input->getAttribute ( "form" ) !== $form->getAttribute ( "id" )) {
// echo "this input does not belong to this form.", PHP_EOL;
continue;
}
if (! array_key_exists ( $name, $ret )) {
$ret [$name] = array (
$input
);
} else {
$ret [$name] [] = $input;
}
}
return $ret;
};
$inputs = $inputs (); // sorry about that, Eclipse gets unstable on IIFE syntax.
$hasName = true;
$name = $form->getAttribute ( "id" );
if ($name === '') {
$name = $form->getAttribute ( "name" );
if ($name === '') {
$hasName = false;
}
}
if (! $hasName) {
$parsedForms [] = array (
$inputs
);
} else {
if (! array_key_exists ( $name, $parsedForms )) {
$parsedForms [$name] = array (
$inputs
);
} else {
$parsedForms [$name] [] = $tmp;
}
}
}
unset ( $form, $tmp, $hasName, $name, $i, $input );
if ($getOnlyFirstMatches) {
foreach ( $parsedForms as $key => $val ) {
$parsedForms [$key] = $val [0];
}
unset ( $key, $val );
foreach ( $parsedForms as $key1 => $val1 ) {
foreach ( $val1 as $key2 => $val2 ) {
$parsedForms [$key1] [$key2] = $val2 [0];
}
}
}
if ($getElements) {
return $parsedForms;
}
$ret = array ();
foreach ( $parsedForms as $formName => $arr ) {
$ret [$formName] = array ();
foreach ( $arr as $ele ) {
$ret [$formName] [$ele->getAttribute ( "name" )] = $ele->getAttribute ( "value" );
}
}
return $ret;
}

Check the empty content in array

I have got an array that contains different kinds of element.
The array can have different dimension in different fields.
I want to write a function to check if there are some variables in the array are empty.
The sample array is like the following.
$array = new array(
'a'=>'A',
'b' => new array('B',''),
'c'=> ''
);
Here is a function that will go through all the arrays:
$isEmpty = checkArray( $arr );
if ( $isEmpty ) {
echo "there are empties!";
} else {
echo "no empties!";
}
function checkArray( $array ) {
foreach ( $array as $key => $value ) {
if ( is_array( $value ) ) {
if ( checkArray( $value ) ) return true;
} else {
if ( empty( $value ) ) return true;
}
}
return false;
}
How about this:
foreach ($array as $key => $value) {
if (empty($value)) {
do_stuff();
}
}

parsing random stdClass

I seem to be a little lost on what to so about this, im trying to parse out some info but the stdClass is going to always be changing, so im not too sure on what to do about it and could use come guidance.
//Query
$query = new EntityFieldQuery;
$result = $query
->entityCondition('entity_type', 'taxonomy_term')
->propertyCondition('name', 'GOOG')
->propertyCondition('vid', '3')
->execute();
//This is the output
Array
(
[taxonomy_term] => Array
(
[1868] => stdClass Object
(
[tid] => 1868
)
)
)
Now I can get to the tid by using
$result['taxonomy_term']['1868']->tid
but as mentioned before the the stdClass will be always changing.
You can use recurssive array search like this:
function array_searchRecursive( $needle, $haystack, $strict=false, $path=array() )
{
if( !is_array($haystack) ) {
return false;
}
foreach( $haystack as $key => $val ) {
if( is_array($val) && $subPath = array_searchRecursive($needle, $val, $strict, $path) ) {
$path = array_merge($path, array($key), $subPath);
return $path;
} elseif( (!$strict && $val == $needle) || ($strict && $val === $needle) ) {
$path[] = $key;
return $path;
}
}
return false;
}
Usage:
$arr = (array) $yourObject;
$keypath = array_searchRecursive('tid', $arr);
Example:
$class = new stdClass;
$class->foo = 'foo';
$class->bar = 'bar';
$arr = (array) $class;
$keypath = array_searchRecursive('foo', $arr);
print_r($keypath);
Results:
Array
(
[0] => foo
)
So now to get actual value:
echo $keypath[0]; // foo

PHP: rename multidimensional array's keys

I have a multidimensional array with strings as keys. I want to perform a function (to manipulate the strings) on those keys and then write to a new array (i.e. leave the original array unchanged).
Example:
$oldArr = array(
"foo_old" => array("moo_old" => 1234, "woo_old" => 5678);
"bar_old" => array("car_old" => 4321, "tar_old" => 8765);
);
Becomes:
$newArr = array(
"foo_new" => array("moo_new" => 1234, "woo_new" => 5678);
"bar_new" => array("car_new" => 4321, "tar_new" => 8765);
);
This is just an example, the actual array has more levels/dimensions. Oh and my function doesn't replace "_old" with "_new", again, just an example.
I hope I made some sense, thanks in advance!
Edit: I added a function for printing out the changed array. You may include the code on a website and it will show the result. New edited code:
// array initialisation
oldArr = array();
$subArr1 = array();
$subArr2 = array();
$subArr1["moo_old"]=1234;
$subArr1["woo_old"]=5678;
$subArr2["car_old"]=4321;
$subArr2["tar_old"]=8765;
$oldArr["foo_old"]=$subArr1;
$oldArr["bar_old"]=$subArr2;
$oldArr; // make a copy of the array
// function which replaces recursivly the keys of the array
function renameArrayKeys( $oldArr ) {
$copyArr = $oldArr;
if( is_array( $oldArr) && count( $oldArr ) ) {
foreach ( $oldArr as $k => $v ) {
unset($copyArr[$k]); // removes old entries
$newKey = str_replace( '_old', '_new', $k );
if( is_array( $v ) ) {
$copyArr[ $newKey ] = renameArrayKeys( $v );
}
else {
$copyArr[ $newKey ] = $v;
}
}
return $copyArr;
}
}
// prints out the keys and values of the changed array
function printout($arr ){
foreach ($arr as $k => $val ) {
echo $k."=>".$val." | ";
if( is_array( $val ) ) {
printout( $val );
}
}
}
// calls the above functions
$changedArr = renameArrayKeys($oldArr);
printout($changedArr);
I'm probably slightly late, but recursion is the way forward with this!
$replace_from = "_old"; //can also be array i.e. array("foo_old", "bar_old")
$replace_to = "_new"; //can also be an array i.e. array("foo_new", "bar_new")
$oldArr = array(
"foo_old" => array("moo_old" => 1234, "woo_old" => 5678),
"bar_old" => array("car_old" => 4321, "tar_old" => 8765),
);
function replace($arr){
global $replace_from, $replace_to;
$newArr = array();
foreach($arr as $key => $value){
$newArr[str_replace($replace_from,$replace_to,$key)] = (is_array($value)) ? replace($value) : $value;
}
return $newArr;
}
print_r (replace($oldArr));
Something like this:
function renameKeys( $arr )
{
if( is_array( $arr ) && count( $arr ) ) {
foreach ( $arr as $k => $v ) {
$nk = str_replace( '_old', '_new', $k );
if( is_array( $v ) ) {
$v = renameKeys( $v );
}
$arr[ $nk ] = $v;
unset( $arr[$k] );
}
}
return $arr;
}
$oldArr = array(
"foo_old" => array("moo_old" => 1234, "woo_old" => 5678) ,
"bar_old" => array("car_old" => 4321, "tar_old" => 8765)
);
$nArr = renameKeys( $oldArr );
print_r( $nArr );
Closure version. This doesn't mess up the namespace.
<?php
$from = '_old';
$to = '_new';
$old_arr = array(
'foo_old' => array('moo_old' => 1234, 'woo_old' => 5678),
'bar_old' => array('car_old' => 4321, 'tar_old' => 8765),
);
$func = function ($arr) use (&$func, $from, $to) {
$new_arr = array();
foreach($arr as $k => $v){
$new_arr[str_replace($from, $to, $k)] = is_array($v) ? $func($v) : $v;
}
return $new_arr;
};
print_r($func($old_arr));

Categories