PHP – function use

As with the previous post about the use method within php (here), you are also able to use the use method attached to a callable function as in

function ($parameter) USE ($somevalue)

So you are able to use any variables that are within scope within the new function, below is an example where I am using the array walk methods callback (which means call a function that is available). The function is using the values within the array ($arrays 4 and 5) and adding them to the $value variable that is passed within the use parameters (here I am using the & symbol which means to pass in reference and not just a copy of the value (you are able to alter the actual parameter passed), so in this instance the $value starts of with 1, then adds 4 and then 5 to it which in turn the result is 10.

$value = 1;
$callback = function ($one) use (&$value) {
	$value += $one;
};
$arrays = array(4,5);
array_walk($arrays, $callback);
print_r("value : " .$value);

And the output would be.

value : 10

pass by reference

When you call a function normally within PHP the variable that you pass is a copy of, for example

function doesNotAlter($alterMe)
{
   $alterMe++;
}
$pleaseAlterMe = 4;
doesNotAlter($pleaseAlterMe);

that will alter the $alterMe variable by adding one to it, but it will only alter it in a local scope of that variable so the actual variable that was passed ($pleaseAlterMe) will not change its value.

But if you pass by reference, then you bring the passing variable into the local scope of that function and thus any alternations to it will act on the variable that has been passed, the only thing that you need to alter is to add a (&), which is very similar to c/c++ which passes the reference to the object (pointer to).

function doesNotAlter(&$alterMe)
{
   $alterMe++;
}
$pleaseAlterMe = 4;
doesNotAlter($pleaseAlterMe);

The & is added to the variable in the passing function parameter list and that is all that it takes to make that remote variable to the function doesNotAlter, to now become a local scoped variable that will alter, so I could change the function name to doesAlter ;).

function doesAlter(&$alterMe)
{
   $alterMe++;
}
$pleaseAlterMe = 4;
doesNotAlter($pleaseAlterMe);
echo $pleaseAlterMe;

So now output would be “5”, because the local variable to the execution of the program is $pleaseAlterMe is first set to 4 and then passed by reference to the doesAlter me function which will actually alter that variable (by adding one to it) and then when you output that variable it will be 5.

CS75 – Assignment 0 – Three Aces Menu

I am doing the Harvards building dynamic websites called CS-75 (also could be called E-75), because someone told me about it and I just thought might as well, it is all learning 🙂 even if allot of it you may already know.

Anyway, to setup the CS75 on my personal laptop ( I am running Ubuntu 10.4) I did a couple of alternations for me so that the local apache instance looks like I am doing it under the top level domain of CS75 :).. so for this assignment Three Aces menu I am calling the website http://threeaces.cs75 on my local host, so to setup that I altered the /etc/hosts file and added

127.0.0.1       threeaces.cs75

so that local IP will also have threeaces.cs75 🙂 and now need to alter apache to allow me to run that as a virtualhost on my laptop, I added the file within

sudo vim /etc/apache2/sites-available/cs75_threeaces

with adding in

<VirtualHost *:80>
       ServerAdmin emailaddress@here.com
       ServerName  threeaces.cs75
       DocumentRoot /var/www/cs75/ass0
       <Directory /var/www/cs75/ass0>
               Options Indexes FollowSymLinks MultiViews
               AllowOverride None
               Order allow,deny
               allow from all
       </Directory>
 
       ErrorLog /var/log/apache2/error.log
       LogLevel warn
       CustomLog /var/log/apache2/access.log combined
 
</VirtualHost>

Which points to the /var/www/cs75/ass0 as the base directory for this assignment :).

I have included the assignments 0 PDF for more information, but basically this assignment is about playing with simpleXML to load in a menu (that you have created from the menu list of the restaurant Three Aces) which is in XML format, you get to pick the format, but here is mine (it has the extras link within the menu->type extras attribute which link to the extras at the bottom of the menu format)

