How to get all values from cache which start with certain key - php

As the title, I want to get all values from cache which start with certain value.
For example, I'm counting post views in my project and I'm storing them on cache. Then I want to reach all stored viewed values on cache..
with Session helper, it's separates keys by dot and create multidimensional array.
So can we can get the stored items like Session::get("views") it gives all stored items used "views." key.
How we can do same thing with Cache ?
function get_all_cache(){
$filesystem = \Cache::getStore()->getFilesystem();
$cache_dir = (\Cache::getDirectory());
$keys = [];
foreach ($filesystem->allFiles($cache_dir) as $file1) {
if (is_dir($file1->getPath())) {
foreach ($filesystem->allFiles($file1->getPath()) as $file2) {
$keys = array_merge($keys, [$file2->getRealpath() => unserialize(substr(\File::get($file2->getRealpath()), 10))]);
}
}
}
return $keys;
}

not proper answer but i give u my best answer
try like this
function get_all_cache(){
if(\Cache::has('viewsValue')) {
$keys = \Cache::get('viewsValue');
}else {
$filesystem = \Cache::getStore()->getFilesystem();
$cache_dir = (\Cache::getDirectory());
$keys = [];
foreach ($filesystem->allFiles($cache_dir) as $file1) {
if (is_dir($file1->getPath())) {
foreach ($filesystem->allFiles($file1->getPath()) as $file2) {
$keys = array_merge($keys, [$file2->getRealpath() => unserialize(substr(\File::get($file2->getRealpath()), 10))]);
}
}
}
\Cache::put('viewsValue',$keys,60); ///add key array into cache
}
return $keys;
}
note first time if key is not exists then store cache values on keys next
time always get on cache so better performance
only work if not updated your keys array every time
for more cache understanding see

Related

How to display unique results from an array with two conditions

In $data I have the following values:
Result
[{"id":2,"author":"example#mail.com","id_orders":502},
{"id":2,"author":"example#mail.com","id_orders":503},
{"id":2,"author":"example#mail.com","id_orders":505},
{"id":3,"author":"second-example#mail.com","id_orders":502},
{"id":3,"author":"second-example#mail.com","id_orders":503},
{"id":3,"author":"second-example#mail.com","id_orders":505},
{"id":4,"author":"third-example#mail.com","id_orders":502},
{"id":4,"author":"third-example#mail.com","id_orders":503},
{"id":4,"author":"third-example#mail.com","id_orders":505}]
I want unique results for id and id_orders. I want 3 out of these 9 results. I have tried this, but it helps on one id_orders condition.
PHP code
$result = json_decode($data, true);
$unique_array = [];
foreach($result as $element) {
$hash = $element['id_orders'];
$unique_array[$hash] = $element;
}
$data = array_values($unique_array);
Do you know how it can be different to make it work for two?
You can do it by keeping track of the values that were already used. Disclaimer: this solution will only produce a clear result for cases where the number of unique values for both criteria is the same.
$uniqueArray = [];
$usedValues = [
'id' => [],
'id_orders' => [],
];
foreach ($result as $element) {
if (!in_array($element['id'], $usedValues['id']) && !in_array($element['id_orders'], $usedValues['id_orders'])) {
$uniqueArray[] = $element;
$usedValues['id'][] = $element['id'];
$usedValues['id_orders'][] = $element['id_orders'];
}
}
Basically, what's happening here is that we're using $usedValues to store all the unique values we've already used and comparing against it using in_array. When we iterate through the objects, any object with an id or id_orders that has already been used will be skipped. The pairings will be done in order of appearance in the array.
I've gone an extra mile to try and make this code a bit more generic:
* Finds elements with a unique combination of values under given keys.
*
* Assumes all elements in the array are arrays themselves and that the
* subarrays have the same structure. Assumes subarray elements are not
* objects (uses strict comparison).
*/
function uniqueCombination(array $arrayToFilter, array $keysToFilterOn): array
{
if (empty($arrayToFilter) || empty($keysToFilterOn)) {
throw new \InvalidArgumentException(
'Parameters of uniqueCombination must not be empty arrays'
);
}
// get the keys from the first element; others are assumed to be the same
$keysOfElements = array_keys(reset($arrayToFilter));
$keysPresentInBoth = array_intersect($keysToFilterOn, $keysOfElements);
// no point in running the algorithm if none of the keys are
// actually found in our array elements
if (empty($keysPresentInBoth)) {
return [];
}
$result = [];
$usedValues = array_combine(
$keysPresentInBoth,
array_fill(0, count($keysPresentInBoth), [])
);
foreach ($arrayToFilter as $element) {
if (!isAlreadyUsed($usedValues, $element)) {
$result[] = $element;
foreach ($keysPresentInBoth as $keyToUse) {
$usedValues[$keyToUse][] = $element[$keyToUse];
}
}
}
return $result;
}
function isAlreadyUsed(array $usedValues, array $element): bool
{
foreach ($usedValues as $usedKey => $usedValue) {
if (in_array($element[$usedKey], $usedValue)) {
return true;
}
}
return false;
}
In its core, this is the same algorithm, but made dynamic. It allows a variable number of keys to filter on (that's why they're passed separately as an argument), so the $usedValues array is created dynamically (using the first element's keys as its own keys, filled with empty arrays) and all the keys must be compared in loops (hence the separate function to check if an element's value had already been used).
It could probably be tweaked here or there as I haven't tested it thoroughly, but should provide satisfactory results for most structures.

