Save Multiples times Cakephp 3.x - php

What I want to do is to save my data multiple times. In order to do that I put this code in my Controller :
foreach ($tw->statuses as $t) {
$tw->image = $t->user->profile_image_url;
$tw->name = $t->user->name;
$tw->screenname = $t->user->screen_name;
$tw->message = $t->text;
$tw->Fil_id = $FiltreId;
$this->Twes->save($tw);
}
return $this->redirect(['action' => 'index']);
However when the execution is done, I found only the last record saved in my database, and not the other ones. Can anyone help me ?

This can be happening due to various things:
The variable $tw->statuses only contains ONE status.
The table where you store the data has a unique index that collides when the data is inserted for the second time.
Can you give more information (like the table description, or a var_dump of the named variable before iterating it) to exactly pinpoint what's happening?

I found where the problem was. I updated my code, and i used TableRegistry and used newEntity inside my foreach as you can see :
$oPeople = TableRegistry::get('Tweets');
$oQuery = $oPeople->query();
foreach ($tw->statuses as $t) {
$test = array($FiltreId,$t->text,$t->user->name,$t->user->screen_name,$t->user->profile_image_url,null,null,null,null,null);
$tw = $oPeople->newEntity($test);
$tw->image = $t->user->profile_image_url;
$tw->name = $t->user->name;
$tw->screenname = $t->user->screen_name;
$tw->message = $t->text;
$tw->Fil_id = $FiltreId;
$this->Twes->save($tw);
}
return $this->redirect(['action' => 'index']);
This way all the data is saved, and not only the last one.

Related

Dynamically created directory returns "Array" 1 in 1000 times

I'm fixing up some old code that is supposed to create a directory for a customer based on the customer's last name. 999 out of 1000 times it works as expected but every now and then I get an "Unable to create base directory" error message and the debug shows me that the $file_directory in that case is simply "Array" instead of something like "\\network\path\order_data\1234567890_Smith".
Could anyone explain how this code could work the vast majority of the time but still consistently fail about .1% of instances? Or is it something other than the code? Thanks!
Note: I did not originally write this code but am tring to leave it as close to the original as possible
Edit I had a typo in my previous code but I think tliokos and Fluinc had a very good point but just wanted to fix my mistake
Code:
<?php
$file_directory = build_directory($customer, $UID);
if(!is_dir($file_directory)){ //Check to make sure it does not already exist
if(!mkdir($file_directory)){
mail("debug#example.com","Unable to create base directory","$file_directory");
}
}
function build_directory($customer, $UID){
if($customer->related_orders){
$related = explode(",", $customer->related_orders);
foreach($related as $r_UID){
$rel_order = get_order($r_UID); //fetches order object
if((isset($rel_order->file_directory) && $rel_order->file_directory != "")){
return $rel_order->file_directory;
}
}
}
//Here is where I made my correction
$paths = array('\\\\network\\path');
$base = $paths[0];
//Test if directory is already assigned
if(is_dir($base . "\\order_data\\".$UID."_".str_replace(" ","_",$customer->last_name)."\\")){
return $base . "\\order_data\\".$UID."_".str_replace(" ","_",$customer->last_name)."\\";
}
if($base){
return $base . "\\order_data\\".$UID."_".str_replace(" ","_",$customer->last_name)."\\";
}
}
?>
Change $base = array('\\network\path');
To $base = '\\network\path';
I think the problem is in the build_directory() function and more specifically after the first if.
So if the customer has no related orders, you are trying to concatenate an Array with a string and the result is like
Array\order_data\....
Try o change
$base = array('\\network\path');
to
$base = '\\network\path';
So the problem ended up being framework/user related.
We discovered that if the user refreshed the page during the directory creation it would create the same directory twice which our framework would save as an array of identical paths.

How to associate multiple Doctrine objects in a foreach loop before flushing the entity manager