<?xml version="1.0" encoding="ISO-8859-1"?>
<menu>
	<type name="Pizzas" extras="Extra Cheese">
		<item name="Tomato &amp; Cheese">
			<price type="Small">5.50</price>
			<price type="Large">9.75</price>
		</item>
		<item name="Onions">
			<price type="Small">6.85</price>
			<price type="Large">10.85</price>
		</item>
	</type>
	<type name="Salads">
		<item name="Garden">
			<price type="Small">3.50</price>
			<price type="Large">4.50</price>
		</item>
		<item name="Greek">
			<price type="Small">4.50</price>
			<price type="Large">5.50</price>
		</item>
	</type>
	<type name="Grinders">
		<item name="Meatless">
			<price type="Small">4.50</price>
			<price type="Large">4.95</price>
		</item>
		<item name="Hamburger">
			<price type="Small">4.50</price>
			<price type="Large">4.95</price>
		</item>
	</type>
	<type name="Special Dinners">
		<item name="Chicken Wing Dinner">
			<price>7.25</price>
		</item>
		<item name="Gyro Plate">
			<price>7.25</price>
		</item>
	</type>
	<extras name="Extra Cheese">
		<price type="Small">1.25</price>
		<price type="Large">1.85</price>
	</extras>
</menu>

You can implement it anyway that you want to, but to not have two same names of the food for different sizes. So that is why I have a the item name with the price list(s) underneath. It is only part of the menu that I implemented above.

The next part is to only have part of the menu on the main home page, so I am just displaying the main types of food options, I have included the source file for all of the files in the zip file above.

<form name="types" method="get" action="types.php">
<?php
// display the user the different types of foods that are avaible to order
$xml = simplexml_load_file("menu.xml");
// list the different types on the menu
foreach ($xml->type as $types)
{
	echo "<input type=\"radio\" name=\"type\" value=\"" .$types->attributes()->name .  "\"/>".$types->attributes()->name . "<br/>" ;
}
?>
<input type="submit"/>
</form>

Once the user has selected the type of food that they want, you next to have display the items of food within that area, so I am passing in the $_GET string from the index page the type of food, so within the types.php I pick up the type and then display all of the food items within that area. I did do some javascript that will make sure that there is a valid integer value within the, also at the start of the code I am pulling any extra values from the menu to populate the extras option.

<form name="types" method="get" action="checkout.php" onsubmit="return checkout()">
<?php
// display the different items within that type area of foods, with also there different prices and sizes
// normal = normal size for the default size
$xml = simplexml_load_file("menu.xml");
$type = $_GET["type"];
echo $type. "<table border=1>";
echo "<input type=\"hidden\" value=\"".str_replace(" ", "@",$type)."\" name=\"type\"/>";
$result = $xml->xpath("//type[@name='$type']");
if (sizeof($result[0]) == 0)
	echo "<br/><br/>Please go back to home, because cannot find that type<br/><br/>";
else
{
	$extras = $result[0]->attributes()->extras;
	if (strlen($extras) > 0)
	{
		$resultExtras = $xml->xpath("//extras[@name='$extras']");
		if (sizeof($resultExtras[0]) > 0)
		{
			$extraName = $resultExtras[0]->attributes()->name;
			for ($i=0; $i < sizeof($resultExtras[0]); $i++)
			{
				$thePrice =  $resultExtras[0]->price[$i];
				$theType = ($resultExtras[0]->price[$i]->attributes()->type ? $resultExtras[0]->price[$i]->attributes()->type : "Normal");
				$theExtras[$i] = array((string)$thePrice, (string)$theType);
			}
		}
	}
	foreach ($result[0] as $items)
	{
		echo "<tr><td>".$items->attributes()->name."</td><td>Price</td><td>Quantity</td>";
		if (strlen($extras)) echo "<td>$extras</td>";
		echo "</tr>";
		for ($i=0; $i < sizeof($items->children()); $i++)
		{
			echo "<tr><td>". $items->price[$i]->attributes()->type . 
				"</td><td>" . $items->price[$i].
				"</td><td><input type=\"text\" size=\"1\" value=\"\" name=\"".str_replace(" ", "@",$items->attributes()->name)."_".$i."\"/></td>";
			if (strlen($extras))
			{
				foreach ($theExtras as $typeCheck)
				{
					if ($typeCheck[1] == $items->price[$i]->attributes()->type)
					{
						echo "<td><input type=\"checkbox\" name=\"".str_replace(" ","_",$extras)."_".$i."\" value=\"".str_replace(" ", "@",$items->attributes()->name)."_".$i."\"/></td>";
						break;
					}
				}
			}
			echo "</tr>";
		}
	}
}?>
</table>
<input type="submit" name="submit"/>
</form>

Because there is a basket of items that the customer will like to buy, I am also storing the basket details within the $_SESSION within a multi array, the array looks like something like

Array
(
    [Pizzas] => Array
        (
            [Tomato  Cheese] => Array
                (
                    [Small] => Array
                        (
                            [price] => 5.5
                            [quantity] => 6
                        )
                )
        )
)