link a value from an array to another in PHP

I'm trying two combine two arrays based on the values names.
Here what I'm trying to do :
$array1 = ("fifa21","pes21","halflife2","carma2");
$array2 = ("fifa21_cover","pes21_cover","halflife2_cover");
I want to loop through both arrays and if value from array1 match value from array 2 it will list both values like this :
fifa21 - fifa21_cover
pes21 - pes21_cover
halflife2 - halflife2_cover
carma2 - default_cover
if not find anything in the array2, a default cover will be used.
Note: the arrays will be filled dynamically based in a scanDir (two different folders search) and the arrays can be sorted differently than shown in the example above.
This code will loop through array1 and check to see if the item cover exists in array2, if it does then it will echo out in the format you wanted.
$array1 = array("fifa21","pes21","halflife2","carma2");
$array2 = array("fifa21_cover","pes21_cover","halflife2_cover");
foreach ($array1 as $item) {
if (in_array($item."_cover", $array2)) {
echo "<p>".$item." - ".$item."_cover</p>\n";
} else {
// use default cover...
}
}
(because it is lunch time and I need to write some code)
Given two arrays:
$array1 = ["fifa21", "pes21", "halflife2", "carma2"];
$array2 = ["fifa21_cover", "pes21_cover", "halflife2_cover"];
A function such as this can walk through and look for items that start with those values:
function merge_arrays(array $array1, array $array2): array
{
$output = [];
array_walk(
$array1,
static function ($key) use ($array2, &$output) {
$items = array_filter($array2, static fn($f) => 0 === mb_strpos($f, $key));
if (count($items) === 1) {
$output[$key] = reset($items);
return;
}
if (count($items) === 0) {
$output[$key] = 'default_cover';
return;
}
throw new RuntimeException('More than one item found starting with key ' . $key);
}
);
return $output;
}
When called as:
print_r(merge_arrays($array1, $array2));
It will output:
(
[fifa21] => fifa21_cover
[pes21] => pes21_cover
[halflife2] => halflife2_cover
[carma2] => default_cover
)
For your use-case, it might be overly complicated when compared to a for loop, but it does the job.
Another version that more-blindly assumes only a one-to-one match could use the ?? operator for a null check, although I wouldn't recommend this. The more terse and compact that code looks, the more I find that it is usually very hard to reason about, especially in the future:
function merge_arrays(array $array1, array $array2): array
{
$output = [];
array_walk(
$array1,
static function ($key) use ($array2, &$output) {
$output[$key] = array_filter($array2, static fn($f) => 0 === mb_strpos($f, $key))[0] ?? 'default_cover';
}
);
return $output;
}
All code snipping provided works, however if the array values have extension it always assumes the default cover. I can figure it how using my code by removing the extension for compare purpose, and then I add it back.
Inside my loop I use this :
$keyvaluetemp = substr($keyvalue, 0, strrpos($keyvalue, "."));
the above it inside my first ForEach (where I check the first array), and then in the covers array I remove the "_cover" by nothing :
$keyvalue2temp = (str_replace("_cover", "",$keyvalue2));
then I use the following code inside the second ForEach to add the data to a DB:
// if fantart match the game file name so we associate it to the game and save to the DB
if ( stripos ( $keyvalue2temp , $keyvaluetemp ) !== FALSE )
{
$sql = "UPDATE listgames SET FanArt='$keyvalue2' WHERE Name='$keyvalue'";
$con->exec($sql);
}
// if fanart is empty we add a default picture
$checkifempty = "SELECT `FanArt` FROM `listgames` WHERE `Name` = '$keyvalue'";
$runsql = $con->query($checkifempty);
$row = $runsql->fetch(PDO::FETCH_ASSOC);
$fanartkey = $row['FanArt'];
if($fanartkey == '')
{
$sql = "UPDATE listgames SET FanArt='nopic.JPG' WHERE Name='$keyvalue'";
$con->exec($sql);
}
Later in my code I print the results from the DB. I don't know if this is the best approach, however it does exactly what I want :)

