Better way to check for URL in PHP - php

Is there a better way or elegance to do this? I've been using this code to check the similar url in database base on the pattern provide.
$menu_selected = '';
$uri_array = explode('/','commodity/statement/flour/factory/');
$menus = array(
'commodity/search/flour/factory/index',
'commodity/statement/sugar/branch/index'
);
$pattern_parts = explode('/', '=/*/=/=/*');
foreach ($menus as $menu) {
$url_parts = explode('/',$menu);
if( count($pattern_parts) == count($url_parts) ){
#[i] Trim down for wildcard pattern
foreach($pattern_parts as $i => $part ){
if( $part == '*' ) {
unset($pattern_parts[$i]);
unset($url_parts[$i]);
unset($uri_array[$i]);
}
}
#[i] Join array and compare
if( join('/', $uri_array) == join('/', $url_parts) ) {
// Found and return the selected
$menu_selected = $menu;
break;
}
}
}

Related

How to get the values only if all the keys have matched?

I want to make a method that returns keys and values. But only if the keys include the following string "_1" and "__last".
If only one matches then exit the function, only if the two string are included in the key, return the key with the value for a weather.
$infoList = array("_key_1"=>array("time"=>9, "day"=>"Tuesday", "weather"=>"sunny",
"humidity"=>"80%"),
"_key_2"=>array("time"=>5, "day"=>"Tuesday", "weather"=>"cloudy"),
"_key__last"=>array("time"=>3, "day"=>"Sunday", "weather"=>"rainy"))
public function getData() {
$list = array();
foreach($infoList as $key){
if(preg_match('/(_key)_(_1)/', $key) && preg_match('/(_key)_(__last)/', $key) == TRUE){
$list[$key] = $list[$key]["weather"]
}
}
return $list
}
You are making your life so much more difficult that it need be, use str_contains() its easier than building complex REGEX's and getting very confused by the look of it :)
I also fixed a number of other mistakes, such as the foreach that was not going to work, so check all the code.
It is also better to pass data to a function/method otherwise you get into scoping issues!
$infoList = array("_key_1"=>array("time"=>9, "day"=>"Tuesday", "weather"=>"sunny", "humidity"=>"80%"),
"_key_2"=>array("time"=>5, "day"=>"Tuesday", "weather"=>"cloudy"),
"_key__last"=>array("time"=>3, "day"=>"Sunday", "weather"=>"rainy"));
function getData(Array $infoList) {
$list = [];
$found = 0;
foreach($infoList as $key => $val) {
if( str_contains($key, '_1') || str_contains($key, '__last') ) {
$list[$key] = $val["weather"];
$found++;
}
}
if ( $found >= 2 ) {
return $list;
} else {
return false;
}
}
$res = getData($infoList);
if ( $res !== false ){
print_r($res);
} else {
echo 'Not Found';
}
RESULTS
Array
(
[_key_1] => sunny
[_key__last] => rainy
)
If you want to stick with RegEx, you can use positive lookaheads, the same way you check for passwords characters :
<?php
$pattern = '/^(?=.*_1)(?=.*_last).*$/';
$shouldMatch = [
'_1_last',
'foo_1bar_lasthello',
'_last_1',
'foo_lastbar_1hello'
];
echo 'next ones should match : ' . PHP_EOL;
foreach ($shouldMatch as $item)
{
if (preg_match($pattern, $item))
echo $item . PHP_EOL;
}
$shouldNOTMatch = [
'_2_first',
'bar_lasthello',
'foo_las_1hello'
];
echo 'next ones should NOT match : ' . PHP_EOL;
foreach ($shouldNOTMatch as $item)
{
// v------------ check
if (!preg_match($pattern, $item))
echo $item . PHP_EOL;
}
Output :
next ones should match :
_1_last
foo_1bar_lasthello
_last_1
foo_lastbar_1hello
next ones should NOT match :
_2_first
bar_lasthello
foo_las_1hello

If elseif condition inside foreach with array