So in the next page, checkout.php I need to update the basket details and also then display what the customer has already picked (with giving the options to update the quantity of goods and also to remove them if they did not want it), the first part loads the new item(s) into the basket and the second part of the code below will display the basket to the user, and call the update.php file if any quantities/remove of items need to be done.

<form name="types" method="get" action="update.php">
<table>
<?php
// display the updated details of the order with the new order addon's 
// and also any previous details of the order, if you want to place the order
// click the order now link below.
$xml = simplexml_load_file("menu.xml");
// load basket from the session
$basket = $_SESSION["basket"];
$type = $_GET["type"];
$type = str_replace("@", " ", $type);
 
$result = $xml->xpath("//type[@name='$type']");
if (sizeof($result[0]) == 0)
{
	if (strlen($type) > 0)
		echo "<br/><br/>Please go back to home, because cannot find that type<br/><br/>";
}
else
{
	$extras = $result[0]->attributes()->extras;
	if (strlen($extras) > 0)
	{
		$resultExtras = $xml->xpath("//extras[@name='$extras']");
		if (sizeof($resultExtras[0]) > 0)
		{
			$extraName = $resultExtras[0]->attributes()->name;
			for ($i=0; $i < sizeof($resultExtras[0]); $i++)
			{
				$newname = str_replace(" ", "_" , $extras) . "_" . $i;
				$$newname = $_GET[$newname];
				if (strlen($$newname) > 0)
				{
					$thePrice =  $resultExtras[0]->price[$i];
					$theType = ($resultExtras[0]->price[$i]->attributes()->type ? $resultExtras[0]->price[$i]->attributes()->type : "Normal");
					$theExtras[$i] = array($$newname, (string)$thePrice, (string)$theType);
				}
			}
		}
	}
 
	foreach ($result[0] as $items)
	{
		for ($i=0; $i < sizeof($items->children()); $i++)
		{
			$newname = $items->attributes()->name."_".$i;
			$newname = str_replace(" ", "@", $newname);
			$$newname = $_GET[$newname];
			if ($$newname > 0)
			{
				$priceType = $items->price[$i]->attributes()->type;
				if (strlen($priceType) <=1)
					$priceType = "Normal";
				$extraPrice = 0;
				foreach ($theExtras as $extraAdd)
				{
					if ($extraAdd[0] == $newname)
						$extraPrice = $extraAdd[1];
				}
				$basket[(string)$type][(string)$items->attributes()->name][(string)$priceType . ($extraPrice > 0 ? (string)" (".$extras.")" : "")] = 
							array("price" =>(float) ($items->price[$i]) + (float)$extraPrice, 
									"quantity" => (int)($$newname 
										+ $basket[(string)$type][(string)$items->attributes()->name][(string)$priceType]["quantity"]) );
				// going with the theory of adding to the previous quantity
				echo "Have added " . $type . " (". $items->attributes()->name . " " . $priceType . ")<br/>";
			}
		}
	}
	$_SESSION["basket"] = $basket;
}
// lets print out the basket in a form of the user to confirm and also remove / alter the quantity
$totalPrice = 0;
echo "<table border=1><tr><td width=50>Type</td><td width=50>Item</td><td width=50>Size</td><td>Price</td><td>Quantity</td><td>Total Price</td><td>Remove</td></tr>";
foreach ($basket as $type => $typevalue)
{
	echo "<tr><td colspan=\"6\">$type</td>";
	foreach ($typevalue as $item => $itemvalue)
	{
			echo "<tr><td></td><td colspan=\"5\">$item</td></tr>";
			foreach ($itemvalue as $size => $sizevalue)
			{
				$namevalue = $type."_".$item."_".$size;
				$namevalue = str_replace(" ","@",$namevalue);
				echo "<tr><td></td><td></td><td>$size</td>";
				echo "<td>&pound;".number_format($sizevalue["price"],2) . "</td><td><input size=5 value=" . $sizevalue["quantity"]  . " name=\"".$namevalue."_quantity\"/></td><td>&pound;".number_format($sizevalue["price"] * $sizevalue["quantity"],2) ."</td><td><input type=\"checkbox\" name=\"".$namevalue."_remove\"/></td></tr>";
				$totalPrice +=$sizevalue["price"] * $sizevalue["quantity"];
			}
	}
	echo "</tr>";
}
echo "</table>";
 
echo "The total price is &pound;".number_format($totalPrice,2)."<br/>";
?>
</table>
<input type="submit"/>
</form>

here is the update.php, this will update the basket from the requested action from the above php file.