Merging two queries to one JSON object

I have two queries:
1) $result = $this->_db->get_where("wishes",array("is_open"=>1))->result_array();
2) $requirements_result = $this->_db->get("requirements")->result_array();
I'm trying to output the data in this JSON format:
{
[
{
id:12,
title:"Meet Messi",
image_url:"http://dsadsa.dsadsa",
previewImageUrl:"http://kdjfla.com"
is_open:"true"
requirements: [
{
id: 123,
title:"kiss Messi",
is_complete: true
}
]
}
]
}
}
I created two models (one for each query).
This is what I've done so far:
$result = $this->_db->get_where("wishes",array("is_open"=>1))->result_array();
$requirements_result = $this->_db->get("requirements")->result_array();
$return_array = array();
foreach ($result as $value)
{
$wishes_model = new wishes_model();
$wishes_model->init_wishes($value);
$return_array[] = $wishes_model;
}
return $return_array;
How to i insert the requirements result to create this JSON?
First, create your wishes array as an associative array, with the ID as the key:
$wishes_array = array();
foreach ($results as $value) {
$wishes_model = new wishes_model();
$wishes_model->init_wishes($value);
$wishes_array[$value['id']] = $wishes_model;
}
Then you can add the requirements to the appropriate wish:
foreach ($requirements_results as $req) {
$wishes_array[$req['wish_id']]->requirements[] = $req;
}
I'm making some assumptions about which things in your application are associative arrays versus objects. You should be able to adjust this to match your specific implementation.
I have couple of question but for now i am gonna guess.
You can try array_merge but it will overwrite same keys.
If you don't want that you can add prefix to keys and then merge both array.
And i think rest of the solutions you already have in here.
Hi like you have 2 results say result1 and result2
you can make 2 foreach loop for each and store them in two different array and then
you make pass it in result and encode it.
see how it works:
foreach ($result1 as $res)
{
$result_s1[]=$res;
}
foreach($result2 as $cmd)
{
result_s1[]=$cmd;
}
$resultdata[]=array_merge($result_s1,$result_s2)

Split a string to form multidimensional array keys?