I'm using a if elseif condition inside the foreach loop. Inside both if and elseif two different functions are calling and retrieving value to same array $nice[]. If I run the following code, only the if condition is working.
$youtube = array(
'https://www.youtube.com/watch?v=nCwRJUg3tcQ1&list=PLv5BUbwWA5RYaM6E-QiE8WxoKwyBnozV2&index=4',
'http://vimeo.com/channels/vimeogirls/87973054123',
'http://www.youtube.com/watch?v=nCwRJUg3tcQ2&feature=relate',
'http://youtube.com/v/nCwRJUg3tcQ3?feature=youtube_gdata_player');
$nice = array();
foreach ($youtube as $url) {
if(preg_grep("/youtu/i", $youtube)){
$nice[] = getYoutubeId($url);
}elseif(preg_grep("/vimeo/i", $youtube)){
$nice[] = getVimeoId($url);
}
}
print_r($nice);
function getVimeoId($url)
{
if (preg_match('#(?:https?://)?(?:www.)?(?:player.)?vimeo.com/(?:[a-z]*/)*([0-9]{6,11})[?]?.*#', $url, $m)) {
return 'v_'.$m[1];
}
return false;
}
function getYoutubeId($url)
{
$parts = parse_url($url);
if (isset($parts['host'])) {
$host = $parts['host'];
if (false === strpos($host, 'youtube') &&
false === strpos($host, 'youtu.be')
)
{
return false;
}
}
if (isset($parts['query'])) {
parse_str($parts['query'], $qs);
if (isset($qs['v'])) {
return 'y_'.$qs['v'];
}
else if (isset($qs['vi'])) {
return 'y_'.$qs['vi'];
}
}
if (isset($parts['path'])) {
$path = explode('/', trim($parts['path'], '/'));
return 'y_'.$path[count($path) - 1];
}
return false;
}
The current output is:
Array (
[0] => y_nCwRJUg3tcQ1
[1] =>
[2] => y_nCwRJUg3tcQ2
[3] => y_nCwRJUg3tcQ3
)
There is no value in [1] position.
First-off, your if() Clause is checking on the main array$youtube instead of the value: $url.Perhaps, the snippet below helps:
$youtube = array(
'https://www.youtube.com/watch?v=nCwRJUg3tcQ1&list=PLv5BUbwWA5RYaM6E-QiE8WxoKwyBnozV2&index=4',
'http://vimeo.com/channels/vimeogirls/87973054123',
'http://www.youtube.com/watch?v=nCwRJUg3tcQ2&feature=relate',
'http://youtube.com/v/nCwRJUg3tcQ3?feature=youtube_gdata_player');
$nice = array();
foreach ($youtube as $url) {
if(preg_match("#youtu#i", $url)){
$nice[] = getYoutubeId($url);
}elseif(preg_match("#vimeo#i", $url)){
$nice[] = getVimeoId($url);
}
}

In CodeIgniter how can i pass an array type argument to a controller from url

