Storing time in array - php

I have some code that stores values in an array. It all seems to work but I also want to store the time that each value is added to the array (as part of the array) The code stores only unique values to a maximum of four.
function getBand() {
$band_name=$_GET['band_name'];
return $band_name;
}
$pages=$_SESSION['pages'];
if(in_array($_GET['band_name'], $pages)) {
echo"Already in Array";
} else {
if (empty($_SESSION['pages']))
$_SESSION['pages'] = array();
$_SESSION['pages'][] = getBand();
$_SESSION['pages'] = array_slice($_SESSION['pages'], -4);
}

Use time () to get the time.
And store that in the desired array.
array_push ($array, time ());
Since you're talking about "the time they are added to the array" it could be that you mean microseconds which in that case use microtime ()
Note that both functions don't return a formatted timestamp, instead they return an integer.
More on time () here
More on microtime () here

Maybe something like this could do the work:
$test = "Metallica";
$test2 = "The Black Keys";
$arr['pages'][$test] = $test;
$arr['pages'][$test] = date("D M d, Y G:i");
$arr['pages'][$test2] = $test;
$arr['pages'][$test2] = date("D M d, Y G:i");
echo '<pre>'.print_r($arr, true).'</pre>';
For date format you can see - http://php.net/manual/bg/function.date.php
Cheers

class SessionManager
{
protected static $pages = null;
protected static $maxPages = 4;
public function __construct($session) {
self::$pages = $session['pages'];
}
public static function addPage($pageName) {
self::$pages[$pageName] = array(
'name' => $pageName,
'created' => date('Y-m-d h:i:s')
);
self::$pages = array_slice(self::$pages, -1 * $maxPages);
}
public static function writeSession(&$session) {
$session['pages'] = self::$pages;
}
public static function getPages() {
return self::$pages;
}
}
session_start();
$session = new SessionManager($_SESSION);
$session->addPage($_GET['band_name']);
$session->writeSession($_SESSION);
print_pre($session->getPages());

Related

How Can we pass function parameter as another function which itself has different parameters?

I have function below :
function cache_activity_data($cid,$somefunction) {
$cache_time = '+15 minutes';
$cache_id = $cid;
$expire = strtotime($cache_time);
$cache = cache_get($cache_id);
if (!empty($cache->data)) {
if (time() > $cache->expire) {
cache_clear_all($cache_id, 'cache_custom_activity_dashboard');
$report = $somefunction; // will get from function
cache_set($cache_id, $report, 'cache_custom_activity_dashboard', $expire);
}
else {
$report = $cache->data;
}
}
else {
$report = $somefunction; // will get from function
cache_set($cache_id, $report, 'cache_custom_activity_dashboard', $expire);
}
return $report;
}
Now $somefunction can be like below examples :
total_comments_per_user($user->uid);
total_comments_per_user_time_limit($user->uid, $user_year_start);
total_revisions_time_limit($month_ago);
total_revisions_time_limit($year_start);
every time I need to pass like 20 different functions. Is that possible I am getting error as at place of varibales I am passing function But I am not able to figure is that possible.
How I want to use :
//want to write this as function
$cache_revisions_total = cache_get("total_revisions", "cache_custom_activity_dashboard");
if (!empty($cache_revisions_total->data)) {
if (time() > $cache_revisions_total->expire) {
cache_clear_all("total_revisions", 'cache_custom_activity_dashboard');
$t_revisions = total_revisions();
cache_set("total_revisions", $t_revisions, 'cache_custom_activity_dashboard', $expire);
}
else {
$t_revisions = $cache_revisions_total->data;
}
}
else {
$t_revisions = total_revisions();
cache_set("total_revisions", $t_revisions, 'cache_custom_activity_dashboard', $expire);
}
// want to write this as function end here
$vars['total_bubbla_rev'] = number_format(($t_revisions / $days_from_rev_start), 2, '.', '');
// here i want to do same so i need to write function or should i repeat code
$y_revisions = total_revisions_time_limit($year_start);
$vars['yearly_bubbla_rev'] = number_format(($y_revisions / $year_days), 2, '.', '');
// here i want to do same so i need to write function or should i repeat code
$m_revisions = total_revisions_time_limit($month_ago);
$vars['monthly_bubbla_rev'] = number_format(($m_revisions / 30), 2, '.', '');
Please suggest, Thanks!
I see two possible options.
Option 1
You could use Anonymous functions. I simplified your function but you'll get the idea:
function cache_activity_data($cid, $somefunction) {
$report = $somefunction();
}
Define your functions as anonymous functions:
$parm1 = "banana";
$parm2 = "fruit";
$your_function1 = function() use ($parm1, $parm2) {
echo "$parm1 is a $parm2";
};
$your_function2 = function() use ($parm1) {
echo $parm1;
};
Usage:
cache_activity_data($cid, $your_function1); // shows "banana is a fruit"
cache_activity_data($cid, $your_function2); // shows "banana"
Read carefully through the documentation. Especially the part about variable scopes.
Option 2
Another possibility is call_user_func_array() but this requires you to make a little adjustment to cache_activity_data(). You need to add a third parameter which holds an array:
function cache_activity_data($cid, $somefunction, $somefunction_parms) {
$report = call_user_func_array($somefunction, $somefunction_parms);
}
Define your functions as usual:
function your_function1($parm1, $parm2) {
echo "$parm1 is a $parm2";
}
function your_function2($parm) {
echo $parm;
}
Usage
cache_activity_data($cid, "your_function1", array("banana", "fruit")); // shows "banana is a fruit"
cache_activity_data($cid, "your_function2", array("banana")); // shows "banana"
First, you cannot pass functions as parameters, however you can use callbacks as explained here:
http://php.net/manual/en/language.types.callable.php
But in your case, this seems irrelevant as you are not determining the function or changing its value in cache_activity_data().
Therefore, you might want to do like this:
$reportDefault = total_comments_per_user($user->uid);
// Or ... $reportDefault = total_revisions_time_limit, total_comments_per_user_time_limit, etc..
$report = cache_activity_data($cid, $reportDefault);
You do not need to add pass $report or any function as parameter.

