I have an 2D array with a few sub-arrays (about 30, and sub-arrays have 10 elements).
I need to get quite frequently basic data from the array , I have a function that return the contents of it (or partial) all around my scripts. The function looks like:
function get_my_data($index = false){
$sub0 = array(
'something' => 'something',
'something else' => 'else',
...
);
$sub1 = array(
'something' => 'something different',
'something else' => 'else different',
...
);
...
$sub30 = array(
'something' => 'something 30 times different',
'something else' => 'else 30 times different',
...
);
$data = array($sub0,$sub1,$sub2,...,$sub30);
if($index !== false)
return $data[$index];
else
return $data;
?>
And then I call to it using include:
<?php
include 'my_data.php';
$id = $_GET['id'];
$mydata = get_my_data($id);
...
?>
I've done this because when I was starting this project, I didn't imagined I would have more that 10 sub-arrays, and I neither that I would need to have it dynamic. In fact, now I have to add a dynamic column (an index to sub-arrays) and it is not a great idea to use array declaration in this case. I immediately thought to use database, transferring data would not difficult, but if I do that, then I need to change my function get_my_data and insert a query in it, so, for it's called many times, I would have a lot of queries, pretty much every script of my website have one of it. I think performance would be worst (cause mysql is already largely used in my website). The dynamic data would change not too frequently (client do that).
The ideas I have to solve this problem are:
save all data in database and get it through mysql queries,
leave on php side and use files to manage dynamic data,
leave the static part on php side, add a logical connector (such 'id' index in sub-arrays) and id column in mysql database, and get the dynamic data on mysql
I don't want to lose much performance, do yo have any advice or suggestions?
Putting data like this in code is the worst possible plan. Not only do you create a whole bunch of junk and then throw out almost all of it, but if any of this changes it's a nightmare to maintain. Editing source code, checking it into version control, and deploying it is a lot of work to make a simple change to some data.
At the very least store this in a data format like JSON, YAML or XML so you can read it in on-demand and change a data-only file as necessary.
Ideally you put this in a database and query against it when necessary. Databases are designed to store, update, and preserve data like this.
You can also store JSON in the database, MySQL 5.7 even has a native column type for it, which makes this sort of thing even easier.
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.
I'm trying to setup caching of postcode lookups, which adds the resulting lookup to a text file using the following;
file_put_contents($cache_file, $postcode."\t".$result."\n", FILE_APPEND);
I'd like to be able to check this file before running a query, which i have done using this:
if( strpos(file_get_contents($cache_file),$postcode) !== false) {
// Run function
}
What I'd like to do, is search for the $postcode with in the text file (as above) and return the data one tab over ($result).
Firstly, is this possible?
Secondly, is this is even a good way to cache SQL lookups?
1) yes it's possible - the easiest way would be storing the lookup data in an array and write/read it from a file with serialze / unserialze
$lookup_codes = array(
'10101' => 'data postcode 1 ...',
'10102' => 'data postcode 2 ...',
// ...
);
file_put_contents($cache_file, serialize($lookup_codes));
$lookup_codes = unserialize(file_get_contents($cache_file));
$postcode = '10101';
if(array_key_exists($postcode, $lookup_codes)){
// ... is available
}
2) is the far more interesting question. It really depends on your data, the structure, the amount etc.
In my opinion, caching add more complexity to your application, and so if possible avoid it :-)
You could try to:
Optimizing your SQL query or database structure to speed it up for requesting postcode data.
Normally Databases are quite fast - and therefore made for such use-cases
I'm not sure which db you are running, but for MySQL look into Select Optimization. Or as another keyword you can search for INDEX which boost queries quite heavy
file_get_contents is really fast, but when you are changing the file often maybe look into other ways of caching, like Memcached for storing it In-Memory
I've made a script that pretty much loads a huge array of objects from a mysql database, and then loads a huge (but smaller) list of objects from the same mysql database.
I want to iterate over each list to check for irregular behaviour, using PHP. BUT everytime I run the script it takes forever to execute (so far I haven't seen it complete). Is there any optimizations I can make so it doesn't take this long to execute...? There's roughly 64150 entries in the first list, and about 1748 entries in the second list.
This is what the code generally looks like in pseudo code.
// an array of size 64000 containing objects in the form of {"id": 1, "unique_id": "kqiweyu21a)_"}
$items_list = [];
// an array of size 5000 containing objects in the form of {"inventory: "a long string that might have the unique_id", "name": "SomeName", id": 1};
$user_list = [];
Up until this point the results are instant... But when I do this it takes forever to execute, seems like it never ends...
foreach($items_list as $item)
{
foreach($user_list as $user)
{
if(strpos($user["inventory"], $item["unique_id"]) !== false)
{
echo("Found a version of the item");
}
}
}
Note that the echo should rarely happen.... The issue isn't with MySQL as the $items_list and $user_list array populate almost instantly.. It only starts to take forever when I try to iterate over the lists...
With 130M iterations, adding a break will help somehow despite it rarely happens...
foreach($items_list as $item)
{
foreach($user_list as $user)
{
if(strpos($user["inventory"], $item["unique_id"])){
echo("Found a version of the item");
break;
}
}
}
alternate solutions 1 with PHP 5.6: You could also use PTHREADS and split your big array in chunks to pool them into threads... with break, this will certainly improve it.
alternate solutions 2: use PHP7, the performances improvements regarding arrays manipulations and loop is BIG.
Also try to sort you arrays before the loop. depends on what you are looking at but very oftenly, sorting arrays before will limit a much as possible the loop time if the condition is found.
Your example is almost impossible to reproduce. You need to provide an example that can be replicated ie the two loops as given if only accessing an array will complete extremely quickly ie 1 - 2 seconds. This means that either the string your searching is kilobytes or larger (not provided in question) or something else is happening ie a database access or something like that while the loops are running.
You can let SQL do the searching for you. Since you don't share the columns you need I'll only pull the ones I see.
SELECT i.unique_id, u.inventory
FROM items i, users u
WHERE LOCATE(i.unique_id, u inventory)
I am trying to do a thing that I dont know if can work. Also accept other ideas.
I have an array passed as a parameter where the index is the task id in the database and the value is the last syncronization for the task with the database
$sync=Array
(
[22805] => 1406822699
[22806] => 1406824500
[22807] => 1406838670
)
Then I do a select in the database which gives me the whole of tasks and I one to update on the database only some tasks, basically the ones that are out of date.
//$tasks is the list of all tasks from the database and $sync is the array which is pased by the user
foreach($tasks as $task)
{
if($task['sync']<=$sync[$task['taskList_id']])
{}
else
{//to be updated
$taskModel->updateLastSync($task['taskList_id'],$time);
$task['sync']=$time;
}
}
This is the problematic line and what I need to know how to do.
$sync[$task['taskList_id']]
I want to use a parameter as index to get the value of an array.
How can I achieve this.
Because this other idea is another foreach for $sync inside the foreach for $tasks
Without seeing the full script or having access to var_dump at certain locations it's hard to say what's going on but here are some things to check:
Make sure you're getting results from the database query and that they are assigned to the $tasks variable
Make sure your $sync array values and $task['sync'] are integer types and not strings or the '<=' comparison may have unexpected results
I don't know where $time gets its value from based on code I see so verify that it does actually have a value when you try to set it
A good first step when debugging is to try to isolate the problem's location first and then worry about the cause. Using something like var_dump to verify that values of certain variables are as expected at various locations in your script is very useful. Once you know where things start going wrong you can focus your attention in the right place to find out why and come up with a solution. I recommend doing this and letting us know what you find.
I solved my question.
Which was if this is allowed, I tested and it is.
$ar=array('1'=>'a','2'=>'b','3'=>'c');
$index=2;
echo $ar[$index];
I am new to php. I was wondering how I could declare a static array in php. Here is what I would do in C. How is the corresponding php code for it?
char a[][] = { (1,1), (1,2), (1,3), (2,1), (2,2), (2,3), (3,1), (3,2), (3,3) };
From what I read it has to be something like this -
$a = array( 1 => array(1,1), 2 => array(1,2), ... );
Is this correct? If so it sucks :) I hope I am wrong.
Thanks,
- Pav
You've already found the way to do it natively.
Another option would be to declare your data as JSON (a very concise and human-friendly format). This could be either in a separate file bundled with your app, or directly in your code in a string. Then parse the JSON at runtime. Since PHP isn't exactly known for speed, this may or may not make your noticeably app slower to start.
you have it already figured out in your question.
One thing I would add is that you do not need to explicitly define the keys if you are intending to use a zero based array, this is assumed and can be done like so...
$a = array(array(1,1),array(1,2), ... );
You can also use what is called associative arrays which use string keys and you define them the same way you do in your example, except use strings instead of numbers...
$ass_array = array( 'array_1' => array(1,1), 'array_2' => array(1,2), ... );
you would then call your associative array like this...
$ass_array['array_1'];
Also, if you want to append single items to an array (for example in a loop to load an array)...
$ass_array[] = $item;
Further to jondavidjohn's anwser, you could just write a quick script to grab your list of values and generate the array statement for you.
No need to care how verbose the syntax is then. If the task is long and repetitious enough to care, don't do it by hand. :)