Make a router like zend - php

I have a url http://*.com/branch/module/view/id/1/cat/2/etc/3.
It becomes.
array
(
'module'=>'branch',
'controller'=>'module',
'action'=>'view'
);
next I need to get the params.
Ihave this array.
/*function getNextSegments($n,$segments) {
return array_slice ( $q = $this->segments, $n + 1 );
}
$params = getNextSegments(3);
*/
array ( 0 => 'id', 1 => '1', 2 => 'cat', 3 => '2', 4 => 'etc', 5 => '3' );//params
And i wanna convert it to this one:
array
(
'id'=>1,
'cat'=>2,
'etc'=>3,
);
How i can do this using php function. I know I can do using for or foreach, but I think php has such function , but i cant find it :(.
Thank you.
class A {
protected function combine($params) {
$count = count ( $params );
$returnArray = array ();
for($i = 0; $i < $count; $i += 2) {
$g = $i % 2;
if ($g == 0 or $g > 0) {
if (isset ( $params [$i] ) and isset ( $params [$i + 1] ))
$returnArray [$params [$i]] = $params [$i + 1];
}
}
return $returnArray;
}
}
This works normaly. If anybody has better logic for this please help.
Thank you again.

PHP does not have a built-in function for this. I would just implement it with explode and a loop, shouldn't be that hard.

I use a function like this in my extended Zend_Controller_Action class.
public function getCleanParams()
{
$removeElements = array(
'module' => '',
'controller' => '',
'action' => '',
'_dc' => ''
);
return array_diff_key($this->_request->getParams(), $removeElements);
}
That will give you your parameters in a clean fashion and the format you want it in.

You can start building your router with the following regular expression (name the file index.php):
<?php
$pattern = '#^(?P<module>branch)/'.
'(?P<controller>module)/'.
'(?P<action>view)'.
'(:?/id[s]?/(?P<id>[0-9]+))?'.
'(:?/cat[s]?/(?P<cat>[0-9]+))?'.
'(:?/etc[s]?/(?P<etc>[0-9]+))?#ui';
preg_match($pattern, trim($_SERVER['REQUEST_URI'], '/'), $segment);
echo sprintf('<pre>%s</pre>', var_export($segment, true));
Assuming you have PHP 5.4.x installed, you can type the following on the command-line:
% php -S localhost:8765
Now browse to http://localhost:8765/branch/module/view/id/1/cat/2/etc/3
The output will be (removed numeric keys except 0 for clarity):
array (
0 => 'branch/module/view/id/1/cat/2/etc/3',
'module' => 'branch',
'controller' => 'module',
'action' => 'view',
'id' => '1',
'cat' => '2',
'etc' => '3',
)

Related

Search associative array of arrays. How?

My question is how can I search an array built this way? Basically there may be a need to repeat the key and this is what I got so far to maybe solve this. If the price is the same for 2 different items I cannot have 2 keys with the same value.
Please feel free to improve on array layout.
$price_list = array(
1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")
);
Provided there will never be any duplication of the second column, you can do this:
$search = "EA_WTRESRVD"; //value to search for
$price_list = array(
1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")
);
$array = array_column($price_list, 0, 1);
echo $array[$search];
I would suggest that if you have a unique product code (SKU), you should use this to index your array.
$products = [
'EA_WTRESRVD' => [
'name' => '...',
'price' => 9.99,
// ...
],
'EA_WTRESRV' => [
'name' => '...',
'price' => 9.99,
// ...
],
];
Then you can access the price of any product by it's SKU.
$price = $products['EA_WTRESRV']['price'];
Here's one way:
<?php
$price_list = [ 1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")];
$search = "EA_WTRESRV";
foreach ($price_list as $arr) {
if (in_array( $search, $arr )) {
echo $search;
}
}
The foreach iterates over the multidimensional array whose elements are each arrays. Each array is inspected by in_array() for the search term.
However, this is not the only way. If you wish to avoid in_array(), you could also code as follows:
<?php
$price_list = [ 1 => array("9.99", "EA_WTRESRVD"),
2 => array("9.99", "EA_WTRESRV")];
$search = "EA_WTRESRV";
$len = strlen($search);
foreach ($price_list as $arr) {
$val = array_values($arr);
foreach($val as $v) {
if ( ( strpos( $v,$search )) !== false) {
if ( strlen($v) == $len) {
echo "$search is in the price list.\n";
}
}
}
}

Express function as a variable

I dont know exactly how to put this. I have this function:
protected function _do_thumb($temaid)
{
$firstPost = $this->registry->topics->getPostById( $temaid );
preg_match('/< *img[^>]*src *= *["\']?([^"\']*)/i', $firstPost['post'], $match);
return $match[1];
}
[...]
while ( $i = $this->DB->fetch() )
{
$forum = $this->registry->class_forums->forum_by_id[ $i['forum_id'] ];
if ( $this->registry->permissions->check( 'read', $forum ) != TRUE )
{
continue;
}
if ( $forum['password'] != "" )
{
continue;
}
$to_echo .= $this->_parseTemplate( $row, array (
'topic_title' => str_replace( '&#', '&#', $i['title'] ),
'topic_id' => $i['tid'],
'topic_link' => "showtopic=".$i['tid'],
'forum_title' => htmlspecialchars($forum['name']),
'forum_id' => $i['forum_id'],
'last_poster_id' => $i['last_poster_id'],
'last_post_name' => $i['last_poster_name'],
'last_post_time' => $this->registry->getClass('class_localization')->getDate( $i['last_post'] , 'LONG', 1 ),
'timestamp' => $i['start_date'],
'starter_id' => $i['starter_id'],
'starter_name' => $i['starter_name'],
'board_url' => $this->settings['board_url'],
'board_name' => $this->settings['board_name'],
'rfc_date' => date( 'j\-M\-Y', $i['start_date']),
'thumb' => $this->_do_thumb($i['topic_firstpost'])
) ) . "\r\n";
}
$firstPost is supposed to produce a value result of another function. The problem here is that that function seems to stop halfway the whole loop so it returns an incomplete result, only the first element of a list. $forum however works fine because it is expressed as a variable so I believe the solution might be to express $topic in the same way. Something like this:
$this->registry->topics->getPostById[ $temaid ];
However, I dont know how I ought do it. Is it even possible?
Thank you.
getBostById() and $i = $this->DB->fetch() in while loop where you call getPostById(), they both use $this->DB to store information from Database.
And when called getPostById(), it overrides information inside of $this->DB and moves hidden pointer to the end. This function returns POST data from database, and also uses something like $i = $this->DB->fetch() for this. Therefore pointer to data moves to the end.
Next, time when $i = $this->DB->fetch() called, it sees pointer at the end, and stop looping.
Solution is, when fetching result from database, don't override it. There for cache them before calling getPostById:
//while ( $i = $this->DB->fetch() )
$items = array();
$counter = 0 ;
while ($i = $this->DB->fetch()) {
$items[$counter++] = $i;
}
foreach ( $items as $i ){
$forum = $this->registry->class_forums->forum_by_id[ $i['forum_id'] ];
if ( $this->registry->permissions->check( 'read', $forum ) != TRUE )
{
continue;
}
if ( $forum['password'] != "" )
{
continue;
}
$to_echo .= $this->_parseTemplate( $row, array (
'topic_title' => str_replace( '&#', '&#', $i['title'] ),
'topic_id' => $i['tid'],
'topic_link' => "showtopic=".$i['tid'],
'forum_title' => htmlspecialchars($forum['name']),
'forum_id' => $i['forum_id'],
'last_poster_id' => $i['last_poster_id'],
'last_post_name' => $i['last_poster_name'],
'last_post_time' => $this->registry->getClass('class_localization')->getDate( $i['last_post'] , 'LONG', 1 ),
'timestamp' => $i['start_date'],
'starter_id' => $i['starter_id'],
'starter_name' => $i['starter_name'],
'board_url' => $this->settings['board_url'],
'board_name' => $this->settings['board_name'],
'rfc_date' => date( 'j\-M\-Y', $i['start_date']),
'thumb' => $this->_do_thumb($i['topic_firstpost'])
) ) . "\r\n";
}

Localize markers in PHP Array

This is quite basic, but I am missing a puzzle piece.
I have a multidimensional PHP array that - among other things - contains some strings. I would like to translate special strings in this array based on a translation table or array in PHP.
$r = array(
0 => 'something',
1 => array(
'othertext' => '1000 {{animals}} and {{cars}}',
'anytext' => '400 {{cars}}',
)
);
In $r, now I would like to replace {{animals}} with another string that is stored in a separate array.
Here it is:
$translations = array(
'animals' => array('Tiere','animaux','bestie'),
'cars' => array('Autos','voitures','macchine'),
);
Now let's set the language / column we want to look up
$langId = 0;
And now, take $r, look for all key that are wrapped in {{}}, look them up in $translations and replace them with key[$langId], so in return we get:
$r = array(
0 => 'something',
1 => array(
'othertext' => '1000 Tiere',
'anytext' => '400 Autos',
)
);
ehm... how's that done?
PS: the marker {{}} is random, could be anything robust
I was able to get the output you expected using the following code. Try it and tell me if it worked for you or not:
<?php
$r = array(
0 => 'something',
1 => array(
'othertext' => '1000 {{animals}} and {{cars}}',
'anytext' => '400 {{cars}}',
)
);
$translations = array(
'animals' => array('Tiere','animaux','bestie'),
'cars' => array('Autos','voitures','macchine'),
);
$langId = 0;
$pattern = "/\{\{[a-zA-Z]+\}\}/";
for($t=0; $t<count($r); $t++) {
$row = $r[$t];
if(!is_array($row))
continue;
foreach($row as $key=>$value) {
if(preg_match_all($pattern, $value, $match, PREG_SET_ORDER)) {
for($i = 0; $i < count($match); $i++) {
//remove {{ & }} to get key
$k = substr($match[$i][0], 2, strlen($match[$i][0])-4);
$replacer = $translations[$k][$langId];
$value = str_replace($match[$i][0], $replacer, $value);
$r[$t][$key] = $value;
}
}
}
}
?>

PHP Find a value in a key and get the value of another key in a multi-dimentional array

Might be a newbie question but I've been trying to figure this problem and it's doing my head in.
I have the following array :
[0] => Array
(
[provisionalBookingRoomID] => 1
[totalSpecificRoomCount] => 2
)
[1] => Array
(
[provisionalBookingRoomID] => 2
[totalSpecificRoomCount] => 5
)
I need a php function that searches through the array for the value of 'provisionalBookingRoomID' and returns the value of 'totalSpecificRoomCount'
basically something like the following
getProvisionalTotalRoomsCount($currentRoom, $arrayOfRooms);
// getProvisionalTotalRoomsCount('1', $arrayOfRooms) should return 2;
Any ideas?
Check this:
getProvisionalTotalRoomsCount($currentRoom, $arrayOfRooms){
foreach($arrayOfRooms as $key=>$value){
if($value['provisionalBookingRoomID'] == $currentRoom){
return $value['totalSpecificRoomCount'];
}
}
}
For anyone looking for a generic function :
function findValueInArray($array, $searchValue, $searchKey, $requiredKeyValue) {
foreach($array as $key=>$value){
if($value[$searchKey] == $searchValue){
return $value[$requiredKeyValue];
}
}
}
// Usage : findValueInArray($provisionalBookedRoomsArray, '1', 'provisionalBookingRoomID', 'totalSpecificRoomCount');
If you are likely to work with more than one value, you could build a new array with a 1->1 map for those attributes.
<?php
$items = array(
array(
'name' => 'Foo',
'age' => 23
),
array(
'name' => 'Bar',
'age' => 47
)
);
// Php 7
$name_ages = array_column($items, 'name', 'age');
echo $name_ages['Foo']; // Output 23
// Earlier versions:
$name_ages = array();
foreach($items as $value)
{
$name_ages[$value['name']] = $value['age'];
}
echo $name_ages['Foo']; // Output 23
$value = 0;
$array = array(array("provisionalBookingRoomID"=>1,"totalSpecificRoomCount"=>2),array("provisionalBookingRoomID"=>2,"totalSpecificRoomCount"=>5));
array_map(
function($arr) use (&$value) {
if($arr['provisionalBookingRoomID']==1) {
$value = $arr['totalSpecificRoomCount'];
}
},$array
);
echo $value;

PHP Variables for if statements

Ok, I am wanting to do something like this:
$which = !empty($param_id) ? "['groups'][$param_id]" : "['groups']";
And than I'd like it to be able to do something like so...
$all_groups . $which = array(
-1 => array(
'id' => '-1',
'name' => $txt['parent_guests_only'],
'checked' => in_array('-1', $checked) || in_array('-3', $checked),
'is_post_group' => false,
)
And I need it to build an array like so, if !empty($param_id)
$all_groups['groups'][$param_id] = array(the array info);
But if $param_id is empty it should do the this instead:
$all_groups['groups'] = array(the array info);
I don't think I can concatenate it or can I?
Can someone please help me here? This is happening many many times throughout a function, so I don't want to use if... else... statements every single time. Would be too many, thinking of a 1 fast approach for all of them.
Thanks :)
EDIT, here is the function in question:
function ListGroups($checked = array(), $unallowed = array(), $order = array(), $param_id = 0)
{
global $context, $smcFunc, $txt;
// We'll need this for loading up the names of each group.
if (!loadLanguage('ManageBoards'))
loadLanguage('ManageBoards');
if (empty($checked))
return array();
$all_groups['groups'][$param_id] = array();
if (!in_array('-1', $unallowed))
// Guests
$all_groups['groups'][$param_id] = array(
-1 => array(
'id' => '-1',
'name' => $txt['parent_guests_only'],
'checked' => in_array('-1', $checked) || in_array('-3', $checked),
'is_post_group' => false,
)
);
if (!in_array('0', $unallowed))
{
// Regular Members
if (!empty($all_groups['groups']))
$all_groups['groups'][$param_id] += array(
0 => array(
'id' => '0',
'name' => $txt['parent_members_only'],
'checked' => in_array('0', $checked) || in_array('-3', $checked),
'is_post_group' => false,
)
);
else
$all_groups['groups'][$param_id] = array(
0 => array(
'id' => '0',
'name' => $txt['parent_members_only'],
'checked' => in_array('0', $checked) || in_array('-3', $checked),
'is_post_group' => false,
)
);
}
// Load membergroups.
$request = $smcFunc['db_query']('', '
SELECT group_name, id_group, min_posts
FROM {db_prefix}membergroups
WHERE id_group > {int:is_zero}',
array(
'is_zero' => 0,
)
);
while ($row = $smcFunc['db_fetch_assoc']($request))
{
if (!in_array($row['id_group'], $unallowed))
{
$all_groups['groups'][(int) $param_id][(int) $row['id_group']] = array(
'id' => $row['id_group'],
'name' => trim($row['group_name']),
'checked' => in_array($row['id_group'], $checked) || in_array('-3', $checked),
'is_post_group' => $row['min_posts'] != -1,
);
}
}
$smcFunc['db_free_result']($request);
// Let's sort these arrays accordingly!
if (!empty($order))
{
$all_groups['groups'][$param_id] = sortGroups($all_groups['groups'][$param_id], $order);
$context['group_order' . $param_id] = implode(', ', $order);
}
else
{
$context['group_order' . $param_id] = '';
sort($all_groups['groups'][$param_id]);
$x = 0;
foreach ($all_groups['groups'][$param_id] as $key => $value)
{
$x++;
$context['group_order' . $param_id] .= $x < count($all_groups['groups'][$param_id]) ? $value['id'] . ', ' : $value['id'];
}
}
return $all_groups['groups'][$param_id];
}
I need to do a check for !empty($param_id), if so, it needs to build the $all_groups['groups'] array without the $param_id.
So will need to add in a check for if (!empty($params_id)) build the array like so: $all_groups['groups'][$params_id] else build it like this instead: $all_groups['groups']. I don't want a bunch of if... else... statements in here, just a 1 or 5 liner would be GREAT!
Thanks Guys :)
Don't overcomplicate it. :)
$array = array(
/* contents */
);
if (!empty($param_id)) {
$all_groups['groups'][$param_id] = $array;
} else {
$all_groups['groups'] = $array;
}
I don't know what $all_groups['groups'] looks like before this; if it was empty, I'd shorten this to:
$all_groups['groups'] = array(
/* contents */
);
if (!empty($param_id)) {
$all_groups['groups'] = array($param_id => $all_groups['groups']);
}
if (!empty($param_id)) {
$which = &$all_groups['groups'][$param_id]
} else {
$which = &$all_groups['groups'];
}
$which = array(
-1 => array(
'id' => '-1',
'name' => $txt['parent_guests_only'],
'checked' => in_array('-1', $checked) || in_array('-3', $checked),
'is_post_group' => false,
);
unset($which); // unset $which, if you want to use this variable
// in this scope once again
Generally speaking, references are the solution. See #zerkms' answer.
However, if at all possible, I would try to redesign your data structures such that you don't have to resort to this type of conditional behavior. For example, using default as the default missing key:
$which = !empty($param_id) ? $param_id : 'default';
$all_groups['groups'][$which] = array( ... );
I don't know if it's possible in your case, but this could be easier to manage.
Other potential solutions:
$tmp = array( ... );
if ($cond)
$foo = $tmp;
else
$bar = $tmp;
or:
function make_array( ... )
{
return array( ... );
}
if ($cond)
$foo = make_array( ... );
else
$bar = make_array( ... );

Categories