Get last part of string with multiple preg_match - php

Spotify has two ways to use url's/identifiers. I want to get the last part of the strings below (the ID)
example url's:
a. https://play.spotify.com/artist/6mdiAmATAx73kdxrNrnlao
b. spotify:artist:6mdiAmATAx73kdxrNrnlao
Can't get the code below to work, so I can add more options to it later as well. I tried basename first, but obviously that doesn't work with ':'.
$str = "https://play.spotify.com/artist/6mdiAmATAx73kdxrNrnlao";
or:
$str = "spotify:artist:6mdiAmATAx73kdxrNrnlao";
if (
preg_match('artist/([a-zA-Z0-9]{22})/', $str, $re) ||
preg_match('artist:([a-zA-Z0-9]{22})/', $str, $re)
) {
$spotifyId = $re[1];
}
Any help is appreciated!

Try this for urls having slashes. If the Spotify string uses colons(:) simply switch the / to a : in the explode() function:
// your url
$url = "https://play.spotify.com/artist/6mdiAmATAx73kdxrNrnlao/blah/blah/blah";
// get path only
$path = parse_url($url)['path'];
// seperate by forward slash
$parts = explode('/', $path);
// go through them and find string with 22 characters
$id = '';
foreach ($parts as $key => $value) {
if (strlen($value) === 22 ) {
// found it, now store it
$id = $value;
break;
}
}
A rough sample of a helpful function would be as follows:
function getSpotifyId($spotifyUrl) {
// check for valid url
if (!filter_var($spotifyUrl, FILTER_VALIDATE_URL)) {
// split using colon
$parts = explode(':', parse_url($spotifyUrl)['path']);
} elseif (filter_var($spotifyUrl, FILTER_VALIDATE_URL)) {
// split using forward slash
$parts = explode('/', parse_url($spotifyUrl)['path']);
}
// loop through segments to find id of 22 chars
foreach ($parts as $key => $value) {
// assuming id will always be 22 characters
if (strlen($value) === 22 ) {
// found it, now return it
return $value;
}
}
return false;
}
$id1 = getSpotifyId('http://localhost/xampp/web_development/6mdiAmATAx73kdxrNrnlao/stack.php');
$id2 = getSpotifyId('spotify:artist:6mdiAmATAx73kdxrNrnlao');
$id3 = getSpotifyId('My name is tom');
results:
$id1 = '6mdiAmATAx73kdxrNrnlao'
$id2 = '6mdiAmATAx73kdxrNrnlao'
$id3 = false

Related

How to get value of specified part of pattern from URL string like MVC route using php?

i have these variables:
$pathPattern = '/catalog/{name}/{id}';
$pathRealUrl = '/catalog/test-product/12343';
The $pathPattern is dynamic, from a json file.
The $pathRealUrl is the url.
Now I need to create this two variables:
$name = 'test-product';
$id = 12343;
Note that the $pathPattern can have many variables
and also that {name} and {id} can have different name ( like {xxx} or {pippo} ), other sample:
$pathPattern = '/home/test/{hello}';
$pathRealUrl = '/home/test/alex';
The best way for archive this?
Split both string by / delimiter and loop through generated array from $pathPattern. In loop, get string that is between { and } and create variable named to it. At the end, set value of relevant index of $pathRealUrlArr in created variable.
$pathPatternArr = explode("/", $pathPattern);
$pathRealUrlArr = explode("/", $pathRealUrl);
foreach($pathPatternArr as $key=>$item){
if (preg_match("/^{(\w+)}$/", $item, $matches))
${$matches[1]} = $pathRealUrlArr[$key];
}
echo $name, $id;
See result in demo
You can shorten the code like bottom
foreach(explode("/", $pathPattern) as $key=>$item){
if (preg_match("/^{(\w+)}$/", $item, $matches))
${$matches[1]} = explode("/", $pathRealUrl)[$key];
}
echo $name, $id;
If the count of the number of values between the slashes will remain same or the position of the {name}/{id} will remain same then you can use explode to split the string by "/" and the get the desired values from the resultant array.
e.g.
$pathRealUrl = '/catalog/test-product/12343';
$array = explode("/",$pathRealUrl );
$id = $array[count($array)-1];
$name = $array[count($array)-2];
Ideone link : http://ideone.com/aNpxEJ
Hope it helps. :)
$pathPattern = '/catalog/{name}/{id}';
$pathRealUrl = '/catalog/test-product/12343';
$b = explode("/", $pathPattern);
$e = explode("/", $pathRealUrl);
$i = 0;
foreach ($b as $v) {
${substr($v,1,-1)} = $e[$i];
$i++;
}
echo $name;
echo $id;
And:
$i = 0;
foreach (explode("/", $pathPattern) as $v) {
${substr($v,1,-1)} = explode("/", $pathRealUrl)[$i];
$i++;
}
Show demo