//let my controller be C and method be:
function X($array){}
//And my url to call it is:
localhost/mysite/C/X/array
Well i tried it but it returns 400-Bad Request response.
Does anyone know how to do it? Quick response will help me a lot//Thanx
localhost/mysite/C/X/?array=1&&?array=2....
$array = $this->input->get('array');
or
localhost/mysite/C/X/1,2,3,4,5
$array = explode(',' $this->uri->segment(n));
// in app/config/config.php
$config['permitted_uri_chars'] = 'a-z 0-9~%.:,_-';
My variant for array in url (/tours/novogodniye-turi/visa=yes;duration=small;transport=4,7,6,2/)
if ( ! function_exists('filter_parse_segment'))
{
function filter_parse_segment($segment, $merge_to_get = FALSE)
{
if(empty($segment))
{
return FALSE;
}
$parameters = explode(";", (string)$segment);
if(empty($parameters))
{
return FALSE;
}
$parameters_array = array();
foreach($parameters as $parameter)
{
if(empty($parameter))
{
continue;
}
$parameter = explode("=", $parameter);
if( ! isset($parameter[0], $parameter[1]) or empty($parameter[0]))
{
continue;
}
if(strpos($parameter[1], ','))
{
$parameter[1] = explode(",", $parameter[1]);
}
$parameters_array[$parameter[0]] = $parameter[1];
}
if($merge_to_get === TRUE)
{
$_GET = array_merge($_GET, $parameters_array);
}
return $parameters_array;
}
}
// --------------------------------------------------------------------
if ( ! function_exists('filter_collect_segment'))
{
function filter_collect_segment($array, $suffix = '', $remove = array())
{
if(empty($array) || ! is_array($array))
{
return '';
}
$segment_str = '';
foreach ($array as $key => $value)
{
if(empty($key) || in_array($key, (array)$remove))
{
continue;
}
if( ! $segment_str == '')
{
$segment_str = $segment_str.';';
}
if( ! is_array($value))
{
$segment_str = $segment_str.$key.'='.$value;
continue;
}
if(empty($value))
{
continue;
}
$parsed_value = '';
foreach ($value as $item)
{
if( ! $parsed_value == '')
{
$parsed_value = $parsed_value.',';
}
if(is_array($item) || empty($item))
{
continue;
}
$parsed_value = $parsed_value.$item;
}
$segment_str = $segment_str.$key.'='.$parsed_value;
}
if($segment_str != '')
{
$segment_str = $segment_str.$suffix;
}
return $segment_str;
}
}
// --------------------------------------------------------------------
if ( ! function_exists('filter_key'))
{
function filter_key($filter_array, $key, $value = NULL)
{
if( ! isset($filter_array[$key]))
{
return;
}
if($value == NULL)
{
return $filter_array[$key];
}
if( ! is_array($filter_array[$key]) && $filter_array[$key] == (string)$value)
{
return $value;
}
if(is_array($filter_array[$key]) && in_array($value, $filter_array[$key]))
{
return $value;
}
return FALSE;
}
}
If you want the solution in the pretty nice URL then you have to loop the array first and then concatenate the elements with some - dash or + plus signs like this;
$array = array(1,2,3,4);
$string = "";
foreach($array as $value){
$string .= $value."-";
}
$string = rtrim($string, "-");
redirect(base_url()."get_products?param=".$string);
And on the next page just get the param and use explode() function with - dash sign to create the array again.
try your url like this
if value you have to pass is
[1,2,3,2]
then
localhost/mysite/index.php/C/X/1,2,3,2
In a simple way you can make the array a string with some special character in between the values of the array.
Then in the landing page you can split the string with the special character and get the array again.
If the values are [1,2,3,4], then make it using a loop "1,2,3,4".
Then pass the string.
In teh landing page split the string with "," and you will again get the array.
Hope it helps you.
Thanks
Why don't you use uri segments for array? You can count uri segments and could use them. Even u could check how many arrays already there.
url.com/1/2/3
http://ellislab.com/codeigniter/user-guide/libraries/uri.html
Note: uri segment doesnt work on main controller index function, you have to define another function than index for example: I don't know what it happens but i think because of htaccess file I'm using do remove index.php.
url.com/uri_segment_controller/go/1/2/3

turning this trainwreck of a function into a recursive one