i need your help for persist data, i explain :
i have entity Player with variable refer Team :
class DataPlayer
{
/**
* #ORM\ManyToOne(targetEntity="Team")
* #ORM\JoinColumn(name="tag_team", referencedColumnName="tag_team")
*/
private $team;
...
}
but when i include the data, i have only tag of team, not entity team...
because the team is not probably present in database (i include team after).
how can i do to set team with string (the tag directly) whitout to change Entity player
thank!
Okay, I believe I see what you're trying to achieve.
You are doing some sort of import, and during the foreach loop, you're creating Team entities that get associated with your DataPlayer. Obviously you don't want to end up making multiple Teams after the first one has been made with a certain tag, but since you haven't performed a flush() using the Entity Manager yet, you can't findOneByTag() because the Team doesn't yet exist in the database.
This is obviously problematic. So what's the solution? Create a temporary array!
$tempTeams = array();
foreach($teams as $team){
$info = explode(',', str_replace("'", "", $team));
if (isset($tempTeams[$info[1]])) {
$db_team = $tempTeams[$info[1]];
} else {
$db_team = $db->getRepository("ApplicationTestBundle:Team")->findOneByTag($info[1]);
}
if(!$db_team){
$db_team = new Team();
$db_team->setTag($info[1]);
$db_team->setName($info[0]);
$em->persist($db_team);
$tempTeams[$info[1]] = $db_team;
}
$dataT = new DataTeam();
$dataT->setTeam($db_team);
$em->persist($dataT);
$db_team = false; // Need to make sure $db_team is cleared out for the next iteration of the foreach
}
This takes all of your temporary PHP objects before persistence and buffers it into the temporary array, which allows you to recall your new Objects by tag name with no problems. The other solution is to $em->flush(); after $em->persist($db_team);
You can then access the $tempTeams array for later lookups (I believe there was an issue with using $info[4] for the tag this time):
foreach($players as $player){
$info = explode(',', str_replace("'", "", $player));
$db_player = $db->getRepository("ApplicationTestBundle:Player")->findOneByPseudo($info[1]);
$dataJ = new DataPlayer();
$dataJ->setJoueur($db_player);
if (isset($tempTeams[$info[4]])) {
$db_team = $tempTeams[$info[4]];
} else {
$db_team = $db->getRepository("ApplicationTestBundle:Team")->findOneByTag($info[4]);
}
$dataJ->setTeam($db_team);
$em->persist($dataJ);
$db_team = false;
}

Yii using a variable with an IN condition

I am trying to pull information into a page using my model. The issue is that I need to use an IN condition on my mysql using a variable.
Here is the code I use currently
$list_id = '1,3';
$clients = ListSubscriber::model()->findAll(array('condition'=>'list_id IN (:list_id)','params'=>array(':list_id'=>$list_id)));
I won't necessarily know how many numbers will be stored within $list_id, hence the need for a variable to work with the IN.
The code does execute without errors, but only seems to return the values for the first number of $list_id, so in this case it only finds users where the list_id = 1.
Any help is appreciated. I have found this question Yii addInCondition
However they are using static values, which does not resolve my issue.
When I do use static values, the code executes with results as expected.
You can use addInCondition :
$list_id = '1,3';
$criteria = new CDbCriteria();
$arr_list_id = explode(",",$list_id);
$criteria->addInCondition("list_id ", $arr_list_id );
$clients = ListSubscriber::model()->findAll($criteria);
$list_ids = array(1,3);
$clients = ListSubscriber::model()->findAllByAttributes(array('list_id'=>$list_ids));

How to move an eDirectory entry via php?

