I am wanting to Phockito (PHP version of Mockito) mock a specific journey with my function that takes an array as an argument...
How would I use Hamcrest matchers to specify just one of the properties of said array?
The function in question looks like this:
function getStuff($path) {
$arr = [
'requestUri' => self::BASE_URI . $path,
...
];
return doMoreStuff($arr);
}
I am wanting to specify a Phockito route for a doMoreStuff mock that uses a specific path within the requestUri property.
I have looked at using arrayContaining:
Phockito($myMock)->doMoreStuff(
arrayContaining(['requestUri' => containsString('some-path')])
)->returns('some value);
but this doesn't seem to work..
Related
I have arrays like this
$InternetGatewayDevice['DeviceInfo'][0]['SoftwareVersion'][1]['_value']
and also like this
$InternetGatewayDevice['DeviceInfo'][1]['SoftwareVersion'][2]['_value']
actually, both of them return same value, which is the software version for the router, but because routers belong to different vendors, I have that problem, so
actually, I want to know the path that I have to go in, in order to get my value
so I want to have somethings like this
InternetGatewayDevice.DeviceInfo.0.SoftwareVersion.1._value
as a string
I mean I want a function where I can provide to it the array and the key ,so the function will return to me the path of the array that I have to follow in order to get the value like this
getpath($array,"SoftwareVersion")
whhich will return value like this
InternetGatewayDevice.DeviceInfo.0.SoftwareVersion
are there any way to do this in php ?or laravel package
or is there any way in PHP to get the value whatever the number key is?
I mean like this
$InternetGatewayDevice['DeviceInfo'][*]['SoftwareVersion'][*]
so what ever the key it will return the value
You could try to use he data_get helper function provided by Laravel.
public function getSoftwareVersion(array $data, int $deviceInfoIndex, int $softwareVersionIndex)
{
$index = "DeviceInfo.{$deviceInfoIndex}.SoftwareVersion.{$softwareVersionIndex}";
return data_get($data, $index);
}
Then it can be used like
$softwareVersion = getSoftwareVersion($internetGatewayDevice, 1, 0);
Laravel Docs - Helpers - Method data_get
you can use the get function from lodash php
https://github.com/lodash-php/lodash-php
Example:
<?php
use function _\get;
$sampleArray = ["key1" => ["key2" => ["key3" => "val1", "key4" => ""]]];
get($sampleArray, 'key1.key2.key3');
// => "val1"
get($sampleArray, 'key1.key2.key5', "default");
// => "default"
get($sampleArray, 'key1.key2.key4', "default");
// => ""
A library I use uses an array. Applying print_r to that array prints this:
Array
(
[*queueId] => 1
[*handle] => 9b875867b36d568483fb35fdb8b0bbf6
[*body] => First string in the TestQueue
[*md5] => c23ba714199666efbc1dcd5659bb0a0a
[*timeout] => 1408003330.6534
[*id] => 2
[*creationdate] => 2014-08-13 16:03:37
)
The library uses a magic getter on that array
public function __get($key)
{
if (!array_key_exists($key, $this->_data)) {
throw new Exception\InvalidArgumentException("Specified field \"$key\" is not in the message");
}
return $this->_data[$key];
}
When I try to access
$myObject->body
I run into the exception. In fact, the debugger shows that array_key_exists will return false while the _data array is available as printed above
The asterisk indicates that this array is a representation of an object, probably the original object property is protected.
http://php.net/manual/en/language.types.array.php#language.types.array.casting
As I explained in the comments, the array keys actually start with an asterisk. Since you can't call them using the regular syntax of $obj->*body (it'll cause a syntax error), you can use the following:
$myObject->{'*body'}
This should solve your problem.
Assuming that $myObject is the array you are talking from:
You can't access arrays with ->, use $myObject['*body'] instead. (And you should as well change the name to $myArray, for example)
As #MarkBaker stated in the comment of my question, the problem was that I was serializing an object with private properties to the array. The asterisk were marks that these properties were private.
I'd like to exclude results from a call to a Lithium model's find() method. I need to do this for models with both MongoDB and MySQL data sources, but in SQL I mean something like WHERE myfield NOT IN (1,2,3).
I'd like to just be able to pass a not clause in the conditions array like below, but that doesn't appear to be possible.
Item::all(array('conditions' => array('not' => array('myfield' => array(1,2,3))));
So my question is, is this possible in Lithium in a way that I've overlooked? And if not, what would be the most Lithium-ish way to implement it for my models?
Just to clarify, Lithium's MongoDB adapter supports most SQL comparison operators as a convenience, so for either Mongo or MySQL, you could simply write the query as follows:
Item::all(array('conditions' => array(
'myfield' => array('!=' => array(1,2,3))
)));
And it should give you the results you expect. For MySQL, the query should look something like:
SELECT * FROM items WHERE myfield NOT IN (1, 2, 3);
And in Mongo:
db.items.find({ myfield: { $nin: [1, 2, 3] }})
Merely filtering for MongoDB can easily be achieved like this:
Item::all(array('conditions' =>
array('myfield' => array(
'$nin' => array(1,2,3)
))
));
If this is something you do a lot you could even create a custom finder for it :
class MyModel extends \lithium\data\Model {
public static function __init()
{
parent::__init();
static::finder('notin', function($self, $params, $chain) {
// Take all array keys that are not option keys
$array = array_diff_key($params['options'],
array_fill_keys(array('conditions', 'fields','order','limit','page'),0));
// Clean up options leaving only what li3 expects
$params['options'] = array_diff_key($params['options'], $array);
$params['options']['conditions'] = array(
'myfield' => array(
'$nin' => $array
)
);
return $chain->next($self, $params, $chain);
});
}
}
And call it like this :
MyModel::notin(array(1,2,3));
In the same manner you could create a custom finder for MySQL sources.
As you probably can see this creates some issues if you pass something like array('fields'=>$array) as it would overwrite the option.
What happens is that ::notin() (finders in general) has a distinct behavior for the (array,null) signature. If that happens it thinks the first array is options and the finder took no arguments.
Using notin($array,array()) breaks the previous finder because the first argument ends up in $params['notin'] when the real second argument (options) is passed.
If you mix data sources on the fly here I would create a custom model that does not inherit \lithium\data\Model and have it delegate
to the different models and create the conditions based on the end models data source.
class MyFacadeModel {
public static function byNotIn($conditions, $source) {
return ($source == "mongodb")
? $source::find( $rewrittenConditions)
: $source::find( $rewrittenConditionsForMysql );
}
}
(Code might be slightly incorrect as its mostly taken from the top of my head)
I know it is possible to use optional arguments as follows:
function doSomething($do, $something = "something") {
}
doSomething("do");
doSomething("do", "nothing");
But suppose you have the following situation:
function doSomething($do, $something = "something", $or = "or", $nothing = "nothing") {
}
doSomething("do", $or=>"and", $nothing=>"something");
So in the above line it would default $something to "something", even though I am setting values for everything else. I know this is possible in .net - I use it all the time. But I need to do this in PHP if possible.
Can anyone tell me if this is possible? I am altering the Omnistar Affiliate program which I have integrated into Interspire Shopping Cart - so I want to keep a function working as normal for any places where I dont change the call to the function, but in one place (which I am extending) I want to specify additional parameters. I dont want to create another function unless I absolutely have to.
No, in PHP that is not possible as of writing. Use array arguments:
function doSomething($arguments = array()) {
// set defaults
$arguments = array_merge(array(
"argument" => "default value",
), $arguments);
var_dump($arguments);
}
Example usage:
doSomething(); // with all defaults, or:
doSomething(array("argument" => "other value"));
When changing an existing method:
//function doSomething($bar, $baz) {
function doSomething($bar, $baz, $arguments = array()) {
// $bar and $baz remain in place, old code works
}
Have a look at func_get_args: http://au2.php.net/manual/en/function.func-get-args.php
Named arguments are not currently available in PHP (5.3).
To get around this, you commonly see a function receiving an argument array() and then using extract() to use the supplied arguments in local variables or array_merge() to default them.
Your original example would look something like:
$args = array('do' => 'do', 'or' => 'not', 'nothing' => 'something');
doSomething($args);
PHP has no named parameters. You'll have to decide on one workaround.
Most commonly an array parameter is used. But another clever method is using URL parameters, if you only need literal values:
function with_options($any) {
parse_str($any); // or extract() for array params
}
with_options("param=123&and=and&or=or");
Combine this approach with default parameters as it suits your particular use case.
I am a total NOOB in programming (but this is only my second question on stackoverflow :-) ).
By a foreach function I get 5 different string values for $Loncoord, $Latcoord, $gui;
this I can see with the print_r in the code written below:
"-5.68166666667","+24.6513888889","IMG_3308",
But I now want to create 5 different markers in the $map->addMarkerByCoords (function is it ?).
print_r ("$Loncoord");
print_r ("$Latcoord");
print_r ("$gui");
$map->addMarkerByCoords("$Loncoord","$Latcoord","$gui",'OldChicago');
Is this possible?
Do I need to put them in a array and call these in the (function ?) or do I need to use a foreach function?
I tried both for a week now but I can't get it working.
Can you help me?
The answers you produced gave me a turn in the right direction.
Thank you for the quick responses and the explaining part.
But for the addMarkerByCoord (function! (stupid me)) I found this in the googlemaps API:
function addMarkerByCoords($lon,$lat,$title = '',$html = '',$tooltip = '') {
$_marker['lon'] = $lon;
$_marker['lat'] = $lat;
$_marker['html'] = (is_array($html) || strlen($html) > 0) ? $html : $title;
$_marker['title'] = $title;
$_marker['tooltip'] = $tooltip;
$this->_markers[] = $_marker;
$this->adjustCenterCoords($_marker['lon'],$_marker['lat']);
// return index of marker
return count($this->_markers) - 1;
}
It depends on the implementation of map::addMarkerByCoords()
The method (not a function) name, and its signature, suggests that you are only able to add one coord at a time. But to be sure you'ld need to know the methods true signature. So the question is: does the method allow arrays as arguments?
Usually, a method that allows you to add multiple items at once, has the plural name of the intended action in it's name:
map::addMarkersByCoords() // note the s after Marker
If the 'map' class is your own implementation, you are free to implement it the way you like of course, but in that case keep the descriptive names of the methods in mind. So, add one marker:
map::addMarkerByCoords()
Add multiple markers at once:
map::addMarkersByCoords()
Typically you would implement the plural method as something like this:
public function addMarkersByCoords( array $markers )
{
foreach( $markers as $marker )
{
$this->addMarkerByCoord( $marker[ 'long' ], $marker[ 'lat' ], $marker[ 'img ' ], $marker[ 'name' ] );
}
}
Basically, the plural method accepts one array, and adds each individual marker by calling the singular method.
If you wanna get even more OOP, you could implement the plural and singular method to accept (an array of) Marker objects. But that is not particalarly relevant for this discussion.
Also, the suggested expantion of the Map's interface with a plural method doesn't nessecarily mean you can't add multiple markers outside the object with calling the singular method in a foreach loop. It's up to your preference really.
If you want to call the addMarkerByCoords for 5 times with 5 different values for each parameter then you can build an array for every parameter and then iterate with the foreach function:
$Loncoord=array(1,2,3,4,5);
$Latcoord=array(1,2,3,4,5);
$gui=array(1,2,3,4,5);
$city=array('OldChicago','bla','bla','bla','bla');
foreach($Loncoord as $k=>$v)
$map->addMarkerByCoords($Loncoord[$k],$Latcoord[$k],$gui[$k],$city[$k]);
Try losing some of the quotes...
$map->addMarkerByCoords($Loncoord,$Latcoord,$gui,'OldChicago');
To answer the question properly though, we would need to know what addMarkerByCoords was expecting you to pass to it.