<?php
// this will update the session basket from the checkout.php page
session_start();
$xml = simplexml_load_file("menu.xml");
// load basket from the session
$basket = $_SESSION["basket"];
foreach ($_GET as $key => $value)
{
	$key = str_replace("@", " ", $key);
	list($type, $item, $size,$command) =  split("_", $key);
	if ($command== "quantity" && $value > 0)
	{
		$basket[$type][$item][$size]["quantity"] = $value;
	}
	elseif ($command =="remove")
	{
		unset($basket[$type][$item][$size]);
		// clean out the type -> item if none more left
		if (sizeof($basket[$type][$item])==0)
			unset($basket[$type][$item]);
		// clean out the type if none left
		if (sizeof($basket[$type])==0)
			unset($basket[$type]);
	}
}
$_SESSION["basket"] = $basket;
// redirect back to checkout.php
header('Location: checkout.php');
?>

and redirects back to checkout.php.

The last page displays the order in total and also says thanks very much for the order :).. and deletes the basket details :).

<table>
<?php
// display the order details and also thanks for placing the order
$basket = $_SESSION["basket"];
// lets print out the basket in a form of the user to confirm and also remove / alter the quantity
$totalPrice = 0;
echo "<table border=1><tr><td width=50>Type</td><td width=50>Item</td><td width=50>Size</td><td>Price</td><td>Quantity</td><td>Total Price</td></tr>";
foreach ($basket as $type => $typevalue)
{
	echo "<tr><td colspan=\"6\">$type</td>";
	foreach ($typevalue as $item => $itemvalue)
	{
			echo "<tr><td></td><td colspan=\"5\">$item</td></tr>";
			foreach ($itemvalue as $size => $sizevalue)
			{
				echo "<tr><td></td><td></td><td>$size</td>";
				echo "<td>&pound;".number_format($sizevalue["price"],2) . "</td><td>" . $sizevalue["quantity"]  . "</td><td>&pound;".number_format($sizevalue["price"] * $sizevalue["quantity"],2) ."</td></tr>";
				$totalPrice +=$sizevalue["price"] * $sizevalue["quantity"];
			}
	}
	echo "</tr>";
}
echo "</table>";
 
echo "The total price is &pound;".number_format($totalPrice,2)."<br/>";
session_destroy();
?>
</table>

The file above does include all of the php files from the above comments and the PDF of the assignment. You can also view the assignment live on my CS – 75 assignment 0 test area.

SugarCRM hook – what are they

SugarCRM is a very nice and open source CRM (Customer relationship management) system. And with being open source means that you are able to alter the internals of it and also are able to write modules for it easier than closed source applications because you can follow the direction of things if you are for example debugging etc.

The hooks part of the sugarCRM setup allows to place your own code into the base code at set parts of execution e.g. after retrieve of data, or post processing of data updates.

Here is a link to the sugarcrm site of hooks definitions. Basically there is 3 main types, with subhooks attached to those types.

  • Application hooks
    • after_ui_frame – Fired after the frame has been invoked and before the footer has been invoked
    • after_ui_footer – Fired after the footer has been invoked
    • server_round_trip – Fired at the end of every SugarCRM page
  • Module hooks
    • before_delete – Fired before a record is deleted
    • after_delete – Fired after a record is deleted
    • before_restore – Fired before a record is undeleted
    • after_restore – Fired after a record is undeleted
    • after_retrieve – Fired after a record has been retrieved from the database. This hook does not fire when you create a new record.
    • before_save – Fired before a record is saved.
    • after_save – Fired after a record is saved.
    • process_record – Fired immediately prior to the database query resulting in a record being made current. This gives developers an opportunity to examine and tailor the underlying queries. This is also a perfect place to set values in a record

SugarCRM add a new menu item

SugarCRM is a very nice and open source CRM (Customer relationship management) system. Being open source means that you are more than welcome to add/alter your own modules to it. I am going to do some modules which add in some basic information and how-to’s. This how to is how to add to a left menu item and in this case a account main menu left menu item.

Also going to be doing a module for it, so that you can upload to different SugarCRM’s that you may have, e.g. development version and live version.

The module consists of the main manifest.php file which holds all of the main details, module name author, description etc and also the install definitions.

Here is a basic manifest.php file that has the main details and install definitions for adding a menu item to the Accounts module.