Unset array Items matching a pattern [duplicate]

This question already has answers here:
filter values from an array similar to SQL LIKE '%search%' using PHP
(4 answers)
Closed last month.
I have the following Array :
Array
{
[0]=>"www.abc.com/directory/test";
[1]=>"www.abc.com/test";
[2]=>"www.abc.com/directory/test";
[3]=>"www.abc.com/test";
}
I only want the items that have something in middle in URL like /directory/ and unset the items that do not have that.
Output should be like:
Array
{
[0]=>"www.abc.com/directory/test";
[1]=>"www.abc.com/directory/test";
}
An example without closures. Sometimes you just need to understand the basics first, before you can move on to the neater stuff.
$newArray = array();
foreach($array as $value) {
if ( strpos( $value, '/directory/') ) {
$newArray[] = $value;
}
}
Try using array_filter this:
$result = array_filter($data, function($el) {
$parts = parse_url($el);
return substr_count($parts['path'], '/') > 1;
});
If you have something inside path will allways contain at least 2 slashes.
So for input data
$data = Array(
"http://www.abc.com/directory/test",
"www.abc.com/test",
"www.abc.com/directory/test",
"www.abc.com/test/123"
);
you output will be
Array
(
[0] => http://www.abc.com/directory/test
[2] => www.abc.com/directory/test
[3] => www.abc.com/test/123
)
A couple of approaches:
$urls = array(
'www.abc.com/directory/test',
'www.abc.com/test',
'www.abc.com/foo/directory/test',
'www.abc.com/foo/test',
);
$matches = array();
// if you want /directory/ to appear anywhere:
foreach ($urls as $url) {
if (strpos($url, '/directory/')) {
$matches[] = $url;
}
}
var_dump($matches);
$matches = array();
// if you want /directory/ to be the first path:
foreach ($urls as $url) {
// make the strings valid URLs
if (0 !== strpos($url, 'http://')) {
$url = 'http://' . $url;
}
$parts = parse_url($url);
if (isset($parts['path']) && substr($parts['path'], 0, 11) === '/directory/') {
$matches[] = $url;
}
}
var_dump($matches);
<?php
$array = Array("www.abc.com/directory/test",
"www.abc.com/test",
"www.abc.com/directory/test",
"www.abc.com/test",
);
var_dump($array);
array_walk($array, function($val,$key) use(&$array){
if (!strpos($val, 'directory')) {
unset($array[$key]);
}
});
var_dump($array);
php >= 5.3.0

URI segment to associative array in code igniter

I have following url:
www.example.com/index.php/search/search_data/Doctor:a/Gender:Male/Language:Urdu/
and I want to convert it to associative array like
$data=array(
'Doctor'=> 'a',
'Gender'=> 'Male',
'Language'=> 'Urdu'
);
I have tried to do this using codeIgniter's URI class function
$this->uri->uri_to_assoc(n)
but as it accepts the data to be separated via '/' but I am having data with ':' as separator.
please help me.
I don't think there's an easier way to do this, rather than to do it manually.
First, retrieve the total segments, loop through, see if it contains ":", then add it into the array.
$segments = $this->uri->segment_array();
$search_array = array();
foreach($segments as $segment) {
if (strpos($segment, ":") !== FALSE) {
$e_array = explode(":", $segment);
$search_array[$e_array[0]] = $e_array[1];
}
}
Running that snippet somewhere will give you desirable results, $search_array will be an associative array with key => value.
You could hack the URI.php file. Change lines 431 - 439 to;
if (strpos($seg, ":") !== FALSE) {
list($parameter, $value) = explode(':', $seg);
if ($i % 2) {
$retval[$parameter] = $value;
} else {
$retval[$parameter] = $value;
$lastval = $seg;
}
} else {
if ($i % 2) {
$retval[$lastval] = $seg;
} else {
$retval[$seg] = FALSE;
$lastval = $seg;
}
}