I've been trying to build this recursive function for the better part of a day now, but I just can't seem to get it to work the way I want.
First, I have a property which holds some data that the function have to access:
$this->data
And then I have this string which the intention is to turn into a relative path:
$path = 'path.to.%id%-%folder%.containing.%info%';
The part of the string that are like this: %value% will load some dynamic values found in the $this->data property (like so: $this->data['id']; or $this->data['folder'];
and to make things really interesting, the property can reference itself again like so: $this->data['folder'] = 'foldername.%subfolder%'; and also have two %values% separated by a - that would have to be left alone.
So to the problem, I've been trying to make a recursive function that will load the dynamic values from the data property, and then again if the new value contains another %value% and so on until no more %value%'s are loaded.
So far, this is what I've been able to come up with:
public function recursiveFolder( $folder, $pathArr = null )
{
$newPathArr = explode( '.', $folder );
if ( count ( $newPathArr ) !== 1 )
{
foreach( $newPathArr as $id => $folder )
{
$value = $this->recursiveFolder( $folder, $newPathArr );
$resultArr = explode( '.', $value );
if ( count ( $resultArr ) !== 1 )
{
foreach ( $resultArr as $nid => $result )
{
$nvalue = $this->recursiveFolder( $result, $newPathArr );
$resultArr[$nid] = $nvalue;
}
}
$resultArr = implode( '.',$resultArr );
$newPathArr[$id] = $resultArr;
}
}
else
{
$pattern = '/%(.*?)%/si';
preg_match_all( $pattern, $folder, $matches );
if ( empty( $matches[0] ) )
{
return $folder;
}
foreach ( $matches[1] as $mid => $match )
{
if ( isset( $this->data[$match] ) && $this->data[$match] != '' )
{
$folder = str_replace( $matches[0][$mid], $this->data[$match], $folder );
return $folder;
}
}
}
return $newPathArr;
}
Unfortunately it is not a recursive function at all as it grinds to a halt when it has multiple layers of %values%, but works with two layers -barely-. (I just coded it so that it would work at a bare minimalistic level this point).
Here's how it should work:
It should turn:
'files.%folder%.blog-%type%.and.%time%'
into:
'files.foldername.blog-post.and.2013.feb-12th.09'
based on this:
$data['folder'] = 'foldername';
$data['type'] = 'post';
$data['time'] = '%year%.%month%-%day%';
$data['year'] = 2013;
$data['month'] = 'feb';
$data['day'] = '12th.%hour%';
$data['hour'] = '09';
Hope you can help!
Jay
I don't see the need for this too be solved recursively:
<?php
function putData($str, $data)
{
// Repeat the replacing process until no more matches are found:
while (preg_match("/%(.*?)%/si", $str, $matches))
{
// Use $matches to make your replaces
}
return $str;
}
?>

Retrieve the country code in PHP

I'm a little lost with that.
How can I retrieve the ISO country code of the visitors at one php page?
Thanks advance
You can either do this by Geolocation of the IP or by inspecting the right headers.
Usually you want the latter, since it tells you which languages the browser/system uses. You will only want to use geolocation when you want to know the physical location.
The header is stored in $_SERVER['HTTP_ACCEPT_LANGUAGE']. It contains comma-separated entries, e.g.: en-GB,en;q=0.8,en-US;q=0.6,nl;q=0.4 (my own)
The HTTP Accept Language parameters seperates it's languages by a comma, it's properties by a semicolon. The q-value is from 0 to 1, with 1 being the highest/most preferred. Here is some naive and untested code to parse it:
$langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$preffered = "";
$prefvalue = 0;
foreach($langs as $lang){
$info = explode(';', $lang);
$val = (isset($lang[1])?$lang[1];1);
if($prefvalue < $val){
$preferred = $lang[0];
$prefvalue = $val;
}
}
Much simpler is it if you want to test if a specific language is accepted, e.g. Spanish (es):
if(strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'], "es") !== false){
// Spanish is supported
}
I think you could use this php script which uses an ip and prints out a country code
Example
http://api.hostip.info/country.php?ip=4.2.2.2
Gives US
Check out
http://www.hostip.info/use.html
for more info.
A library i use myself and can recommend, is MaxMind GeoLite Country. To get the country code, you need only to copy 2 files to your server, the php code geoip.inc and the binary data GeoIP.dat.
Using the library is also very straightforward:
function ipToCountry()
{
include_once('geoip/geoip.inc');
$gi = geoip_open(__DIR__ . '/geoip/GeoIP.dat', GEOIP_STANDARD);
$result = geoip_country_code_by_addr($gi, $_SERVER['REMOTE_ADDR']);
geoip_close($gi);
return $result;
}
This will use GeoIp and fall back to accept_lang
class Ip2Country
{
function get( $target )
{
$country = false;
if( function_exists( 'geoip_record_by_name' ) )
$country = $this->getFromIp( $target );
if( !$country && isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) )
$country = $this->getFromLang( $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
return $country;
}
function getFromIp( $target )
{
$dat = #geoip_record_by_name( $target );
return ( isset( $dat['country_code'] ) ) ? mb_strtolower( $dat['country_code'] ) : false;
}
function getFromLang( $str )
{
$info = array();
$langs = explode( ',', $str );
foreach( $langs as $lang )
{
$i = explode( ';', $lang );
$j = array();
if( !isset( $i[0] ) ) continue;
$j['code'] = $i[0];
if( strstr( $j['code'], '-' ) )
{
$parts = explode( '-', $j['code'] );
$j['lang'] = $parts[0];
$j['country'] = mb_strtolower( $parts[1] );
}
$info[] = $j;
}
return ( isset( $info[0]['country'] ) ) ? $info[0]['country'] : false;
}
}
$x = new Ip2Country();
var_dump( $x->get( 'canada.ca' ) );

Categories