Generating a php object, two levels deep

I'm new to php - objects and arrays, especially. Coming from a JavaScript world, I'm having a modicum of trouble understanding the right way to construct objects, that may easily be iterated.
I'd like to create an object (or array - although I suspect an object would be more suitable) with the following structure:
$client_body:
$cst:
$title: 'Unique string'
$copy: function_result()
$ser:
$title: 'Unique string'
$copy: function_result()
$imp
$title: 'Unique string'
$copy: function_result()
...
I've been trying with variations on the following, but with numerous errors:
$client_body = new stdClass();
$client_body->cst->title = 'Client case study';
$client_body->cst->copy = get_field('client_cst');
$client_body->ser->title = 'Our service';
$client_body->ser->copy = get_field('client_ser');
...
And it seems that, using this approach, I'd have to use a new stdClass invocation with each new top-level addition, which seems a little verbose.
Could someone point me in the right direction?
You can just typecast an array to an object:
$client_body = (object)array(
"cst" => (object)array(
"title" => "Unique string",
"copy" => function_result()
)
);
You can try this object class more OOP:
<?php
class ClientBody{
protected $cst;
protected $ser;
protected $imp;
public function __construct($cst = '', $ser ='', $imp = '')
{
$this->cst = $cst;
$this->ser = $ser;
$this->imp = $imp;
}
public function getCst()
{
return $this->cst;
}
public function getSer()
{
return $this->ser;
}
public function getImp()
{
return $this->imp;
}
public function setCst($value)
{
$this->cst = $value;
}
public function setSer($value)
{
$this->ser = $value;
}
public function setImp($value)
{
$this->imp = $value;
}
}
$myObject = new ClientBody('toto', 'titi', 'tata');
echo $myObject->getCst(); // output 'toto'
echo $myObject->getSer(); // output 'titi'
echo $myObject->getImp(); // output 'tata'
Or you could use json_decode($client_body, TRUE);

Yii2 MongoDB query not working

I was using MySQL for my db before and moved to using MongoDB just recently. I have been converting my queries to MongoDB format then I encountered a problem along the way.
I wanted to get the payslip_id of a specific user where date_generated (of the payslip) is in between the start and end dates of a specific payroll period. Here's the original query (MySQL):
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => 'user_id'])->where('date_generated BETWEEN :start_time AND :end_time', array(':start_time' => $session['start'], ':end_time' => $session['end']));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->payslip_id : '';
}
Now, here's my converted query to MongoDB:
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => '_id'])->where(array('date_generated' => array('$in' => array($session['start'], $session['end']))));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->_id : '';
}
Notice the return statements are different. I wonder if my MongoDB query is correct or not. It doesn't return any error as well.
I would really appreciate your response.
The $in operator selects the documents where the value of a field equals any value in the specified array. It is not equivalent to MySQLBETWEEN.
Use $gte and $lte operators.
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => '_id'])->where(array('date_generated' => array('$gte' => $session['start']), 'date_generated' => array('$lte' => $session['end'])));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->_id : '';
}
I am not sure about the syntax of php-mongodb but I think this should help.

How to Promote certain elements to the start of an array in PHP