PHP: building a URL path

I have a few strings to combine to build a full path. e.g.
$base = "http://foo.com";
$subfolder = "product/data";
$filename = "foo.xml";
// How to do this?
$url = append_url_parts($base, $subfolder, $filename); ???
String concatenation won't do, that would omit the necessary forward slashes.
In Win32 I'd use PathCombine() or PathAppend(), which would handle adding any necessary slashes between strings, without doubling them up. In PHP, what should I use?
Try this:
$base = "http://foo.com";
$subfolder = "product/data";
$filename = "foo.xml";
function stripTrailingSlash(&$component) {
$component = rtrim($component, '/');
}
$array = array($base, $subfolder, $filename);
array_walk_recursive($array, 'stripTrailingSlash');
$url = implode('/', $array);
when it comes down to something like this I like to use a special function with unlimited parameters.
define('BASE_URL','http://mysite.com'); //Without last slash
function build_url()
{
return BASE_URL . '/' . implode(func_get_args(),'/');
}
OR
function build_url()
{
$Path = BASE_URL;
foreach(func_get_args() as $path_part)
{
$Path .= '/' . $path_part;
}
return $Path;
}
So that when I use the function I can do
echo build_url('home'); //http://mysite.com/home
echo build_url('public','css','style.css'); //http://mysite.com/public/css/style.css
echo build_url('index.php'); //http://mysite.com/index.php
hope this helps you, works really well for me especially within an Framework Environment.
to use with params you can append the url like so for simplicity.
echo build_url('home') . '?' . http_build_query(array('hello' => 'world'));
Would produce: http://mysite.com/home?hello=world
not sure why you say string concat won't do, because something like this is basically similar to a string concat. (untested semi-pseudo)
function append_url_parts($base, $subf, $file) {
$url = sprintf("%s%s%s", $base, (($subf)? "/$subf": ""), (($file)? "/$file": ""));
return $url;
}
with string concat, we'd have to write a slightly longer block like so:
function append_url_parts($base, $subf, $file) {
$subf = ($subf)? "/$subf": "";
$file = ($file)? "/$file": "";
$url = "$base$subf$file";
return $url;
}
I usually go simple:
<?
$url = implode('/', array($base, $subfolder, $filename));
Either that or use a framework, and then use whatever route system it has.
There are a few considerations first.
Are you interested in getting the current path of the script or some other path?
How flexible do you need this to be? Is it something that is going to change all the time? Is it something an admin will set once and forget?
You want to be careful not to include the slash bug where your document has a slash added at the end because you were too lazy to figure out how to separate directory vars from the file var. There will only be one file and one base per URL and unknown number of directories in each path, right? :)
If you want to make sure there are no duplicate slashes within the resultant path, I like this little function...simply pass it an array of path part you want combined and it will return a formatted path - no need to worry whether any of the parts contain a slash alerady or not:
function build_url($arr)
{
foreach ( $arr as $path ) $url[] = rtrim ( $path, '/' );
return implode( $url, '/' );
}
This should work on all versions of PHP too.
Not my code, but a handy function which takes an absolute URL and a relative URL and combines the two to make a new absolute path.
The function has been modified to ignore an absolute URL passed as relative ( basically anything that includes a schema ).
$url = "http://www.goat.com/money/dave.html";
$rel = "../images/cheese.jpg";
$com = InternetCombineURL($url,$rel);
public function InternetCombineUrl($absolute, $relative) {
$p = parse_url($relative);
if(isset($p["scheme"]))return $relative;
extract(parse_url($absolute));
$path = dirname($path);
if($relative{0} == '/') {
$cparts = array_filter(explode("/", $relative));
}
else {
$aparts = array_filter(explode("/", $path));
$rparts = array_filter(explode("/", $relative));
$cparts = array_merge($aparts, $rparts);
foreach($cparts as $i => $part) {
if($part == '.') {
$cparts[$i] = null;
}
if($part == '..') {
$cparts[$i - 1] = null;
$cparts[$i] = null;
}
}
$cparts = array_filter($cparts);
}
$path = implode("/", $cparts);
$url = "";
if($scheme) {
$url = "$scheme://";
}
if(isset($user)) {
$url .= "$user";
if($pass) {
$url .= ":$pass";
}
$url .= "#";
}
if($host) {
$url .= "$host/";
}
$url .= $path;
return $url;
}
I wrote this function for all cases to combine url parts with no duplicate slashes.
It accepts many arguments or an array of parts.
Some parts may be empty strings, that does not produce double slashes.
It keeps starting and ending slashes if they are present.
function implodePath($parts)
{
if (!is_array($parts)) {
$parts = func_get_args();
if (count($parts) < 2) {
throw new \RuntimeException('implodePath() should take array as a single argument or more than one argument');
}
} elseif (count($parts) == 0) {
return '';
} elseif (count($parts) == 1) {
return $parts[0];
}
$resParts = [];
$first = array_shift($parts);
if ($first === '/') {
$resParts[] = ''; // It will keep one starting slash
} else {
// It may be empty or have some letters
$first = rtrim($first, '/');
if ($first !== '') {
$resParts[] = $first;
}
}
$last = array_pop($parts);
foreach ($parts as $part) {
$part = trim($part, '/');
if ($part !== '') {
$resParts[] = $part;
}
}
if ($last === '/') {
$resParts[] = ''; // To keep trailing slash
} else {
$last = ltrim($last, '/');
if ($last !== '') {
$resParts[] = $last; // Adding last part if not empty
}
}
return implode('/', $resParts);
}
Here is a check list from unit test. Left array is input and right part is result string.
[['/www/', '/eee/'], '/www/eee/'],
[['/www', 'eee/'], '/www/eee/'],
[['www', 'eee'], 'www/eee'],
[['www', ''], 'www'],
[['www', '/'], 'www/'],
[['/www/', '/aaa/', '/eee/'], '/www/aaa/eee/'],
[['/www', 'aaa/', '/eee/'], '/www/aaa/eee/'],
[['/www/', '/aaa/', 'eee/'], '/www/aaa/eee/'],
[['/www', 'aaa', 'eee/'], '/www/aaa/eee/'],
[['/www/', '/aaa/'], '/www/aaa/'],
[['/www', 'aaa/'], '/www/aaa/'],
[['/www/', 'aaa/'], '/www/aaa/'],
[['/www', '/aaa/'], '/www/aaa/'],
[['/www', '', 'eee/'], '/www/eee/'],
[['www/', '/aaa/', '/eee'], 'www/aaa/eee'],
[['/www/', '/aaa', ''], '/www/aaa'],
[['', 'aaa/', '/eee/'], 'aaa/eee/'],
[['', '', ''], ''],
[['aaa', '', '/'], 'aaa/'],
[['aaa', '/', '/'], 'aaa/'],
[['/', 'www', '/'], '/www/'],
It can be used as implodePath('aaa', 'bbb') or implodePath(['aaa', 'bbb'])

