I'm currently working on an advance search feature that needs to work with .htaccess clean urls. This search could have 3-5 Parameters depending on what the user inputs. So basically the search string ( before clean URL ) could be something like this:
http://www.example.com?category=lorem&subcategory=ipsum&on_sale=1&featured=1&vendor=foo
These parameters could also be in a different order, so I can't use the standard regex method to clean up the URL.
The way I solved this was to use keywords & terms in the URL.
My final URL looked like so:
http://www.example.com/search/term/lorem/category/shirts/subcategory/tank-top/color/red/featured/1
In htaccess I looked for the signifier "/search" and made rules for search parameters that followed.
RewriteRule ^search/([A-Za-z0-9_-\s]+)/([A-Za-z0-9_-\s]+)/?$ http://www.example.com/?page=search&keywords[]=$1&terms[]=$2 [QSA,NC]
etc,etc.
So basically in PHP, all odd indices are stored in a $keywords array and all even indices are stored in a $terms array.
I then check all keywords against a list of acceptable keywords to prevent MySQL injection.
$allowable_keywords = array('term','category','subcategory','color','featured');
I am then able to filter the search results with this tidy little search array by combining the keywords and terms.
$params = array_combine($keywords,$terms);
$params = array(
'term' => 'lorem',
'category' => 'shirts',
'subcategory' => 'tank-top',
'color' => 'red',
'featured' => 1
);
Hope this helps!
Related
I am pretty sure this challenge has been solved by someone already but even searching with different words, I could not find a solution for this problem:
I try to give users the possibility to run certain functions of a class based on an argument like
service_class::do_this( "selection-argument" );
but the user shall be able to use "clear words" as well as "aliases" and even "well known" abbreviations or synonyms.
I use switch-case construction to call the "real" function.
Example: To get the contens of a folder, The user can use "getdir", "dir", "Directory", "getfolder", "getcontent", "content", "d-cont" and a number of more other "matching words" to start the function(s) underlaying and getting back the very same result.
Capture-ing lowercase/uppercase is simple. What I search for is an efficient way to capture all possible "variations" - that are, of course different number of variations for different functions called.
At the moment I use multiple "case "": lines after each other, but that makes the code quite long, and further I would like the user to be able to "enahnce" the recognition set for a certain function.
That's why I thought about "stripos" to determine first what "internal word" to use and only then run into the switch-case construction.
Anyone had that issue and can direct me to a "good and efficient" solution?
Seems that Stck-exchange itself had a similar challenge (https://codereview.stackexchange.com/tags/php/synonyms) ... maybe I can simply re-use the underlying code?
Thanks in advance and sorry if I overlooked a solution already posted.
You could use a database or array. Let's do the latter. So to determine whether an user wants to get a directory you would define an array like this:
$getDirVariants = ['getdir',
'dir',
'directory',
'getfolder',
'getcontent',
'content',
'd-cont'];
It is easy to add more of these arrays. To test the query word you would do:
$queryWord = strtolower($queryWord);
if (in_array($queryWord, $getDirVariants)) service_class::getDir(<arguments>);
elseif (in_array($queryWord, $deleteVariants)) service_class::delete(<arguments>);
You can easily add to the arrays or make it a 2D array to contain more commands. That array could also be placed in a database.
Especially when there are many commands, with many variants, a database will be the better solution, because you can find the query word with one database query.
There's a variation I can think of that will also simplify the code when there are many commands. You could use an associative array to find the command:
$commandVariants = ['getdir' => 'getdir',
'dir' => 'getdir',
'directory' => 'getdir',
'getfolder' => 'getdir',
'getcontent' => 'getdir',
'content' => 'getdir',
'd-cont' => 'getdir',
'delete' => 'delete',
'del' => 'delete',
'remove' => 'delete',
'unlink' => 'delete'];
$queryWord = strtolower($queryWord);
if (isset($commandVariants[$queryWord])) {
$command = $commandVariants[$queryWord];
service_class::$command(<arguments>);
}
else echo "I don't recognize that command.";
This uses a variable identifier.
Example:
I want to make an url with different categorised variables. And there is an order. First variable is vegetables({variable01}), second is fruits({variable02}), third is trees ({variable03}) etc.
xxx.com/{variable01}-{variable02}-{variable03}-{variable04}-......
Yes I got this url.
BUT
What if a variable have two words(or three) AND I want the seperator is also a hyphen(brussels-sprouts)?
Example:
xxx.com/brussels-sprouts-{variable02}-{variable03}-{variable04}-......
or
xxx.com/{variable02}-green-apple-{variable03}-{variable04}-......
xxx.com/brussels-sprouts-green-apple
How can this be possible?
Thanks.
There is no way to specify the boundaries of your variables anymore, so it's only possible if you know the exact amount of variables and only 1 of your variables may contain hyphens. You can create a regex for that:
First variable:
^([\w-]+)-(\w+)-(\w+)-(\w+)$
Second variable:
^(\w+)-([\w-]+)-(\w+)-(\w+)$
But: if you know that each variable can have at most 1 hyphen, you can also do this:
/var1-foo1-var2-foo2-var3-foo3-var4
RewriteRule ^(\w+(-\w+)?)-(\w+(-\w+)?)-(\w+(-\w+)?)-(\w+(-\w+)?)$ index.php?var1=$1&var2=$3&var3=$5&var4=$7 [L]
Which results in:
array (
'var1' => 'var1-foo1',
'var2' => 'var2-foo2',
'var3' => 'var3-foo3',
'var4' => 'var4',
)
I have an array of fields & values that I wish to pass to the Amazon CloudSearchDomain as a filterQuery argument using one or both the 'and' or 'or' operators.
For example, I'd like to pass a single 'and' field (a category) and a second 'and' field which is comprised of several 'or' values:
$filters = array(
'category' => 'cat name',
'colour' => array(
'red',
'green'
)
);
I have tried:
$results = $cloudSearchClient->search(array(
'filterQuery' => "(and(category:'cat name') (or (colour:'red') (colour:'green')))"
));
So the search would find items that match 'cat name' AND are red OR green
I can't seem to pass the correct syntax manually, and would then also like a good clean solution to convert the PHP array into the correct AWS syntax please.
You might want to check two things here.
First is when you filter within the facet array you are using the 'OR' operator and if you are filtering between two facet arrays you are using 'AND'. Judging by your usage you want to display the results when a user selects either "red" or "green". Eg. filterQuery which you return should have the query --> "(or color:'red'(or color:'green'))"
Second is monitor the query that gets passed to the aws URL. Your filter query might be correct but the URL string needs to appended with html encoded space. For example http://your-search-domain/2013-01-01/search?&q.parser=structured&q.options=%7Bsomefield%27%2C+%27&sort=something%20&fq=%28or+color%3A%27red%27%28or+color%3A%27green%27%29%29....."
Not sure about how to title this post.
I just inherited a set of internationalization documents, each containing an array of key value pairs. I recognize the methodology is not ideal, it is however, what I'm stuck with given my role, the time and resources I have available. These lists were created by hand and items were constantly being added haphazardly to keep up with demand. The examples below are simplified, there are ~21 language files, each with 100+ entries.
The array from one file will have elements something like the below:
'download_high' => 'Vysoké',
'download_low' => 'Nízké',
'download_med' => 'Strední',
'download_video' => 'Stáhnout video',
While another file will have something like the following:
'download_video' => 'Descargar Video',
'download_high' => 'Alta',
'download_med' => 'Media',
'download_low' => 'Baja',
For the most part, the elements are ordered consistently, but there are plenty of exceptions and it complicates maintaining the files. I was wondering if there's a way to make the order / formatting of these arrays consistent either via an IDE or notepad++ plugin, etc. I don't want to order them alphabetically necessarily as there are logical groupings that won't translate well to alphabetical sorting since only some of the variables are namespaced. Doing it by hand is almost out of the question, but it would be nice if there were some way to specify an order and have some kind of text manipulation tool batch process the files. I'm not all that familiar with php, so I don't know that it would be worth it for me to do this via code unless it's very simple.
PHP has a function called var_export. You could run the code and then print it with the function.
Personally, I would run some regex in notepad++ to do it.
Edit: In notepad++, you can do a find/replace with regex.
In the "Find what" field, put \s*'(.+?)'\s*=>\s*'(.+?)'\s*(?:(,)|\s*$)\s*
In the "Replace with" field, put '$1' => '$2'$3\n
This will turn something like:
'download_high' => 'Vysoké',
'download_low'=>
'Nízké',
'download_med'
=>
'Strední'
,
'download_video' => 'Stáhnout video',
'filter_by' => 'Filtrovat podle'
,
'footer_contact' => 'Kontakt'
into
'download_high' => 'Vysoké',
'download_low' => 'Nízké',
'download_med' => 'Strední',
'download_video' => 'Stáhnout video',
'filter_by' => 'Filtrovat podle',
'footer_contact' => 'Kontakt'
*note: This is written with the assumption that all keys and values use single quotes and that neither keys nor values have any escaped single quotes inside.
Given the situation I'd do it semi-automatically on an as-needed basis. That is, it sounds to me like you're charged with maintaining these files, and it's in the maintenance that the sorting becomes an issue.
For each language file formatted like:
<?php
$something = array(
'download_video' => 'Descargar Video',
'download_high' => 'Alta',
...
'download_med' => 'Media',
'download_low' => 'Baja',
);
Issue a sort lang.es.php command in bash, or via however you prefer to sort something.
Open the file for editing.
Delete the array declaration.
Copy/paste the sorted lines from #1.
Honestly, it was a super bad idea for your predecessor to effectively hard-code something like this. It would be much better if this were stored via CSV, XML, pg/mySQL, etc where you could at least invoke an editor that understands the data format.
i wouldn't suggest using arrays and php files etc if you are going to have a continuously growing list. take the couple minutes now to set up mysql and pull from a database with your desired parameters. NEAT, FAST, EFFECIENT AND SCALABLE.
My suggestion would be to simply build a script to load all those arrays into a database where they can be maintained more easily. Of course you would need to make sure you database table/fields were set up for UTF-8 character sets and collations.
Am I correct in understanding that you have already gotten your data into PHP arrays? At this point you could just do this to sort the keys. This would make the ordering consistent:
ksort($array);
For a new application I'd like to work with the URI to determine what content should be loaded. Nothing special so far ... But how can I let the slug have slash(es) in it and make sure Zend Framework sees them as 1 variable? ZF splits the requested URL in chunks where every part is the string between 2 slashed. Now I'd like to have all the parts in 1 variable to work with.
For Example:
/de/my/page
de > language
my/page > 1 variable
Any ideas?
Advice from Hari K is the best choice, but if you really want to keep your slash, you can work with a Zend_Controller_Router_Route_Regex to catch your parameter, you just need to find a good regexp, a simple example :
$routetotry = new Zend_Controller_Router_Route_Regex('([^/]+)/(.*)',
array(1 => 'de', 'controller' => 'someController', 'action' => 'someAction'),
array(1 => 'lang',2=>'my_variable_with_slash'),
'%s/%s'
);
$router->addRoute('routetotry', $routetotry);
Custom router. Most flexible solution, but not the easiest one :(
Replace the slashes in the slug with someother value of your choice.
For example hyphen ( - ) or underscore ( _ ) .