(BTW, what software did you use to create this beautiful diagram?)
20 feb 2012
Evitar que un script en PHP se ejecute desde navegador
18 ene 2012
PHP y ORACLE
Estas conexiones las hará un script en PHP por lo que además, deberemos instalar OCI (Oracle Call Interface) para PHP. Suponemos que está ya instalado el servidor web Apache 2 y los componentes básicos de PHP.
Instalación de Oracle instantclient
Antes de instalar el instantclient como tal, debemos instalar la librería libaio, necesaria para gestionar entradas/salidas asíncronas al kernel. La instrucción será (utilizo “#” en el prompt para indicar como superusuario, “$” en caso contrario):
# yum install libaio1O si usamos una distribución que use APT:
# apt-get install libaio1Lo siguiente será acceder al portal de descargas de Oracle y descargar los componentes necesarios para el instantclient:
- Basic
- Devel
- SQLPlus
# yum install paquete.rpmEn caso contrario, deberemos instalar alien previamente para que convierta los paquetes RPM en paquetes DEB:
# apt-get install alienAhora ya nos tocar configurar el famoso fichero Tnsnames.ora. Este fichero variará de una configuración a otra por lo que sólo vamos a comentar dónde situarlo. Su ruta debe ser: /etc/oracle/tnsnames.ora, en caso de no existir, deberemos crearla.
# alien paquete.rpm
# dpkg -i paquete.deb
Para terminar, deberemos crear unas variables de entorno. Para ello accedemos al fichero /root/.bashrc como superusuario e incluimos las siguientes líneas:
export TNS_ADMIN=/etc/oracleexport SQLPATH=/usr/lib/oracle/11.1.0.1/client/binexport LD_LIBRARY_PATH=/usr/lib/oracle/11.1.0.1/client/lib:$LD_LIBRARY_PATHexport PATH=$PATH:$SQLPATHEn algunas distribuciones, también podréis hacer ese cambio en otro fichero: /etc/environment.
Instalación de OCI en PHP
Ahora nos toca la parte de PHP, es decir, instalar los componentes necesarios para poder hacer llamadas a Oracle desde PHP usando el instantclient que acabamos de instalar (con lo fácil que es hacer esto mismo con MySQL o PostgreSQL…, las cosas del software cerrado).
Suponemos que tenemos instalado Apache2 y PHP, pero aún así instalaremos dos paquetes más:
# yum install php-pear php5-devPHP-PEAR es según definen sus siglas: PHP Extension and Application Repository, es decir, un repositorio de extensiones y aplicaciones para PHP que nos permite instalar sin problemas ciertos componentes de PHP que no podemos instalar a través de nuestro gestor de paquetes habitual (me recuerda a CPAN con Perl, pero esa es otra historia para otra entrada).
# apt-get install php-pear php5-dev
Ya estamos en disposición de ejecutarlo para instalar OCI:
pecl install oci8En la terminal nos aparecerá algo así como:
1-1, ‘all’, ‘abort’, or Enter to continue:Pulsamos “1″ luego ENTER y escribimos las siguientes opciones (debemos saber el PATH exacto de nuestras librerías Oracle, cambiará en función de la versión):
shared,instantclient,/usr/lib/oracle/mi_version/client/lib/PHP-PEAR descargará, configurará, compilará e instalará el módulo. Finalmente, tenemos que añadir a nuestro fichero php.ini una línea para que cargue la librería dinámica de OCI y puedan hacerse llamadas desde los ficheros PHP.
La ruta del fichero será: /etc/php5/apache2/php.ini y la línea a agregar junto a las demás extensiones la siguiente:
extension=oci8.soReiniciamos el servidor web y listo:
services httpd restartO:
/etc/init.d/apache2 reload
21 jul 2011
3 jun 2011
PHP date difference
Step 1 - PHP date difference
Code:
// Get current time // Get the timestamp of 2006 October 20 ?>
Code:
$dateDiff = $date1 - $date2; echo "Differernce is $fullDays days"; ?>
As next step we need to get how many hours are still present in the remaining seconds. So from the original difference we need to remove the complete days in seconds and from the remaining value we can calculate the full hours similar to as we calculated the full days. Repeating these steps for minutes as well at the end we get the difference between the original dates. The complete calculation looks like this:
Code:
$dateDiff = $date1 - $date2; echo "Differernce is $fullDays days, $fullHours hours and $fullMinutes minutes."; ?>
31 may 2011
PHP: Sorting Arrays - Manual
Sorting Arrays
- Some sort based on the array keys, whereas others by the values: $array['key'] = 'value';
- Whether or not the correlation between the keys and values are maintained after the sort, which may mean the keys are reset numerically (0,1,2 ...)
- The order of the sort: alphabetical, low to high (ascending), high to low (descending), numerical, natural, random, or user defined
- Note: All of these sort functions act directly on the array variable itself, as opposed to returning a new sorted array
- If any of these sort functions evaluates two members as equal then the order is undefined (the sorting is not stable).
Function name | Sorts by | Maintains key association | Order of sort | Related functions |
---|---|---|---|---|
array_multisort() | value | associative yes, numeric no | first array or sort options | array_walk() |
asort() | value | yes | low to high | arsort() |
arsort() | value | yes | high to low | asort() |
krsort() | key | yes | high to low | ksort() |
ksort() | key | yes | low to high | asort() |
natcasesort() | value | yes | natural, case insensitive | natsort() |
natsort() | value | yes | natural | natcasesort() |
rsort() | value | no | high to low | sort() |
shuffle() | value | no | random | array_rand() |
sort() | value | no | low to high | rsort() |
uasort() | value | yes | user defined | uksort() |
uksort() | key | yes | user defined | uasort() |
usort() | value | no | user defined | uasort() |
10 may 2011
CCK Overview and Structure | drupal.org
CCK Overview and Structure
- Drupal version: Drupal 4.7.x, Drupal 5.x
- Page status: Needs updating
- Last modified: December 4, 2008
Overview
CCK is comprised of 2 things:- fields: These refer to the data that's being stored. For example, Text or Number.
- widgets: These refer to how the input widget an end user uses to enter the data looks. For example, Text field or Check boxes.
Data Model
CCK's data model consists of 3 base tables:
- node_type_content: A table containing the CCK node type defninitions: name, label, description, help, and the label given to the node's Title field.
- node_field: A table containing the various field definitions: field name, type, and various settings.
- node_field_instance: An individual instance of a field applied to a content type, along with its widget settings. For example, field_description in the content_blog type and field_description in the content_product type.
If, however, a field is shared among more than one content type, a table called node_data_field_X, where X is the name of the field, is also created to track the field's settings between node types.
Hooks
Note: More detailed hook information is available from the file field.php in the CCK module.Fields
- hook_field_info(): Here you declare the label for your field type(s). This will show up when you click "add field" on a CCK content type.
- hook_field_settings($op, $field): Handles displaying, validating, and saving field settings forms. In addition, manages how they're stored in the database and provides Views integration.
- hook_field($op, &$node, $field, &$node_field, $teaser, $page): Define the behavior of a field type.
- hook_field_formatter_info(): Declare information about a formatter.
- hook_field_formatter($field, $item, $formatter, $node): Prepare an individual item for viewing in a browser.
Widgets
- hook_widget_info(): Here you declare any widgets associated with your field type. These will show up below the fields when you click "add field" on a CCK content type in 4.7.x and 5.x. Fields show up in the first drop-down and widgets in the second drop down when adding content types in 6.x.
- hook_widget_settings($op, $widget): Handle the parameters for a widget.
- hook_widget: Define the behavior of a widget.
Tips
- While developing CCK, you may notice oddities such as settings you made not appearing and other such things. Always remember to clear your cache!
Comments
(BTW, what software did you use to create this beautiful diagram?)
Have you ever wondered about the "_value" suffix in column names?
A field's data may actually occupy more than one DB column. It's true that the simple Text and Number fields occupy only one column (field_X_value), but the more complex Date field, for example, occupies two DB columns: field_X_value and field_X_timezone.
There's nothing "holy" in a _value suffix:
Let's say I want to create a new field type: Color. This field will occupy three DB columns (for the red, green and blue intensities). I'll define my hook_field_settings as:
function color_field_settings($op, ...) {
switch($op) {
...
case 'database columns':
return array(
'red' => array('type' => 'integer', ...),
'green' => array('type' => 'integer', ...),
'blue' => array('type' => 'integer', ...)
);
...
}
}?>
Similarly, the nodereference field doesn't define a "value" column. It defines "nid" instead:
function nodereference_field_settings($op, $field) {
switch($op) {
...
case 'database columns':
$columns = array(
'nid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
);
return $columns;
...
}
}?>
BTW, contrary to what I've said, the Text field is not so simple: it may occupy two DB columns if an input format may be applied to the string (that is, when the "Filtered text" option is selected).
(BTW #2, in my previous comment I said you should leave only one field (in CCK terms) in the diagram for the node_data_field_X table. But this one field may occupy several DB columns (depending on its type and settings)).
- First, create the new cck content type you want to move to (in this example, it ended up named 'content_event')
- CCK doesn't use the body field, so you need to add a cck text field for the body content. Give the field more than 1 line to make it a textarea instead of a textfield, and be sure to indicate that it uses filtering. Note the name of the field that is created. For my example, I created a field called 'field_description'.
- Create a test node to be sure that everything got set up correctly and that you can manually enter data into your new content type and that it gets saved correctly. Be sure that you get a textarea field instead of a textfield and that the filter is available for selection.
- Make a good backup of your database. Go ahead and make another one just in case :-)
- Now run the following code to change the data in the database.
// convert another node type to a cck type
$from_type = 'event';
$to_type = 'content_event';
// the name of the cck field that will hold the value of the node body
$to_body_field = 'field_description';
// pull up nodes with the old content type
$results = db_query("SELECT nid, title FROM node where type='$from_type' ORDER BY nid");
while ($arr = db_fetch_array($results)) {
$nid = $arr['nid'];
drupal_set_message('Converting '.$arr['nid'].': '.$arr['title']);
// create a cck record for this node and make sure it's not a duplicate
db_query("DELETE FROM node_".$to_type." WHERE nid=$nid");
db_query("INSERT INTO node_".$to_type." SET nid=$nid, vid=$nid");
// change the node type in the node table
db_query("UPDATE node SET type='$to_type' WHERE nid=$nid");
// move the value in node body to the cck body field
if ($to_body_field) {
$node = node_load($nid);
$results2 = db_query("SELECT format, body FROM node_revisions WHERE nid=$nid");
while ($arr2 = db_fetch_array($results2)) {
// if there is a body value save it to new field
if ($arr2['body'] > '') {
$node->$to_body_field = array(
0 => array(
'value' => $arr2['body'],
'format' => $arr2['format'],
),
);
node_save($node);
$node = node_load($nid);
$value = $node->$to_body_field;
if ($value[0]['value'] == $arr2['body'] && $value[0]['value'] > '') {
// if successful, erase the body and teaser (cck doesn't use them)
db_query("UPDATE node_revisions SET body='', teaser='' WHERE nid=$nid");
}
}
}
}
}
// update other tables that use content type name
db_query("UPDATE vocabulary_node_types SET type='$to_type' WHERE type='$from_type'");
$node->$to_body_field = array(
0 => array(
'value' => $arr2['body'],
'format' => $arr2['format'],
),
);
multiple values?
Can someone with more intimite knowledge of CCK shine some light on this 'multiple' thing?* what is it for?
* how should developers handle this when storing their own data in private tables?
---
Professional | Personal
| Sympal: Development and Hosting
What would be of use are examples of more complex relationships.
Similar fields with different means should be processed some other way and I am still looking for an example built with CCK. Suppose I have a Contact node and add a telephone field. I then want to have home and work numbers. I could change telephone to have multiple but that does not let me find out which is the work number. I could define separate fields named work_telephone and home_telephone but then I have to define the same format twice. It makes sense to define telephone then telephone.work and telephone.home to inherit telephone's attributes. I think that is where widgets are used. You define a widget to handle the telephone format then apply the one widget to both telephone fields.
What makes sense next, and again I have not found a current example implemented with CCK, is to have minimum and maximum entries in multiple. You might have a field xyz that has to have a minimum of two entries or a maximum of 10 entires. I am thinking of polls where you ask people to nominate their top 10 choices or emergency contact details where you might ask someone to nominate a minimum of two forms of contact.
Perhaps we could start pages in the CCK documentation with the questions and leave space for more experienced users to add the answers.
petermoulding.com/web_architect
An example in my case is "People attending Events":
Many people can attend an event, and many events can be attended by one person.
In the database, as mentioned before, a new table is created which has foreign keys for both person and event. This means the many-to-many relationship can exist without having to have a 'list' in a field (thus keeping it 3rd Normal Form).
What I'm saying is, the multiple values thing is essential (at least for me :)
Thanks for the documentation. I didn't realise this was here until now - figured it all out from poking around the database...
23 abr 2010
PHP: preg_match - Manual
Description
Searches subject for a match to the regular expression given in pattern.
Parameters
- pattern
-
The pattern to search for, as a string.
- subject
-
The input string.
- matches
-
If matches is provided, then it is filled with the results of search. $matches[0] will contain the text that matched the full pattern, $matches[1] will have the text that matched the first captured parenthesized subpattern, and so on.
- flags
-
flags can be the following flag:
- PREG_OFFSET_CAPTURE
- If this flag is passed, for every occurring match the appendant string offset will also be returned. Note that this changes the value of matches into an array where every element is an array consisting of the matched string at offset 0 and its string offset into subject at offset 1.
- offset
-
Normally, the search starts from the beginning of the subject string. The optional parameter offset can be used to specify the alternate place from which to start the search (in bytes).
Note: Using offset is not equivalent to passing substr($subject, $offset) to preg_match() in place of the subject string, because pattern can contain assertions such as ^, $ or (?<=x). Compare:
= "abcdef";
$pattern = '/^def/';
preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, 3);
print_r($matches);
?>The above example will output:
Array
(
)while this example
= "abcdef";
$pattern = '/^def/';
preg_match($pattern, substr($subject,3), $matches, PREG_OFFSET_CAPTURE);
print_r($matches);
?>will produce
Array
(
[0] => Array
(
[0] => def
[1] => 0
)
)
Return Values
preg_match() returns the number of times pattern matches. That will be either 0 times (no match) or 1 time because preg_match() will stop searching after the first match. preg_match_all() on the contrary will continue until it reaches the end of subject. preg_match() returns FALSE if an error occurred.
Examples
Example #1 Find the string of text "php"
// The "i" after the pattern delimiter indicates a case-insensitive search
if (preg_match("/php/i", "PHP is the web scripting language of choice.")) {
echo "A match was found.";
} else {
echo "A match was not found.";
}
?>
Example #2 Find the word "web"
/* The \b in the pattern indicates a word boundary, so only the distinct
* word "web" is matched, and not a word partial like "webbing" or "cobweb" */
if (preg_match("/\bweb\b/i", "PHP is the web scripting language of choice.")) {
echo "A match was found.";
} else {
echo "A match was not found.";
}
if (preg_match("/\bweb\b/i", "PHP is the website scripting language of choice.")) {
echo "A match was found.";
} else {
echo "A match was not found.";
}
?>
Example #3 Getting the domain name out of a URL
// get host name from URL
preg_match('@^(?:http://)?([^/]+)@i',
"http://www.php.net/index.html", $matches);
$host = $matches[1];
// get last two segments of host name
preg_match('/[^.]+\.[^.]+$/', $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>
The above example will output:
domain name is: php.net
Example #4 Using named subpattern
= 'foobar: 2008';
preg_match('/(?P\w+): (?P\d+)/' , $str, $matches);
/* This also works in PHP 5.2.2 (PCRE 7.0) and later, however
* the above form is recommended for backwards compatibility */
// preg_match('/(?\w+): (?\d+)/', $str, $matches);
print_r($matches);
?>
The above example will output:
The effect of the "Multiple values" field setting
The node_data_field_X table is also created when the field is of type "Multiple values". This happens even if the field is not shared among content types.
When the field is multiple-valued, the node_data_field_X table contains an additional column: delta.