Finding tags in query string with regular expression

I have to set some routing rules in my php application, and they should be in the form
/%var/something/else/%another_var
In other words i beed a regex that returns me every URI piece marked by the % character, String marked by % represent var names so they can be almost every string.
another example:
from /%lang/module/controller/action/%var_1
i want the regex to extract lang and var_1
i tried something like
/.*%(.*)[\/$]/
but it doesn't work.....
Seeing as it's routing rules, and you may need all the pieces at some point, you could also split the string the classical way:
$path_exploded = explode("/", $path);
foreach ($path_exploded as $fragment) if ($fragment[0] == "%")
echo "Found $fragment";
$str='/%var/something/else/%another_var';
$s = explode("/",$str);
$whatiwant = preg_grep("/^%/",$s);
print_r($whatiwant);
I don’t see the need to slow down your script with a regex … trim() and explode() do everything you need:
function extract_url_vars($url)
{
if ( FALSE === strpos($url, '%') )
{
return $url;
}
$found = array();
$parts = explode('/%', trim($url, '/') );
foreach ( $parts as $part )
{
$tmp = explode('/', $part);
$found[] = ltrim( array_shift($tmp), '%');
}
return $found;
}
// Test
print_r( extract_url_vars('/%lang/module/controller/action/%var_1') );
// Result:
Array
(
[0] => lang
[1] => var_1
)
You can use:
$str = '/%lang/module/controller/action/%var_1';
if(preg_match('#/%(.*?)/[^%]*%(.*?)$#',$str,$matches)) {
echo "$matches[1] $matches[2]\n"; // prints lang var_1
}

Categories