<?php
$manifest = array(
  'acceptable_sugar_flavors' => array(
          0 => 'CE',
          1 => 'PRO',
          2 => 'ENT',
          3 => 'DEV'
        ),
    'acceptable_sugar_versions' => array (
        'regex_matches' => array (
            0 => "5\.*\.*.*"
        ),
    ),
 
    'name'              => 'Accounts insert left menu addition',
    'description'       => 'This module inserts a left menu addition',
    'author'            => 'Ian Porter',
    'published_date'    => '2009/06/01',
    'version'           => '0.1',
    'type'              => 'module',
    'icon'              => '',
    'is_uninstallable'   => 1,
    'silent' => true,
);
 
$installdefs = array (
  'id' => 'AccountsLeftMenu',
    'vardefs'=> array( ),
  'custom_fields' =>  array (  ),
  'copy' =>
  array ( ),
'menu'=> array(
array('from'=> '<basepath>/Menu.php',
'to_module'=> 'Accounts', ),
),
       'beans'=> array (
                 ),
  'language' => 
  array (
  ),
);
?>

As you can see from the above code, the acceptable sugar flavors means any of the version types of sugar, development, pro etc.. and the acceptable sugar versions means which version of sugar e.g. version 4.1.2 or 5.etc. the name etc speaks for itself really.

The installdefs are what happens with the files and such when the module is installed, id is the name of the module, the one that we are focusing in on is menu, this will insert the code below into the a set menu module (this case the Accounts menu structure).

Here is the Menu.php file

<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); 
 
/* licence and you stuff */
 
global $mod_strings, $app_strings, $sugar_config, $current_user;
 
/* you need to create the DetailViewPersonal.php file to communicate with */
 
if(ACLController::checkAccess('Accounts', 'edit', true)) {
    $module_menu[]=Array("index.php?module=Accounts&action=DetailViewPersonal&return_module=Accounts&return_action=DetailView&record=".$current_user->id, "Personal View",  'Accounts');
}
?>

The ACLController will check the access level of the user for editable, ACL(Access Control Level), and if so place a new menu below called “Personal View”, the action in the module_menu array is what is called and thus you will need to have a DetialViewPersonal.php in the modules/Accounts directory, but this was just a how to, of how to insert a menu item and not the underlying code.

There is more to come!.

Method – Add Two numbers

This tutorial is using the same base code as Add two numbers, but with using the function addtwo, this takes two parameters $a and $b which are both set to 0 as the default value and returns the two values added together. The answer part of the web page uses the function to add the two numbers together.

The source code

<?php
       function addtwo($a = 0, $b = 0)
       {
              return ($a + $b);
       }
       $value1 = $_POST['value1'];
       $value2 = $_POST['value2'];
?>
<html>
       <title>PHP - Add two numbers</title>
       <body>
              <form action="addtwonumbers.php" method="post">
                     <input type="text" name="value1" value="0" />
                     <input type="text" name="value2" value="0" />
                     <input type="submit" value="Calculate values"/>
              </form>
              Answer : <?php echo addtwo($value1+$value2); ?>
       </body>
</html>

save as addtwonumbers_function.php, this program will function the same as the previous tutorial apart from the inner working will call the method. The method programming allows for one method to be called multiple times, e.g. Within the example above there could be a method that was 5 lines in length and instead of writing the same 5 lines each time, you just write a method that is called.

Add two numbers

This tutorial will add up two values that have been entered within the web page, I am going to use the web page functional aspects rather than the command line interface because php is mainly used within websites.

The web page itself is using a form tag, this form tag allows for the web page to post data back to the server, where the php will use the posts ($_POST) array ( []).

The source code is

<?php
       $value1 = $_POST['value1'];
       $value2 = $_POST['value2'];
?>
<html>
       <title>PHP - Add two numbers</title>
       <body>
              <form action="addtwonumbers.php" method="post">
                     <input type="text" name="value1" value="0" />
                     <input type="text" name="value2" value="0" />
                     <input type="submit" value="Calculate values"/>
              </form>
              Answer : <?php echo ($value1 + $value2); ?>
       </body>
</html>

if you save that as addtwonumbers.php within the php website configured directory and then open up that page via a web browser (e.g. http://localhost/addtwonumbers.php, localhost means the local pc, just like 127.0.0.1 is the local ring e.g the pc itself to talk to itself via an IP).

Just for completeness, this is the command line interface code.

<?php
 echo "Please enter value 1 : ";
 fscanf(STDIN, "%d\n", $value1); // reads number from STDIN standard input
 echo "Please enter value 2 : ";
 fscanf(STDIN, "%d\n", $value2);
 echo "Answer : " .($value1 + $value2) . "\n";
?>