If certain elements are contained in an array, I want them moved to the start of it.
At first I used a bunch of array_diff_keys to get it to work, but I wanted something more elegant. So I tried using uksort with a callback, but perhaps I'm doing it wrong because it's not working.
I tried this, it's a method of my helper class, but it's not working.
$good_elements = array('sku','name','type','category','larping');
$test_array = array('sku','name','asdf','bad_stuff','larping','kwoto');
$results = helper::arrayPromoteElementsIfExist($test_array,$good_elements,false);
public static function arrayPromoteElementsIfExist($test_array,$promote_elements,$use_keys = false) {
foreach(array('test_array','promote_elements') as $arg) {
if(!is_array($$arg)) {
debug::add('errors',__FILE__,__LINE__,__METHOD__,'Must be array names',$$arg);
return false;
}
}
if(!$use_keys) {
$test_array = array_flip($test_array); // compare keys
$promote_elements = array_flip($promote_elements); // compare keys
}
uksort($test_array,function($a,$b) use($promote_elements) {
$value1 = intval(in_array($a, $promote_elements));
$value2 = intval(in_array($b,$promote_elements));
return $value1 - $value2;
});
if(!$use_keys) {
$test_array = array_flip($test_array);
}
return $test_array;
}
Fairly quick and dirty but here you go.
function promoteMembers($input, $membersToPromote)
{
$diff = array_diff($input, $membersToPromote);
return array_merge($membersToPromote, $diff);
}
Assuming I understood what you wanted to do.
Example output: for your verification.

Refactoring JavaScript and PHP code [Job Interview]