I have this ldap entry:
cn=blah,ou=apples,ou=people,dc=yay,dc=edu
I need to move that entry to:
cn=blah,ou=oranges,ou=people,dc=yay,dc=edu
My scripts are all PHP so I've been trying to use php.net/ldap_rename
ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", "ou=oranges,ou=people,dc=yay,dc=edu", true);
Does not work. It returns false.
This http://us2.php.net/manual/en/function.ldap-rename.php#82393 comment mentions that eDirectory wants to leave the parent as NULL. Like:
ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", NULL, true);
That returns TRUE but does not actually move the entry. Not surprising since it's not changing the parent... I'm sure it could change the cn=blah to something else...
I have thought of deleting the entry and recreating it. But that's a painful way to go about it. Writing out and running a LDIF file would also be painful.
So, how do I move an entry from one OU to another, in php, without the pain of my other two options?
What I'm running:
Ubuntu 12.04 LTS
PHP 5.3.10
eDirectory 8.8 is on SLES 11
Edit
So, I found this:
The modrdn change type cannot move an entry to a completely different subtree. To move an entry to a completely different branch, you must create a new entry in the alternative subtree using the old entry's attributes, and then delete the old entry.
From http://www.centos.org/docs/5/html/CDS/ag/8.0/Creating_Directory_Entries-LDIF_Update_Statements.html
I found a couple other pages with similar statements.
So it sounds like I have to make a new entry, copying the attributes, the delete the old one. Like the second painful option I mentioned above.
Well, I ended up using the "create new entry, delete old one" method. I still think I had another way working a while back, but I can't remember what. So here's a basic move function.
function move($connection, $ldapEntryReference, $new_dn){
//First, get the values of the current attributes.
$attributes = array(); //start attributes array
$firstattr = ldap_first_attribute($connection, $ldapEntryReference);
$value = ldap_get_values($connection, $ldapEntryReference, $firstattr);
$attributes[$firstattr] = $value;
while($attr = ldap_next_attribute($connection, $ldapEntryReference)) {
if (strcasecmp($attr, 'ACL') !== 0) { //We don't want ACL attributes since
//eDir/ldap should deal with them for us.
if (strcasecmp($attr, 'jpegPhoto') === 0) {
//binary values need to use the ldap_get_values_len function.
$value = ldap_get_values_len($this->connection, $ldapEntryReference, $attr);
} else {
$value = ldap_get_values($this->connection, $ldapEntryReference, $attr);
}
$attributes[$attr] = $value;
}
}
//Create a new entry array with the values.
$entry = array(); //start entry array.
foreach($attributes as $key => $value) {
foreach($value as $key2 => $value2) {
if (strcasecmp($key2, 'count') !== 0) {//get rid of 'count' indexes
//ldap_add chokes on them.
$entry[$key][$key2] = $value2;
}
}
}
//Add the new entry.
if (ldap_add($connection, $new_dn, $entry)) {
//Delete the old entry.
if (ldap_delete($connection, ldap_get_dn($connection, $ldapEntryReference)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
Hopefully this helps someone, sometime.
There actually isn't a need to recreate in eDir. Doing a recreate causes problems in an environment that runs IDM as the object will have a new GUID and the IDM engine will not see the event as a true "move".
The following code moves users fine (tested eDir 8.8.x & eDir 9.x):
$olduserdn = "cn=userid,ou=container1,o=org";
$newdestdn = "ou=container2,o=org";
if (preg_match('/^(cn=[A-Za-z0-9]+)\,(.+)/i', $olduserdn, $rdnmatches))
{
if (ldap_rename($ldapconn, $olduserdn, $rdnmatches[1], $newdestdn, TRUE))
{
print("Moved $olduserdn to $rdnmatches[1],$newdestdn");
}
else
{
print("Failed move because " . ldap_error($ldapconn));
}
}
Don't forget to give a bit of time for replication...
Also consider constraints around modifying/moving objects that are still being replicated from a previous move event.
Try this:
ldap_rename($ldapconn, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", "ou=oranges,ou=people,dc=yay,dc=edu", true);

PHP & MySQL with options page

Finally completed the frontend of my website, I am now looking at coding the backend which needs an overhaul, the coding is very messy and uses far too many SQL Connections and commands, so much so that the host is complaining about it.
One of the main problems I am having is the Site Settings page, problem is this page will soon contain over 10 different options, and I prefer not to have a MySQL Update simply updating the option field to what it already is, so I am wondering if anyone has any ideas?
This is the structure of my options table, nice and simple which I recently changed from an awful layout.
What would be the best way to edit these options without having to update every single one, and what would be the best way to have them in a function? Currently, the function I have was made back when I was new to coding, and you can see that is is very uneffective(note it uses the old table structure)
function site_upd($site_title, $site_email, $maint_status, $maint_mess, $upload_disable, $site_url, $reg_status, $land_mess)
{
if( !$site_title )
{
echo $this->errorMessage('There was no <b>site title</b> supplied, therefore we can not continue with this request.', 'error');
}
else
{
$this->logQuery('Updated site settings');
$query = "UPDATE `table`.`settings` SET `site_title` = '".$site_title."', `site_email` = '".$site_email."', `maint_status` = '".$maint_status."', `maint_mess` = '".$maint_mess."', `upload_disable` = '".$upload_disable."', `site_url` = '".$site_url."', `registration_status` = '".$reg_status."', `landing_mess` = '".$land_mess."' WHERE `settings`.`sid` = '1'";
mysql_query($query) or die(''.mysql_error()); } }
So yeah, there is the awful old structure and my old way of doing things, before I get stuck into coding I want other peoples opinions on what is the best way to do this!
You can work with $_POST Variable to simplify the update method.
This is what I usually do:
First I create a non specific function to update:
function update_db($table, $id,$idvalue,$field,$fieldvalue){
return mysql_query("update ".$table." set ".$field."=".$fieldvalue." where ".$id."=".$idvalue);
}
Then i create the specific function to the table (config i.e):
function update_table_config($name,$value){
return update_db("config","name",$id,"value",$value);
}
In the form i call all <input> like its name on the table:
Site Name: <input type="text" name="site_name">
...
and in the "action" page i check $_POST array:
$data_array=$_POST;
if(check_variables($data_array)){
foreach ($data_array as $key=>$value){
update_table_config($key,$value);
}
}
the function check_variables has all the checks that you need for all the fields:
function check_variables($data){
if($data["site_title"]=="") return false;
if(!is_numeric($data["landing_mess"])) return false;
...
return true;
}
with this methods if in the future you have to include more fields in the configuration table you only have to add the <input> field and a check in check_variables function if needed

Categories