CakePHP question: What's the difference between these two routing? - php

This is one =>
echo $this->Html->link('Edit',
array('controller'=>'comments','action'=>'edit',$comment['Comment']['id']));
This is another one in form =>
echo $this->Form->create('Comment',
array('url'=>array('controller' => 'comments', 'action' =>'add', $listposts['Post']['id']) )
);
echo $this->Form->input('post_id',array('type'=>'hidden','style'=>'width:30%','value'=>$listposts['Post']['id']));
echo $this->Form->input('name',array('style'=>'width:30%'));
echo $this->Form->input('email',array('style'=>'width:30%'));
echo $this->Form->input('body',array('rows'=>'5'));
echo $this->Form->end('Submit');
Is it possible to do echo $this->Form->create like the previous one ? Why do i need 'url'=>array(..) why not like this =>
echo $this->Form->create('Comment',array('controller' => 'comments', 'action' =>'add', $listposts['Post']['id']));

The reason for that is tthat the url-array is an argument in the link()-function of the HTML-helper. If you take a look at the declaration:
link(string $title, mixed $url = null, array $options = array(),
string $confirmMessage = false)
So you pass the url as second argument without the $url name as you would do with other methods.
Howerver, the declaration of the create()-method in the Form-helper is:
create(string $model = null, array $options = array())
Notice that there is just one $options-array. So your url here is a member of an array rather then a member of an argument list. In associative arrays you can't simply leave the keys so using the url-array without explicitly naming the key should not work.
For more information see the Docs for this methods:
HTML->link()
Form->create()

Related

Passing an argument to callback function working on an array

I'm using an external class (Zebra_cURL) to execute multiple HTTP GET requests. It worked in the following way:
$items = array(
0=>array('url' => 'url0'),
1=>array('url' => 'url1'),
2=>array('url' => 'url2'),
3=>array('url' => 'url3'),
);
$curl = new Zebra_cURL();
$curl->get(array_column($urls,'url'),'scan_item',$moreimfo);
function scan_item($result,$moreimfo){
$items[$key]['size'] = strlen($result->body);
}
So my callback should fill up my $items array with more info for each url (in my case - size of the page). So there is a missing $key variable.
This class supports extra parameters in the callbacks ($moreimfo in my case). BUT as I understand the data passing to each callback will be always the same.
$result object containing the original url info ($result->info['url']). So I COULD use it to find needed array element. However this looks too inefficient in case the size of an array will be big enough.
I think that I should find how to pass an array member key information for EACH callback execution. Is it possible without modifying the original class?
If you use the url as key in the $items array the solution could be something like
<?php
$items = [
'url0'=>array('url' => 'url0'),
'url1'=>array('url' => 'url1'),
'url2'=>array('url' => 'url2'),
'url3'=>array('url' => 'url3'),
];
$curl = new Zebra_cURL();
$curl->get(
array_keys($items),
function($result) use (&$items) {
$key = $result->info['url'];
$items[$key]['size'] = strlen($result->body);
}
);
using an anymous function that "Imports" the $items array via reference.
While it doesn't solve the original problem of passing a reference to the according array element to the callback, the following should be very fast (as noted in the comments, PHP Arrays are implemented using a hashtable).
$items = array(
0=>array('url' => 'url0'),
1=>array('url' => 'url1'),
2=>array('url' => 'url2'),
3=>array('url' => 'url3'),
);
$lookup=array();
foreach($lookup as $k=>$v) {
$lookup[$v['url']]=$k;
}
$curl = new Zebra_cURL();
$curl->get(array_column($urls,'url'),'scan_item',$moreimfo);
function scan_item($result,$moreimfo){
global $lookup,$items;
$items[$lookup[$result->info['url']]]['size'] = strlen($result->body);
}
Probably you may consider using an OOP-approach, with the callback as a method, then the global-izing of the arrays shouldn't be necessary if you use $this->anyMember

Remove array element with YiiMongoDbSuite

