Symfony2 form builder, choices multiple, excepted array also on sample code - php

After hours of searching on this forum and google no answer worked.
I have tried more types of array like array of arrays, and simple key => value array.
Also i have tried code for: expanded true, and multiple true at http://symfony.com/doc/current/reference/forms/types/choice.html
I am getting error " Expected an array. 500 Internal Server Error - TransformationFailedException " When i turn on "multiple" I have tried it with array of arrays and key pair array.
What i want is to do and what its doing.
I select videos from database
make conversion
$video = $this->entityManager->getRepository("CMMSHomeBundle:Video")->findAll();
if (!$video)
{
return '0';
}
$video_arr = array();
for ($i = 0; $i < count($video); $i++)
{
//$video_arr[$i]["id"] = $video[$i]->getId();
//$video_arr[$i]["videoid"] = $video[$i]->getVideoid();
$video_arr[$video[$i]->getId()] = $video[$i]->getVideoid();
}
return $video_arr;
print_f if array is correct: Array ( [1] => X-77txuiVXs [5] => uelHwf8o7_U ) OR Array ( [0] => Array ( [id] => 1 [videoid] => X-77txuiVXs ) [1] => Array ( [id] => 5 [videoid] => uelHwf8o7_U ) )
Do the magick
$form = $this->createFormBuilder($product);
$form->add('name', 'text');
$form->add('short', 'textarea');
$form->add("description", "textarea");
$form->add("price", "text");
$form->add("images", "text");
$form->add('videos', 'choice', array(
'choices' => $videos,
'expanded' => true,
'multiple' => true,
)
);
$form->add("files", "text");
$form->add("size", "text");
$form->add("weight", "text");
$form->add("category", "text");
$form->add("active", "text");
$form->add('save', 'submit');
$form->getForm();
$form is chained, i unchained it to get correct formating by this soverflow editor.
It wont work :-( As soon i turn on multiple
Thank you

Related

Compare Data from JSON API thats not listed in numbers format

PHP beginner here.
I want to display compared Data ($myCoins) from a JSON API, so that only those Items will be displayed that I first inserted into the $myCoins arrays, but I can't figure out how to get the code to operate the same with NAMES instead of NUMBERS.
Used API:
https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,XRB,MIOTA,XRP,XLM,TRX&tsyms=USD
CODE:
<?php
//// API
$coinData = json_decode(file_get_contents('https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,XRB,IOTA,XRP,XLM,TRX,LINK&tsyms=USD'), true);
// Arrays
$myCoins = array(
'BTC' => array ( 'balance' => 12.90 ),
'ETH' => array ( 'balance' => 122.23 ),
'XRB' => array ( 'balance' => 221.52 ),
'MIOTA' => array ('balance' => 233.00 ),
'XRP' => array ( 'balance' => 429.00 ),
'XLM' => array ( 'balance' => 1205.89 ),
'TRX' => array ( 'balance' => 5299.40 )
);
// Fetch the Coins
$numCoins = sizeof ($coinData['RAW']);
$portfolioValue = 0;
for ( $xx=0; $xx<$numCoins; $xx++) {
// Comparing to Data
$thisCoinSymbol = $coinData[$xx]['FROMSYMBOL'];
//
$coinHeld = array_key_exists($thisCoinSymbol, $myCoins);
// Only retour held
if ( !$coinHeld ) { continue; }
// names test:
echo $coinData[$xx]['FROMSYMBOL'];
};
?>
The Tutorial I used was made with an API that displays the Items as numbers, not the Item names like in the API I want to use.
Tutorial API:
https://api.coinmarketcap.com/v1/ticker/
So my console puts out a Undefined offset: 0 - Undefined offset: 7 on line $thisCoinSymbol = $coinData[$xx]['FROMSYMBOL']; I understand that this is because $xx equals 0 - 7, because there are 8 Items under ['RAW'], and there is no 0-7 in the API I use.
How would i get the same result as the Tutorial but with the API I want to use?
You should use a foreach to parse your json that is structured like that:
RAW: {
BTC: {
USD: {
TYPE: "5",
MARKET: "CCCAGG",
FROMSYMBOL: "BTC",
....
}
},
ETH: {....},
...
}
So your code should looks like that:
<?php
$coinData = json_decode(file_get_contents('https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,XRB,IOTA,XRP,XLM,TRX,LINK&tsyms=USD'), true);
$myCoins = array(
'BTC' => array ( 'balance' => 12.90 ),
'ETH' => array ( 'balance' => 122.23 ),
'XRB' => array ( 'balance' => 221.52 ),
'MIOTA' => array ('balance' => 233.00 ),
'XRP' => array ( 'balance' => 429.00 ),
'XLM' => array ( 'balance' => 1205.89 ),
'TRX' => array ( 'balance' => 5299.40 )
);
$portfolioValue = 0;
// your information in json path ['RAW'] so safeguard here to be sure it exists
if (isset($coinData['RAW'])) {
// then loop on all entries $cryptoSymbol will contains for example BTC and cryptoInfo the array USD => [...]
foreach($coinData['RAW'] as $cryptoSymbol => $cryptoInfo) {
// safeguard, check path [USD][FROMSYMBOL] exists
if (!isset($cryptoInfo['USD']) || !isset($cryptoInfo['USD']['FROMSYMBOL'])) {
// log or do whatever to handle error here
echo "no path [USD][FROMSYMBOL] found for crypto: " . $cryptoSymbol . PHP_EOL;
continue;
}
// Your symbol in on your json path/array [USD][FROMSYMBOL]
$thisCoinSymbol = $cryptoInfo['USD']['FROMSYMBOL'];
$coinHeld = array_key_exists($thisCoinSymbol, $myCoins);
// Only retour held
if ( !$coinHeld ) { continue; }
echo $cryptoInfo['USD']['FROMSYMBOL'] . PHP_EOL;
}
}
?>
You will have the output:
BTC
ETH
XRB
XRP
XLM
TRX
Now you can parse the json in the right way, it should be easy for you to build the expected json.
Have a look at the foreach doc here: https://www.php.net/manual/en/control-structures.foreach.php

PHP: create subarray based on similar value types

Hello to the community: in the following array, I'd like to gather all the hobbies of the same user under that user's name into a subarray I'd call hobbies.
My current solution is to compare whether the email value is the same for both arrays, and if so, then push the hobby into its own array.
The problem is that the loops seems right but does not produce the results I expect it and I can't see where lies the problem. I thank you all for your time.
for($x = 0; $x <= count($majorArray); $x++) {
if($majorArray[$x]['email'] == $majorArray[$x+1]['email'])
array_push($hobbies, $majorArray[$x]['hobby']);
}
The array:
Array
(
[1] => Array
(
[fname] => Eli
[lname] => Solo
[hobby] => plants
[id] => 1
[email] => elis#elis.com
)
[2] => Array
(
[fname] => Eli
[lname] => Solo
[hobby] => hiking
[id] => 1
[email] => elis#elis.com
)
The problem with your code is that you compare the email of the current contents with the email of the next.
This check does not check if the user is already present, it just checks the next user in the array. This will only work if the next user is also the current, not if there is something in between.
Also, this code will eventually give you an undefined index error, as it will try to fetch the data under the next key in the last iteration.
Also it's not clear where $hobbies is from, according to you explanation, you want to create a hobbies array, and append all data there.
You can try the following (untested):
<?php
$majorArray = [
[
'fname' => 'Eli',
'lname' => 'Solo',
'hobby' => 'plants',
'id' => 1,
'email' => 'elis#elis.com',
],
[
'fname' => 'Eli',
'lname' => 'Solo',
'hobby' => 'hiking',
'id' => 1,
'email' => 'elis#elis.com',
],
];
$output = [];
foreach ($majorArray as $userData) {
// check if email already exists as key, you can also just use id for this
if (!array_key_exists($userData['email'], $output)) {
$newUserData = [
'fname' => $userData['fname'],
'lname' => $userData['lname'],
'id' => $userData['id'],
'email' => $userData['email'],
'hobbies' => [], // create the hobbies array
];
// add the newly created user data array to the output with email as key
$output[$userData['email']] = $newUserData;
}
// append the hobby to the hobbies array
$output[$userData['email']]['hobbies'][] = $userData['hobby'];
}
// array_values will reset the array keys if you need to
print_r(array_values($output));
Simply write a new array and use the ID as key
$betterArray = array();
foreach($majorArray as $data){
$betterArray[$data['id']]['fname'] = $data['fname'];
$betterArray[$data['id']]['lname'] = $data['lname'];
$betterArray[$data['id']]['email'] = $data['email'];
$betterArray[$data['id']]['hobbies'][] = $data['hobby'];
}
notice the [] in the last line in the loop to add a new element to the subarray each time it loops trough

PHP ObjectId group a number of Ids

I have a two collections one of all the people I am following and another of what they have been posting on social networking sites like Twitter and Facebook.
The following collection has a subarray of the _id of the feed collection of each user which each status has the word owner and that has the ObjectId that the owner which is the same as the following key. Here is an example.
'_id' => new MongoId("REMOVED"),
'following' =>
array (
'0' => 'ObjectId("53bf464ee7fda8780c8b4568")',
'1' => 'ObjectId("53b00ab5e7fda8304b8b4567")',
),
'owner' => new MongoId("53b9ea3ae7fda8863c8b4123"),
and in the feed you will see that the following.0 status below
array (
'_id' => new MongoId("REMOVED"),
'owner' => new MongoId("53bf464ee7fda8780c8b4568"),
'status' => ' love this video - Pedigree Shelter dogs http://youtube.com/watch?v=5v5Ui8HUuN8',
'timestamp' => new MongoDate(1405044327, 565000),
)
While I can loop through one by one, I can't for some reason do an $or search. I am not quite understanding how I loop through the following array and add it to the search query before I ran the query.
collection = static::db()->feed;
$where=array( '$or' => array(array('owner' => new MongoId($following.0)))));
$feed = $collection->find($where);
return $feed;
now I understand I will somehow have to loop the $where=array( '$or' => array(array('owner' => new MongoId($following.0))))); But I am just not 100% sure how to do this.
Update
As per the answer below I had to edit the array that was returned - now I have only got this working manually and can't seem to get the PHP script to do it.
Answer Returns
Array ( [owner] => Array ( [$in] => Array ( [0] => new MongoId("53bf464ee7fda8780c8b4568") [1] => new MongoId("53b00ab5e7fda8304b8b4567") ) ) )
Correct:
Array ( "owner" => Array ( '$in' => Array ( "0" => new MongoId("53bf464ee7fda8780c8b4568"), "1" => new MongoId("53b00ab5e7fda8304b8b4567") ) ) )
I am not sure how else to get this to work.
current PHP
$collection = static::db()->following;
$following = $collection->findOne(array ('owner' => new MongoId($_SESSION['user_information'][0]['_id'])));
$follow = $following['following'];
$collection = static::db()->feed;
$where=array("owner" => array( '$in' =>$follow));
print_r($where);
$feed = $collection->find($where);
print_r($feed);
return $feed;
I have fixed a small issue with the collection and now the return array shows
Array ( [owner] => Array ( [$in] => Array ( [0] => MongoId Object ( [$id] => 53bf464ee7fda8780c8b4568 ) [1] => MongoId Object ( [$id] => 53b00ab5e7fda8304b8b4567 ) ) ) )
However, I still can't get it to return the feed like this one:
array (
'_id' => new MongoId("53bf4667e7fda8700e8b4567"),
'owner' => new MongoId("53bf464ee7fda8780c8b4568"),
'status' => ' love this video - Pedigree Shelter dogs http://youtube.com/watch?v=5v5Ui8HUuN8',
'timestamp' => new MongoDate(1405044327, 565000),
)
I am presuming here that this is just a PHPism in the way things are displayed and that your following array is an actual array and not a hash/map, which would generally look like this in a JSON representation:
{
"following": [
ObjectId("53bf464ee7fda8780c8b4568"),
ObjectId("53b00ab5e7fda8304b8b4567"),
],
"owner": ObjectId("53b9ea3ae7fda8863c8b4123"),
}
In which case the "following" is already an actual array, and if you just want to .find() all the "feed" items for the people you are following, then you just pass that to the $in operator for your query selection:
$where = array( "owner" => array( '$in' => $following ) );
$feed = $collection->find($where);
return $feed;
The returned cursor will only contain results from the feed where the "owner" is present in your "following" array from the other collection item.
Watch this code:
$list = array(new MongoId(), new MongoId, new MongoId());
$doc = array( "owner" => array( '$in' => $list ));
echo json_encode( $doc, JSON_PRETTY_PRINT );
Despite how this serializes for JSON by this method the equivalent JSON is:
{
"owner": {
"$in": [
ObjectId("53bf8157c8b5e635068b4567"),
ObjectId("53bf8157c8b5e635068b4568"),
ObjectId("53bf8157c8b5e635068b4569")
]
}
}
That is how the BSON will serialize and is the correct query.
(Answer added on behalf the question author to move it to the answer space).
The issue was fixed when I used the following:
var_dump(iterator_to_array($feed));