recently I had a job interview. I had two tasks:
1) to refactor a JavaScript code
// The library 'jsUtil' has a public function that compares 2 arrays, returning true if
// they're the same. Refactor it so it's more robust, performs better and is easier to maintain.
/**
#name jsUtil.arraysSame
#description Compares 2 arrays, returns true if both are comprised of the same items, in the same order
#param {Object[]} a Array to compare with
#param {Object[]} b Array to compare to
#returns {boolean} true if both contain the same items, otherwise false
#example
if ( jsUtil.arraysSame( [1, 2, 3], [1, 2, 3] ) ) {
alert('Arrays are the same!');
}
*/
// assume jsUtil is an object
jsUtil.arraysSame = function(a, b) {
var r = 1;
for (i in a) if ( a[i] != b[i] ) r = 0;
else continue;
return r;
}
2) To refactor a PHP function that checks for a leap year
<?php
/*
The class 'DateUtil' defines a method that takes a date in the format DD/MM/YYYY, extracts the year
and works out if it is a leap year. The code is poorly written. Refactor it so that it is more robust
and easier to maintain in the future.
Hint: a year is a leap year if it is evenly divisible by 4, unless it is also evenly
divisible by 100 and not by 400.
*/
class DateUtil {
function notLeapYear ($var) {
$var = substr($var, 6, 4);
if (! ($var % 100) && $var % 400) {
return 1;
}
return $var % 4;
}
}
$testDates = array('03/12/2000', '01/04/2001', '28/01/2004', '29/11/2200');
/* the expected result is
* 03/12/2000 falls in a leap year
* 01/04/2001 does not fall in a leap year
* 28/01/2004 falls in a leap year
* 29/11/2200 does not fall in a leap year
*/
?>
<? $dateUtil = new DateUtil(); ?>
<ul>
<? foreach ($testDates as $date) { ?>
<li><?= $date ?> <?= ($dateUtil->notLeapYear($date) ? 'does not fall' : 'falls') ?> in a leap year</li>
<? } ?>
</ul>
I think I cope with the task but I am not quite sure, I still don't have an answer from them and it's been about a week. Could you give an example of your approach to this tasks? I'd really appreciate. Later I can post my solutions/code.
OK here are my answers to the questions.
<?php // Always use full/long openning tags not
$start = microtime(true);
class DateUtil {
/**
* The date could be used in other
* class methods in the future.
* Use just internally.
**/
var $_date;
/**
* The constructor of the class takes
* 1 argument, date, as a string and sets
* the object parameter _date to be used
* internally. This is compatable only in PHP5
* for PHP4 should be replaced with function DateUtil(...)
*/
public function __construct( $date = '' ) {
$this->_date = $date;
}
/**
* Setter for the date. Currently not used.
* Also we could use _set magical function.
* for PHP5.
**/
public function setDate( $date = '' ) {
$this->_date = $date;
}
/**
* Gettre of the date. Currently not used.
* Also we could use _get magical function.
* for PHP5.
**/
public function getDate() {
return $this->_date;
}
public function isLeapYear( $year = '' ) {
// all leap years can be divided through 4
if (($year % 4) != 0) {
return false;
}
// all leap years can be divided through 400
if ($year % 400 == 0) {
return true;
} else if ($year % 100 == 0) {
return false;
}
return true;
}
}
$dates = array('03/12/2000', '01/04/2001', '30/01/2004', '29/11/2200');
$dateUtil = new DateUtil();
foreach($dates as $date) {
/**
* This processing is not done in the class
* because the date format could be different in
* other cases so we cannot assume this will allways
* be the format of the date
*
* The php function strtotime() was not used due to
* a bug called 2K38, more specifically dates after and 2038
* are not parsed correctly due to the format of the UNIX
* timestamp which is 32bit integer.
* If the years we use are higher than 1970 and lower
* than 2038 we can use date('L', strtotime($date));
**/
$year = explode('/', $date);
$year = $year[2];
$isLeap = $dateUtil->isLeapYear($year);
echo '<pre>' . $date . ' - ';
echo ($isLeap)? 'Is leap year': 'Is not leap year';
echo '</pre>';
}
echo 'The execution took: ' . (microtime(true) - $start) . ' sec';
?>
JavaScript
/***************************************************/
jsUtil = new Object();
jsUtil.arraysSame = function(a, b) {
if( typeof(a) != 'object') {
// Check if tepes of 'a' is object
return false;
} else if(typeof(a) != typeof(b)) {
// Check if tepes of 'a' and 'b' are same
return false;
} else if(a.length != b.length) {
// Check if arrays have different length if yes return false
return false;
}
for(var i in a) {
// We compare each element not only by value
// but also by type so 3 != '3'
if(a[i] !== b[i]) {
return false;
}
}
return true;
}
// It will work with associative arrays too
var a = {a:1, b:2, c:3};
var b = {a:1, b:2, c:3}; // true
var c = {a:1, b:2, g:3}; // false
var d = {a:1, b:2, c:'3'}; // false
var output = '';
output += 'Arrays a==b is: ' + jsUtil.arraysSame( a, b );
output += '\n';
output += 'Arrays a==c is: ' + jsUtil.arraysSame( a, c );
output += '\n';
output += 'Arrays a==d is: ' + jsUtil.arraysSame( a, d );
alert(output);
Iterate arrays using a for loop rather than for...in. If the arrays are different, you want to return as quickly as possible, so start with a length comparison and return immediately you come across an element that differs between the two arrays. Compare them using the strict inequality operator !==. Iterate backwards through the array for speed and to minimise the number of variables required by assigning a's length to i and reusing i as the iteration variable.
This code assumes that the parameters a and b are both supplied and are both Array objects. This seems to be implied by the question.
var jsUtil = jsUtil || {};
jsUtil.arraysSame = function(a, b) {
var i = a.length;
if (i != b.length) return false;
while (i--) {
if (a[i] !== b[i]) return false;
}
return true;
};
For the PHP version:
class DateUtil {
function LeapYear ($var) {
$date = DateTime::CreateFromFormat($var, 'd/m/Y');
return($date->format('L')); // returns 1 for leapyear, 0 otherwise
}
function notLeapYear($var) {
return(!$this->LeapYear($var)) {
}
}
For the first problem maybe I can help you with this:
var jsUtil = jsUtil || {};
jsUtil.arraysSame = function(a, b){
//both must be arrays
if (!a instanceof Array || !b instanceof Array) {
return false;
}
//both must have the same size
if (a.length !== b.length) {
return false;
}
var isEquals = true;
for (var i = 0, j = a.length; i < j; i++) {
if (a[i] !== b[i]) {
isEquals = false;
i = j; //don't use break
}
}
return isEquals;
}
I included type checking and made the things more clear.
In my opinion using built-in predefined functions is always your best bet.
1) Use a function that converts the arrays into strings. There are many of these available and depending on which library you are already using you may want to use different ones. You can find one at Json.org
jsUtil.arraysSame = function(a, b) {
return JSON.stringify(a) == JSON.stringify(b);
}
2) USe PHP's built in date function and strtotime
class DateUtil {
function notLeapYear ($var) {
return (date( 'L', strtotime( $var)) == "0");
}
}
check inputs (type, range - keep in mind that very old dates used a different calendar); you might use PHP date functions to parse date (more flexibility on one hand, limited to relatively recent dates on the other)
never iterate with in in javascript, will fail horribly when prototypes of the standard types have been extended
you should clarify what the functions should do; e.g. should the array comparison be recursive? Should it use strict equivalence?
you can stop iterating the arrays when the first difference is found. Also, you might want to check if the two refer to the same object before starting to iterate.
write unit tests

Categories