I have some code that should be deleting a record from an embedded MongoDB document.
Here is the code:
public function actionDeleteSaved()
{
$savedLink = $_POST['savedLink'];
$userId = Yii::app()->user->getId();
$current = SaveLink::model()->findByPk($userId);
if(in_array($savedLink, $current->links))
{
array_slice($current->links, $savedLink);
$current->save();
}
}
This is what is passing the data to the controllers action method:
echo CHtml::ajaxButton(
'delete',
Yii::app()->createUrl("dashboard/index/deletesaved"),
array( // ajax options
'type' => 'POST',
'context' => "js:this",
'data' => array(
'savedLink' => $savedLink
)
),
array( //html options
'class'=>'deleteSaved'
)
);
This is what renderPartial looks like:
$this->renderPartial('_deleteSaved', array('savedLink'=>$s));
What I want being posted is being posted correctly but I'm not sure if it's communicating with the Controller and passing the data through or if my code for removing the data from the database is correct.
Any help would be greatly appreciated, thanks.
The problem is with array_slice part. As specified in php docs array slice does not modify array parameter.
Use array_splice instead (it modifies passed array param) and array_search to get key:
if(in_array($savedLink, $current->links))
{
$key = array_search($savedLink, $current->links);
array_splice($current->links, $key, 0);
$current->save();
}
NOTE: If $current->links is embedded documents (objects) array, you might have to find $key and check if is in array some other way.

Extracting array as list of arguments passed to function

Is it possible to make something like that:
$array = array('id' => '5', 'something_else' => 'hi');
function some_function($id, $something_else)
{
echo $something_else;
}
some_function(extract($array));
This code is giving me true/false and not $id,$something_else, etc..
It is important for me to do something like that, because I have different list of variables for each function ( I'm working on my ( let's call it ) "framework" and I want to pass list of variables instead of array with variables. This code is actually going in my router so it's not quite that simple, but in the end it comes to that ).
I assume you know how your array is built. So, why do not you just pass an array as a parameter and then use it in your function ?
If you do something like this you can access to your array's values :
echo $array['something_else'];
And build your function like this :
$array = array('id' => '5', 'something_else' => 'hi');
function some_function($an_array)
{
echo $an_array['something_else']; // value for something_else
}
some_function($array);
Or if you don't want to change function's parameters, call it like this :
some_function($array['id'], $array['something_else']);

yii ajaxLink is not passing variable to controller

I am trying to pass a variable from an ajaxLink into my controller but my controller is not getting the variable.
//view
$ids = Yii::app()->storedData->getIds();
foreach($ids as $id) {
echo 'ID '.$id .'<br />';
echo CHtml::ajaxLink(
'remove',
array('/storedInfo/remove'),
array(
'data' => array('removeItem' => $id),
));
}
//controller
public function actionRemove() {
var_dump($_GET['removeItem']); // RETURNS string(0) ""
die();
}
The ajax array you're passing to CHtml::ajaxLink ends up taking the whole array and passing it to CJavaScript::encode().
As you mentioned in your comments, the $id you were using to build your data array was a PHP object. When this got to CJavaScript::encode, things got wonky, and the results weren't what you were expecting. Extracting a string or numeric value from $id, rather that passing the whole object should take care of this, e.g.:
'data' => array('removeItem' => $id->value) // obviously you'll need to use the proper key to get the value
Or maybe something like this depending on the data structure:
'data' => array('removeItem' => settype($id, 'string'),
I edited out my answer because i admit it was not what the original asker wanted but for the sake of the comments, i leave my code here
$ids = Yii::app()->storedData->getIds();
foreach($ids as $id) {
echo 'ID '.$id .'<br />';
echo CHtml::ajaxLink(
'remove',
array('/storedInfo/remove', array('removeItem' => $id)),
);
}
Looks like CHtml::ajaxLink takes more parameters than you're sending.
public static string ajaxLink(string $text, mixed $url, array $ajaxOptions=array ( ), array $htmlOptions=array ( ))
Do you need to send along some $text before the $url?

Can I call a function who's name is stored in a variable?

I'm coding an IRC bot, and in it I have an array holding the commands, and an action for each command.
For example, a stored action might be $array("action" => $irc->say_something())
Would I be able to call that with $array['action'] or would I have to do it some other way?
Use call_user_func('func', list, of, args) or call_user_func_array('func', array(containing, arguments)).
As you want to call a class method, you'll have to pass 'func' not a a string but as an array: array($instance, 'func') - in your case: array($irc, 'say_something')
Fyi, $array("action" => $irc->say_something()) makes no sense. But you probably wanted to write array("action" => $irc->say_something()). However, this assigns 'action' to the result of the method call - not what you want. See the last paragraph on how the 'action' value should look like to use it as a method pointer.
Sure:
$invocation = array("action" => array(
'func' => array($irc,'say_something'),
'args' => array()));
call_user_func_array($invocation['action']['func'], $invocation['action']['args']);
call_user_func http://us.php.net/call_user_func
<?php
function barber($type)
{
echo "You wanted a $type haircut, no problem\n";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");
?>
I know you can do something like this:
$target = " blah ";
$function = "trim";
$trimmed = $function($target);
I'd guess that would also work if $function is an array element

Categories