CakePHP - Select box item not properly appearing in POSTED data

I have the following select box with CakePHP.
//Users/settings.ctp
$options = array('NYC', 'LA');
echo $this->Form->create('Location');
echo $this->Form->input('Location', array('type' => 'select', 'options' => $options));
echo $this->Form->end(__('Submit'));
In the UsersController I have
public function settings($id = null){
if ($this->request->is('post')) {
$location = $this->request->data;
//$location = $location['Location']['Location'][0];
$this->Session->setFlash( __(print_r($location))); //displays '1' in the alert no matter the selection
}
}
When I use print_r on the raw data it shows the following.
Array ( [Location] => Array ( [Location] => 0 ) )
So I have two problems
The index of the item is being selected, not the item itself
The setFlash window always displays '1'. I need to do some string manipulation after I get the listbox working and it's nice to see the output.
update - I went into /Cake/View/Helper/FormHelper.php and did some digging
I did a print_r on the following line
$attributes = $this->_initInputField($fieldName, array_merge(
(array)$attributes, array('secure' => self::SECURE_SKIP)
));
Which resulted in
Array ( [value] => 0 [class] => [name] => data[Users][Location] [id] => UsersLocation )
The value being passed is 0, I don't see the location anywhere
You're creating a form for the "Location" model, but you need to specify which field the select is for:
echo $this->Form->input('Location.location', array('type' => 'select', 'options' => $options));
Or, if it's not actually for the "Location" model, then either replace the "Location" in the form create() with the correct model, or use null if it's not a model at all:
$this->Form->create(null);
I figured it out and decided someone else might find it useful so.
The array needed to be formatted as
$options = array(
'value' => 'Display');
So, I used
$options = array(
'NYC' => 'NYC',
'LA' => 'LA');