I'm creating JSON encoded data from PHP arrays that can be two or three levels deep, that look something like this:
[grandParent] => Array (
[parent] => Array (
[child] => myValue
)
)
The method I have, which is simply to create the nested array manually in the code requires me to use my 'setOption' function (which handles the encoding later) by typing out some horrible nested arrays, however:
$option = setOption("grandParent",array("parent"=>array("child"=>"myValue")));
I wanted to be able to get the same result by using similar notation to javascript in this instance, because I'm going to be setting many options in many pages and the above just isn't very readable, especially when the nested arrays contain multiple keys - whereas being able to do this would make much more sense:
$option = setOption("grandParent.parent.child","myValue");
Can anyone suggest a way to be able to create the multidimensional array by splitting the string on the '.' so that I can json_encode() it into a nested object?
(the setOption function purpose is to collect all of the options together into one large, nested PHP array before encoding them all in one go later, so that's where the solution would go)
EDIT: I realise I could do this in the code:
$options['grandparent']['parent']['child'] = "myValue1";
$options['grandparent']['parent']['child2'] = "myValue2";
$options['grandparent']['parent']['child3'] = "myValue3";
Which may be simpler; but a suggestion would still rock (as i'm using it as part of a wider object, so its $obj->setOption(key,value);
This ought to populate the sub-arrays for you if they haven't already been created and set keys accordingly (codepad here):
function set_opt(&$array_ptr, $key, $value) {
$keys = explode('.', $key);
// extract the last key
$last_key = array_pop($keys);
// walk/build the array to the specified key
while ($arr_key = array_shift($keys)) {
if (!array_key_exists($arr_key, $array_ptr)) {
$array_ptr[$arr_key] = array();
}
$array_ptr = &$array_ptr[$arr_key];
}
// set the final key
$array_ptr[$last_key] = $value;
}
Call it like so:
$opt_array = array();
$key = 'grandParent.parent.child';
set_opt($opt_array, $key, 'foobar');
print_r($opt_array);
In keeping with your edits, you'll probably want to adapt this to use an array within your class...but hopefully this provides a place to start!
What about $option = setOption("grandParent", { parent:{ child:"myValue" } });?
Doing $options['grandparent']['parent']['child'] will produce an error if $options['grandparent']['parent'] was not set before.
The OO version of the accepted answer (http://codepad.org/t7KdNMwV)
$object = new myClass();
$object->setOption("mySetting.mySettingsChild.mySettingsGrandChild","foobar");
echo "<pre>".print_r($object->options,true)."</pre>";
class myClass {
function __construct() {
$this->setOption("grandparent.parent.child","someDefault");
}
function _setOption(&$array_ptr, $key, $value) {
$keys = explode('.', $key);
$last_key = array_pop($keys);
while ($arr_key = array_shift($keys)) {
if (!array_key_exists($arr_key, $array_ptr)) {
$array_ptr[$arr_key] = array();
}
$array_ptr = &$array_ptr[$arr_key];
}
$array_ptr[$last_key] = $value;
}
function setOption($key,$value) {
if (!isset($this->options)) {
$this->options = array();
}
$this->_setOption($this->options, $key, $value);
return true;
}
}
#rjz solution helped me out, tho i needed to create a array from set of keys stored in array but when it came to numerical indexes, it didnt work. For those who need to create a nested array from set of array indexes stores in array as here:
$keys = array(
'variable_data',
'0',
'var_type'
);
You'll find the solution here: Php array from set of keys

Patterns for building multidimensional array with unique key

Problem:
Extract data from an object/array and represent this data using a multidimensional array with a unique key generated from the inner loop.
I always find myself building multidimensional arrays like this:
$final_array = array();
foreach ($table as $row) {
$key = null;
$data = array();
foreach ($row as $col => $val) {
/* Usually some logic goes here that does
some data transformation / concatenation stuff */
if ($col=='my_unique_key_name') {
$key = $val;
}
$data[$col] = $val;
}
if (!is_null($key) {
if (!isset($final_array[$key]) {
$final_array[$key] = array();
}
$final_array[$key][] = $data;
}
}
I can't help but wonder if I'm constantly doing this out of habit, but it feels kind of verbose with all the key-checking and whatnot. Is there a native function I am not utilizing? Can this be refactored into something more simple or am I overthinking this?
Why are you always doing that? Doesn't seem the common kind of stuff one works with on a day to day basis... Anyway, that's kinda cryptic (an example would be nice) but have you though of using an MD5 hash of the serialized dump of the array to uniquely define a key?
$key = md5(serialize($value));

Categories