Need a map reduce function in mongo using php

Need a map reduce function by mongo in php
This my mongo structure
[_id] => MongoId Object (
[$id] => 4fcf2f2313cfcd2454500000d
)
[id] => 454
[table] => people
[news] => Array (
[03-06-2012] => 2
[04-06-2012] => 3
[05-06-2012] => 5
[06-06-2012] => 4
)
Here I try to sum the array news with below code,
$map = new MongoCode('function() { emit(this.news, 1); }');
$reduce = new MongoCode('function(previous, current) {
var count = 0;
for (index in current) {
count = count + current[index];
}
return count;
}');
$sales = $db->command(array(
'mapreduce' => 'mycollection',
'map' => $map,
'reduce' => $reduce,
'query' => array('table' => 'people'),
'out' => 'news'
));
//pr($sales);exit;
$users = $db->selectCollection($sales['result'])->find();
foreach ($users as $user) {
//echo "{$user['_id']} had {$user['value']} sale(s).\n";
pr($user);
}
When pr($user)
Array
(
[_id] => Array
(
[04-06-2012] => 0
[08-06-2012] => 2
[11-06-2012] => 6
)
[value] => 39540
)
Where I expected a value will be 8 instead of 39540.
How I can correct this function and how to the add a field sum as array sum of 'news' to original collection(mycollection) ?
I am not familar with map reduce functions in mongo.
When calling emit(), the first parameter is the key you'll be reducing on (or grouping, for this example). The second parameter is the value being emitted for that key, which can be anything. For your example, you probably mean to emit the sum of all values in the news field, using the document's ID as your key:
var map = function() {
var total = 0;
for (count in this.news) {
total += count;
}
emit(this._id, total);
}
In this case, a placeholder reduce function can be used (since each emitted key will be unique, there's very little reduction to be done):
var reduce = function(key, values) {
var total = 0;
values.forEach(function(v) { total += v; });
return total;
}
However, as I mentioned in the Google Group post, you may be better off doing this with pure PHP:
$cursor = $collection->find(array(), array('news' => 1));
$cursor->snapshot();
foreach ($cursor as $document) {
$collection->update(
array('_id' => $document['_id']),
array('$set' => array('sum' => array_sum($document['news']))),
array('multiple' => false)
);
}
With map/reduce, you'd still have to examine its results and update your records. This would avoid the need to execute JavaScript through Mongo, and should be more performant. And if you can utilize $inc to update the sums as the news field is modified on a per-document basis, that will be even better. The above snippet would still be useful for initializing sum fields across the collection, or correcting any drift if things get out of sync with per-document increments.
Note: see snapshot() in the documentation for the reasoning behind that method call in the example above.
While jmikola's answer gives me wright track to deal with mongo map reduce functions.
I am adding this answer in order to help future visitors.
The following map-reduce function works perfectly to my requirement.
This will sum all values in the news field to new collection called news created in command by adding ("out" => "news").
Map-Reduce Function
$map = new MongoCode('function() {
var total = 0;
for (count in this.news) {
total += this.news[count];
}
emit(this._id, {id: this.id, total: total});
}');
$reduce = new MongoCode('function(key, values) {
var result = {id: null, total: 0};
values.forEach(function(v) {
result.id = v.id;
result.total = v.total;
});
return result;
}');
$sales = $db->command(array(
'mapreduce' => 'mycollection', // collection name
'map' => $map,
'reduce' => $reduce,
'query' => array('table' => 'people'),
"out" => "news" // new collection name
));
The result will be news collection with sum as total and id of actual document
Output
[_id] => MongoId Object (
[$id] => 4fd8993a13cfcd4e42000000
)
[value] => Array (
[id] => 454
[total] => 14
)

Categories