() translation by (you can also view the original English article)
Con la estructura básica de nuestro Marco en su lugar, es hora de comenzar a agregarle funcionalidad. En este tutorial, crearemos un administrador de plantillas y un controlador de base de datos, que nos acercará un paso más hacia un potente Framework adecuado para casi cualquier proyecto. Si aún no lo ha hecho, asegúrese de revisar la Parte 1 de esta serie primero.
MVC: Ajustar la estructura
En la primera parte de este tutorial, creamos una carpeta llamada controladores para almacenar la lógica de negocios para nuestras aplicaciones. Como señaló Daok en un comentario, este no es el mejor lugar para toda la lógica de negocios, y ese modelo debería usarse para almacenar esta lógica. Anteriormente, siempre he usado la base de datos como el modelo en la mayoría de mis aplicaciones, sin embargo, separar esto un poco más hará que nuestro marco sea más poderoso y más fácil de extender.
Entonces, ¿qué es MVC? MVC es un patrón de diseño (como lo fueron los patrones Singleton y Registry que vimos en la parte 1), y significa Model View Controller, y el objetivo de este patrón es separar la lógica empresarial, las acciones de la interfaz de usuario y la interfaz de usuario de unos y otros. Aunque todavía no vamos a hacer nada con nuestros modelos y controladores, actualicemos nuestra estructura de carpetas de marcos para incluir la carpeta "modelos". El modelo contendrá la lógica de negocios principal, y el controlador tratará la interacción del usuario (por ejemplo, el envío de datos, como un comentario). NB: No es necesario cambiar nuestra función __autoload.



Operaciones de base de datos
La mayoría de los sitios web y aplicaciones web que utilizan PHP también utilizan un motor de base de datos, como MySQL. Si mantenemos todas nuestras funciones relacionadas con la base de datos en el mismo lugar, entonces podemos (en teoría) cambiar fácilmente el motor de base de datos que utilizamos. También podemos facilitar ciertas operaciones, como insertar registros, actualizar registros o eliminar registros de la base de datos. También puede hacerlo más fácil cuando se trata de conexiones de base de datos múltiples.
Entonces ... ¿qué debe hacer nuestro controlador de base de datos:
- Gestionar conexiones a la base de datos.
- Trate de proporcionar algún nivel de abstracción de la base de datos
- Consultas de caché para que podamos usarlas más tarde.
- Facilita las operaciones comunes de la base de datos.
Veamos el código de nuestro manejador de bases de datos, luego lo discutiremos.
1 |
|
2 |
<?php
|
3 |
|
4 |
/**
|
5 |
* Database management and access class
|
6 |
* This is a very basic level of abstraction
|
7 |
*/
|
8 |
class database { |
9 |
|
10 |
/**
|
11 |
* Allows multiple database connections
|
12 |
* probably not used very often by many applications, but still useful
|
13 |
*/
|
14 |
private $connections = array(); |
15 |
|
16 |
/**
|
17 |
* Tells the DB object which connection to use
|
18 |
* setActiveConnection($id) allows us to change this
|
19 |
*/
|
20 |
private $activeConnection = 0; |
21 |
|
22 |
/**
|
23 |
* Queries which have been executed and then "saved for later"
|
24 |
*/
|
25 |
private $queryCache = array(); |
26 |
|
27 |
/**
|
28 |
* Data which has been prepared and then "saved for later"
|
29 |
*/
|
30 |
private $dataCache = array(); |
31 |
|
32 |
/**
|
33 |
* Record of the last query
|
34 |
*/
|
35 |
private $last; |
36 |
|
37 |
|
38 |
/**
|
39 |
* Hello
|
40 |
*/
|
41 |
public function __construct() |
42 |
{
|
43 |
|
44 |
}
|
45 |
|
46 |
/**
|
47 |
* Create a new database connection
|
48 |
* @param String database hostname
|
49 |
* @param String database username
|
50 |
* @param String database password
|
51 |
* @param String database we are using
|
52 |
* @return int the id of the new connection
|
53 |
*/
|
54 |
public function newConnection( $host, $user, $password, $database ) |
55 |
{
|
56 |
$this->connections[] = new mysqli( $host, $user, $password, $database ); |
57 |
$connection_id = count( $this->connections )-1; |
58 |
if( mysqli_connect_errno() ) |
59 |
{
|
60 |
trigger_error('Error connecting to host. '.$this->connections[$connection_id]->error, E_USER_ERROR); |
61 |
}
|
62 |
|
63 |
return $connection_id; |
64 |
}
|
65 |
|
66 |
/**
|
67 |
* Close the active connection
|
68 |
* @return void
|
69 |
*/
|
70 |
public function closeConnection() |
71 |
{
|
72 |
$this->connections[$this->activeConnection]->close(); |
73 |
}
|
74 |
|
75 |
/**
|
76 |
* Change which database connection is actively used for the next operation
|
77 |
* @param int the new connection id
|
78 |
* @return void
|
79 |
*/
|
80 |
public function setActiveConnection( int $new ) |
81 |
{
|
82 |
$this->activeConnection = $new; |
83 |
}
|
84 |
|
85 |
/**
|
86 |
* Store a query in the query cache for processing later
|
87 |
* @param String the query string
|
88 |
* @return the pointed to the query in the cache
|
89 |
*/
|
90 |
public function cacheQuery( $queryStr ) |
91 |
{
|
92 |
if( !$result = $this->connections[$this->activeConnection]->query( $queryStr ) ) |
93 |
{
|
94 |
trigger_error('Error executing and caching query: '.$this->connections[$this->activeConnection]->error, E_USER_ERROR); |
95 |
return -1; |
96 |
}
|
97 |
else
|
98 |
{
|
99 |
$this->queryCache[] = $result; |
100 |
return count($this->queryCache)-1; |
101 |
}
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
* Get the number of rows from the cache
|
106 |
* @param int the query cache pointer
|
107 |
* @return int the number of rows
|
108 |
*/
|
109 |
public function numRowsFromCache( $cache_id ) |
110 |
{
|
111 |
return $this->queryCache[$cache_id]->num_rows; |
112 |
}
|
113 |
|
114 |
/**
|
115 |
* Get the rows from a cached query
|
116 |
* @param int the query cache pointer
|
117 |
* @return array the row
|
118 |
*/
|
119 |
public function resultsFromCache( $cache_id ) |
120 |
{
|
121 |
return $this->queryCache[$cache_id]->fetch_array(MYSQLI_ASSOC); |
122 |
}
|
123 |
|
124 |
/**
|
125 |
* Store some data in a cache for later
|
126 |
* @param array the data
|
127 |
* @return int the pointed to the array in the data cache
|
128 |
*/
|
129 |
public function cacheData( $data ) |
130 |
{
|
131 |
$this->dataCache[] = $data; |
132 |
return count( $this->dataCache )-1; |
133 |
}
|
134 |
|
135 |
/**
|
136 |
* Get data from the data cache
|
137 |
* @param int data cache pointed
|
138 |
* @return array the data
|
139 |
*/
|
140 |
public function dataFromCache( $cache_id ) |
141 |
{
|
142 |
return $this->dataCache[$cache_id]; |
143 |
}
|
144 |
|
145 |
/**
|
146 |
* Delete records from the database
|
147 |
* @param String the table to remove rows from
|
148 |
* @param String the condition for which rows are to be removed
|
149 |
* @param int the number of rows to be removed
|
150 |
* @return void
|
151 |
*/
|
152 |
public function deleteRecords( $table, $condition, $limit ) |
153 |
{
|
154 |
$limit = ( $limit == '' ) ? '' : ' LIMIT ' . $limit; |
155 |
$delete = "DELETE FROM {$table} WHERE {$condition} {$limit}"; |
156 |
$this->executeQuery( $delete ); |
157 |
}
|
158 |
|
159 |
/**
|
160 |
* Update records in the database
|
161 |
* @param String the table
|
162 |
* @param array of changes field => value
|
163 |
* @param String the condition
|
164 |
* @return bool
|
165 |
*/
|
166 |
public function updateRecords( $table, $changes, $condition ) |
167 |
{
|
168 |
$update = "UPDATE " . $table . " SET "; |
169 |
foreach( $changes as $field => $value ) |
170 |
{
|
171 |
$update .= "`" . $field . "`='{$value}',"; |
172 |
}
|
173 |
|
174 |
// remove our trailing ,
|
175 |
$update = substr($update, 0, -1); |
176 |
if( $condition != '' ) |
177 |
{
|
178 |
$update .= "WHERE " . $condition; |
179 |
}
|
180 |
|
181 |
$this->executeQuery( $update ); |
182 |
|
183 |
return true; |
184 |
|
185 |
}
|
186 |
|
187 |
/**
|
188 |
* Insert records into the database
|
189 |
* @param String the database table
|
190 |
* @param array data to insert field => value
|
191 |
* @return bool
|
192 |
*/
|
193 |
public function insertRecords( $table, $data ) |
194 |
{
|
195 |
// setup some variables for fields and values
|
196 |
$fields = ""; |
197 |
$values = ""; |
198 |
|
199 |
// populate them
|
200 |
foreach ($data as $f => $v) |
201 |
{
|
202 |
|
203 |
$fields .= "`$f`,"; |
204 |
$values .= ( is_numeric( $v ) && ( intval( $v ) == $v ) ) ? $v."," : "'$v',"; |
205 |
|
206 |
}
|
207 |
|
208 |
// remove our trailing ,
|
209 |
$fields = substr($fields, 0, -1); |
210 |
// remove our trailing ,
|
211 |
$values = substr($values, 0, -1); |
212 |
|
213 |
$insert = "INSERT INTO $table ({$fields}) VALUES({$values})"; |
214 |
$this->executeQuery( $insert ); |
215 |
return true; |
216 |
}
|
217 |
|
218 |
/**
|
219 |
* Execute a query string
|
220 |
* @param String the query
|
221 |
* @return void
|
222 |
*/
|
223 |
public function executeQuery( $queryStr ) |
224 |
{
|
225 |
if( !$result = $this->connections[$this->activeConnection]->query( $queryStr ) ) |
226 |
{
|
227 |
trigger_error('Error executing query: '.$this->connections[$this->activeConnection]->error, E_USER_ERROR); |
228 |
}
|
229 |
else
|
230 |
{
|
231 |
$this->last = $result; |
232 |
}
|
233 |
|
234 |
}
|
235 |
|
236 |
/**
|
237 |
* Get the rows from the most recently executed query, excluding cached queries
|
238 |
* @return array
|
239 |
*/
|
240 |
public function getRows() |
241 |
{
|
242 |
return $this->last->fetch_array(MYSQLI_ASSOC); |
243 |
}
|
244 |
|
245 |
/**
|
246 |
* Gets the number of affected rows from the previous query
|
247 |
* @return int the number of affected rows
|
248 |
*/
|
249 |
public function affectedRows() |
250 |
{
|
251 |
return $this->$this->connections[$this->activeConnection]->affected_rows; |
252 |
}
|
253 |
|
254 |
/**
|
255 |
* Sanitize data
|
256 |
* @param String the data to be sanitized
|
257 |
* @return String the sanitized data
|
258 |
*/
|
259 |
public function sanitizeData( $data ) |
260 |
{
|
261 |
return $this->connections[$this->activeConnection]->real_escape_string( $data ); |
262 |
}
|
263 |
|
264 |
/**
|
265 |
* Deconstruct the object
|
266 |
* close all of the database connections
|
267 |
*/
|
268 |
public function __deconstruct() |
269 |
{
|
270 |
foreach( $this->connections as $connection ) |
271 |
{
|
272 |
$connection->close(); |
273 |
}
|
274 |
}
|
275 |
}
|
276 |
?>
|
Antes de discutir esto con más detalle, debo señalar que este controlador de base de datos es muy básico. Podríamos proporcionar una abstracción completa no ejecutando consultas directamente, sino construyendo consultas basadas en parámetros para una función de consulta y luego ejecutándolas.
Nuestros métodos de borrado, inserción y actualización de registros facilitan la realización de algunas tareas comunes (como mencioné anteriormente, podríamos extender esto para hacer mucho más), al proporcionar solo información como el nombre de la tabla, una matriz de campos y valores correspondientes Valores y condiciones límite. Las consultas también se pueden "almacenar en caché" para que podamos hacer cosas con ellas más adelante. Considero que esta característica (así como la capacidad de "almacenar en caché" arreglos de datos) es muy útil cuando se combina con un administrador de plantillas, ya que podemos iterar fácilmente a través de filas de datos y rellenarla en nuestras plantillas con poco problema, como lo harás Ver cuando nos fijamos en el gestor de plantillas.
1 |
|
2 |
// insert record
|
3 |
$registry->getObject('db')->insertRecords( 'testTable', array('name'=>'Michael' ) ); |
4 |
// update a record
|
5 |
$registry->getObject('db')->updateRecords( 'testTable', array('name'=>'MichaelP' ), 'ID=2' ); |
6 |
// delete a record (well, upto 5 in this case)
|
7 |
$registry->getObject('db')->deleteRecords( 'testTable', "name='MichaelP'", 5 ); |
También podemos trabajar con múltiples conexiones de base de datos con relativa facilidad, siempre que cambiemos entre las conexiones adecuadas cuando sea necesario (aunque esto no funcionará cuando las consultas en caché se recuperen a través de nuestro administrador de plantillas sin más trabajo), por ejemplo, El siguiente fragmento de código nos permitiría eliminar registros de dos bases de datos.
1 |
|
2 |
// our second database connection (let's assume we already have a connection to our main DB)
|
3 |
$newConnection = $registry->getObject('db')->newConnection('localhost', 'root', 'password', 'secondDB'); |
4 |
// delete from the primary db connection
|
5 |
$registry->getObject('db')->deleteRecords( 'testTable', "name='MichaelP'", 5 ); |
6 |
// change our active db connection, to allow future queries to be on the second connection
|
7 |
$registry->getObject('db')->setActiveConnection( $newConnection ); |
8 |
// delete from the secondary db connection
|
9 |
$registry->getObject('db')->deleteRecords( 'testTable', "name='MichaelP'", 5 ); |
10 |
// revert the active connection so future queries are on the primary db connection
|
11 |
$registry->getObject('db')->setActiveConnection( 0 ); |
¿Cómo podríamos querer extender esta clase?
- Abstracción completa
- Haga uso de la herencia, cree una interfaz y haga heredar las clases de la base de datos, cada una para los diferentes motores de base de datos
- Almacene los identificadores de conexión junto con la consulta al almacenar en caché las consultas
- Mejorar la desinfección de datos, según el tipo de datos que deseamos sanear.
Administrador de plantillas
El administrador de plantillas manejará toda la salida, debe poder trabajar con varios archivos de plantillas diferentes, reemplazar los marcadores de posición (los llamo etiquetas) con datos e iterar a través de partes de la plantilla con varias filas de datos de la base de datos.
Para facilitar las cosas, utilizaremos una clase de página para contener el contenido relacionado con la página, esto también nos facilita ampliarlo y agregarle funciones más adelante. El gestor de plantillas gestionará este objeto.
1 |
|
2 |
<?php
|
3 |
|
4 |
// prevent this file being called directly
|
5 |
if ( ! defined( 'PCAFW' ) ) |
6 |
{
|
7 |
echo 'This file can only be called via the main index.php file, and not directly'; |
8 |
exit(); |
9 |
}
|
10 |
|
11 |
/**
|
12 |
* Template manager class
|
13 |
*/
|
14 |
class template { |
15 |
|
16 |
private $page; |
17 |
|
18 |
/**
|
19 |
* Hello!
|
20 |
*/
|
21 |
public function __construct() |
22 |
{
|
23 |
include( APP_PATH . '/PCARegistry/objects/page.class.php'); |
24 |
$this->page = new Page(); |
25 |
|
26 |
}
|
27 |
|
28 |
/**
|
29 |
* Add a template bit onto our page
|
30 |
* @param String $tag the tag where we insert the template e.g. {hello}
|
31 |
* @param String $bit the template bit (path to file, or just the filename)
|
32 |
* @return void
|
33 |
*/
|
34 |
public function addTemplateBit( $tag, $bit ) |
35 |
{
|
36 |
if( strpos( $bit, 'skins/' ) === false ) |
37 |
{
|
38 |
$bit = 'skins/' . PCARegistry::getSetting('skin') . '/templates/' . $bit; |
39 |
}
|
40 |
$this->page->addTemplateBit( $tag, $bit ); |
41 |
}
|
42 |
|
43 |
/**
|
44 |
* Put the template bits into our page content
|
45 |
* Updates the pages content
|
46 |
* @return void
|
47 |
*/
|
48 |
private function replaceBits() |
49 |
{
|
50 |
$bits = $this->page->getBits(); |
51 |
foreach( $bits as $tag => $template ) |
52 |
{
|
53 |
$templateContent = file_get_contents( $bit ); |
54 |
$newContent = str_replace( '{' . $tag . '}', $templateContent, $this->page->getContent() ); |
55 |
$this->page->setContent( $newContent ); |
56 |
}
|
57 |
}
|
58 |
|
59 |
/**
|
60 |
* Replace tags in our page with content
|
61 |
* @return void
|
62 |
*/
|
63 |
private function replaceTags() |
64 |
{
|
65 |
// get the tags
|
66 |
$tags = $this->page->getTags(); |
67 |
// go through them all
|
68 |
foreach( $tags as $tag => $data ) |
69 |
{
|
70 |
if( is_array( $data ) ) |
71 |
{
|
72 |
|
73 |
if( $data[0] == 'SQL' ) |
74 |
{
|
75 |
// it is a cached query...replace DB tags
|
76 |
$this->replaceDBTags( $tag, $data[1] ); |
77 |
}
|
78 |
elseif( $data[0] == 'DATA' ) |
79 |
{
|
80 |
// it is some cached data...replace data tags
|
81 |
$this->replaceDataTags( $tag, $data[1] ); |
82 |
}
|
83 |
}
|
84 |
else
|
85 |
{
|
86 |
// replace the content
|
87 |
$newContent = str_replace( '{' . $tag . '}', $data, $this->page->getContent() ); |
88 |
// update the pages content
|
89 |
$this->page->setContent( $newContent ); |
90 |
}
|
91 |
}
|
92 |
}
|
93 |
|
94 |
/**
|
95 |
* Replace content on the page with data from the DB
|
96 |
* @param String $tag the tag defining the area of content
|
97 |
* @param int $cacheId the queries ID in the query cache
|
98 |
* @return void
|
99 |
*/
|
100 |
private function replaceDBTags( $tag, $cacheId ) |
101 |
{
|
102 |
$block = ''; |
103 |
$blockOld = $this->page->getBlock( $tag ); |
104 |
|
105 |
// foreach record relating to the query...
|
106 |
while ($tags = PCARegistry::getObject('db')->resultsFromCache( $cacheId ) ) |
107 |
{
|
108 |
$blockNew = $blockOld; |
109 |
// create a new block of content with the results replaced into it
|
110 |
foreach ($tags as $ntag => $data) |
111 |
{
|
112 |
$blockNew = str_replace("{" . $ntag . "}", $data, $blockNew); |
113 |
}
|
114 |
$block .= $blockNew; |
115 |
}
|
116 |
$pageContent = $this->page->getContent(); |
117 |
// remove the seperator in the template, cleaner HTML
|
118 |
$newContent = str_replace( '<!-- START ' . $tag . ' -->' . $blockOld . '<!-- END ' . $tag . ' -->', $block, $pageContent ); |
119 |
// update the page content
|
120 |
$this->page->setContent( $newContent ); |
121 |
}
|
122 |
|
123 |
/**
|
124 |
* Replace content on the page with data from the cache
|
125 |
* @param String $tag the tag defining the area of content
|
126 |
* @param int $cacheId the datas ID in the data cache
|
127 |
* @return void
|
128 |
*/
|
129 |
private function replaceDataTags( $tag, $cacheId ) |
130 |
{
|
131 |
$block = $this->page->getBlock( $tag ); |
132 |
$blockOld = $block; |
133 |
while ($tags = PCARegistry::getObject('db')->dataFromCache( $cacheId ) ) |
134 |
{
|
135 |
foreach ($tags as $tag => $data) |
136 |
{
|
137 |
$blockNew = $blockOld; |
138 |
$blockNew = str_replace("{" . $tag . "}", $data, $blockNew); |
139 |
}
|
140 |
$block .= $blockNew; |
141 |
}
|
142 |
$pageContent = $this->page->getContent(); |
143 |
$newContent = str_replace( $blockOld, $block, $pageContent ); |
144 |
$this->page->setContent( $newContent ); |
145 |
}
|
146 |
|
147 |
/**
|
148 |
* Get the page object
|
149 |
* @return Object
|
150 |
*/
|
151 |
public function getPage() |
152 |
{
|
153 |
return $this->page; |
154 |
}
|
155 |
|
156 |
/**
|
157 |
* Set the content of the page based on a number of templates
|
158 |
* pass template file locations as individual arguments
|
159 |
* @return void
|
160 |
*/
|
161 |
public function buildFromTemplates() |
162 |
{
|
163 |
$bits = func_get_args(); |
164 |
$content = ""; |
165 |
foreach( $bits as $bit ) |
166 |
{
|
167 |
|
168 |
if( strpos( $bit, 'skins/' ) === false ) |
169 |
{
|
170 |
$bit = 'skins/' . PCARegistry::getSetting('skin') . '/templates/' . $bit; |
171 |
}
|
172 |
if( file_exists( $bit ) == true ) |
173 |
{
|
174 |
$content .= file_get_contents( $bit ); |
175 |
}
|
176 |
|
177 |
}
|
178 |
$this->page->setContent( $content ); |
179 |
}
|
180 |
|
181 |
/**
|
182 |
* Convert an array of data (i.e. a db row?) to some tags
|
183 |
* @param array the data
|
184 |
* @param string a prefix which is added to field name to create the tag name
|
185 |
* @return void
|
186 |
*/
|
187 |
public function dataToTags( $data, $prefix ) |
188 |
{
|
189 |
foreach( $data as $key => $content ) |
190 |
{
|
191 |
$this->page->addTag( $key.$prefix, $content); |
192 |
}
|
193 |
}
|
194 |
|
195 |
public function parseTitle() |
196 |
{
|
197 |
$newContent = str_replace('<title>', '<title>'. $page->getTitle(), $this->page->getContent() ); |
198 |
$this->page->setContent( $newContent ); |
199 |
}
|
200 |
|
201 |
/**
|
202 |
* Parse the page object into some output
|
203 |
* @return void
|
204 |
*/
|
205 |
public function parseOutput() |
206 |
{
|
207 |
$this->replaceBits(); |
208 |
$this->replaceTags(); |
209 |
$this->parseTitle(); |
210 |
}
|
211 |
|
212 |
|
213 |
|
214 |
}
|
215 |
?>
|
Entonces, ¿qué hace exactamente esta clase?
Crea nuestro objeto de página y lo basa en archivos de plantilla, el objeto de página contiene el contenido y la información que se necesita para crear el HTML de la página. Luego, creamosFromTemplate ('templatefile.tpl.php', 'templatefile2.tpl.php') para obtener el contenido inicial de nuestra página, este método toma cualquier número de archivos de plantilla como sus argumentos y los unimos en orden, útil para Plantillas de encabezado, contenido y pie de página.
Administra el contenido asociado con la página ayudando al objeto de la página a mantener un registro de los datos que se van a reemplazar en la página, y también los bits de plantilla adicionales que deben incorporarse en la página (addTemplateBit ('barra de usuario', 'usertoolsbar.tpl.php ')).
Agrega datos y contenido a la página realizando varias operaciones de reemplazo en el contenido de la página, incluida la recuperación de resultados de una consulta en caché y la adición a la página.
El archivo de la plantilla debe marcarse dentro de sí mismo cuando sea necesario recuperar una consulta en caché y reemplazar los datos de la consulta. Cuando el administrador de plantillas encuentra una etiqueta para reemplazar la que es una consulta, obtiene la porción de la página donde necesita iterar llamando a getBlock ("bloque") en el objeto de la página. Esta porción de contenido luego se copia para cada registro en la consulta, y tiene etiquetas reemplazadas con los resultados de la consulta. Veremos cómo se ve esto en la plantilla más adelante en este tutorial.
Administrador de plantillas: Página
El administrador de plantillas gestiona el objeto de la página y se utiliza para contener todos los detalles relacionados con la página. Esto permite que el administrador de plantillas se pueda administrar libremente, y nos facilita la extensión de la funcionalidad en una fecha posterior.
1 |
|
2 |
<?php
|
3 |
|
4 |
/**
|
5 |
* This is our page object
|
6 |
* It is a seperate object to allow some interesting extra functionality to be added
|
7 |
* Some ideas: passwording pages, adding page specific css/js files, etc
|
8 |
*/
|
9 |
class page { |
10 |
|
11 |
// room to grow later?
|
12 |
private $css = array(); |
13 |
private $js = array(); |
14 |
private $bodyTag = ''; |
15 |
private $bodyTagInsert = ''; |
16 |
|
17 |
// future functionality?
|
18 |
private $authorised = true; |
19 |
private $password = ''; |
20 |
|
21 |
// page elements
|
22 |
private $title = ''; |
23 |
private $tags = array(); |
24 |
private $postParseTags = array(); |
25 |
private $bits = array(); |
26 |
private $content = ""; |
27 |
|
28 |
/**
|
29 |
* Constructor...
|
30 |
*/
|
31 |
function __construct() { } |
32 |
|
33 |
public function getTitle() |
34 |
{
|
35 |
return $this->title; |
36 |
}
|
37 |
|
38 |
public function setPassword( $password ) |
39 |
{
|
40 |
$this->password = $password; |
41 |
}
|
42 |
|
43 |
public function setTitle( $title ) |
44 |
{
|
45 |
$this->title = $title; |
46 |
}
|
47 |
|
48 |
public function setContent( $content ) |
49 |
{
|
50 |
$this->content = $content; |
51 |
}
|
52 |
|
53 |
public function addTag( $key, $data ) |
54 |
{
|
55 |
$this->tags[$key] = $data; |
56 |
}
|
57 |
|
58 |
public function getTags() |
59 |
{
|
60 |
return $this->tags; |
61 |
}
|
62 |
|
63 |
public function addPPTag( $key, $data ) |
64 |
{
|
65 |
$this->postParseTags[$key] = $data; |
66 |
}
|
67 |
|
68 |
/**
|
69 |
* Get tags to be parsed after the first batch have been parsed
|
70 |
* @return array
|
71 |
*/
|
72 |
public function getPPTags() |
73 |
{
|
74 |
return $this->postParseTags; |
75 |
}
|
76 |
|
77 |
/**
|
78 |
* Add a template bit to the page, doesnt actually add the content just yet
|
79 |
* @param String the tag where the template is added
|
80 |
* @param String the template file name
|
81 |
* @return void
|
82 |
*/
|
83 |
public function addTemplateBit( $tag, $bit ) |
84 |
{
|
85 |
$this->bits[ $tag ] = $bit; |
86 |
}
|
87 |
|
88 |
/**
|
89 |
* Get the template bits to be entered into the page
|
90 |
* @return array the array of template tags and template file names
|
91 |
*/
|
92 |
public function getBits() |
93 |
{
|
94 |
return $this->bits; |
95 |
}
|
96 |
|
97 |
/**
|
98 |
* Gets a chunk of page content
|
99 |
* @param String the tag wrapping the block ( <!-- START tag --> block <!-- END tag --> )
|
100 |
* @return String the block of content
|
101 |
*/
|
102 |
public function getBlock( $tag ) |
103 |
{
|
104 |
preg_match ('#<!-- START '. $tag . ' -->(.+?)<!-- END '. $tag . ' -->#si', $this->content, $tor); |
105 |
|
106 |
$tor = str_replace ('<!-- START '. $tag . ' -->', "", $tor[0]); |
107 |
$tor = str_replace ('<!-- END ' . $tag . ' -->', "", $tor); |
108 |
|
109 |
return $tor; |
110 |
}
|
111 |
|
112 |
public function getContent() |
113 |
{
|
114 |
return $this->content; |
115 |
}
|
116 |
|
117 |
}
|
118 |
?>
|
¿Cómo se puede ampliar y mejorar esta clase?
- PostParseTags: es posible que desee reemplazar las etiquetas después de que se haya analizado la mayor parte de la página, tal vez el contenido de la base de datos contenga etiquetas que deban analizarse.
- Páginas con contraseña: asigne una contraseña a una página, verifique si el usuario tiene la contraseña en una cookie o una sesión para que puedan ver la página.
- Páginas restringidas (¡aunque primero necesitamos nuestros componentes de autenticación!)
- Alterando el
- Agregar dinámicamente referencias a archivos javascript y css basados en la página o la aplicación.
Cargar objetos centrales
Ahora que tenemos algunos objetos que nuestro registro va a almacenar para nosotros, necesitamos decirle al registro qué objetos son. He creado un método en el objeto PCARegistry llamado loadCoreObjects que (como dice) carga los objetos centrales. Esto significa que puede simplemente llamar a esto desde nuestro archivo index.php para cargar el registro con estos objetos.
1 |
|
2 |
public function storeCoreObjects() |
3 |
{
|
4 |
$this->storeObject('database', 'db' ); |
5 |
$this->storeObject('template', 'template' ); |
6 |
}
|
Este método se puede modificar más adelante para incorporar los otros objetos centrales que debe cargar el registro, por supuesto, puede haber objetos que queremos que nuestro registro administre, pero solo dependiendo de la aplicación para la que se use el marco. Estos objetos se cargarían fuera de este método.
Algunos datos
Para poder demostrar las nuevas características agregadas a nuestro marco, necesitamos una base de datos para hacer uso del controlador de la base de datos y algunas de las funciones de administración de plantillas (donde reemplazamos un bloque de contenido con las filas en la base de datos).
El sitio de demostración que haremos con nuestro marco al final de esta serie de tutoriales es un sitio web con un directorio de miembros, así que hagamos una tabla de base de datos muy básica para perfiles de miembros, que contenga un ID, nombre y dirección de correo electrónico.



¡Obviamente, necesitamos algunas filas de datos en esta tabla!
Una plantilla rapida
Para que se muestre cualquier cosa, necesitamos una plantilla básica, donde listaremos los datos de nuestra tabla de miembros.
1 |
|
2 |
<html>
|
3 |
<head>
|
4 |
<title> Powered by PCA Framework</title> |
5 |
</head>
|
6 |
<body>
|
7 |
<h1>Our Members</h1> |
8 |
<p>Below is a list of our members:</p> |
9 |
<ul>
|
10 |
<!-- START members -->
|
11 |
<li>{name} {email}</li> |
12 |
<!-- END members -->
|
13 |
</ul>
|
14 |
</body>
|
15 |
</html>
|
Los miembros de START y los comentarios HTML de los miembros de END denotan el bloque de miembros (que se obtiene a través del método getBlock () en la página), donde el administrador de plantillas recorrerá los registros de la base de datos y los mostrará.
Marco en uso
Ahora, necesitamos reunir todo esto, con nuestro archivo index.php:
1 |
|
2 |
// require our registry
|
3 |
require_once('PCARegistry/pcaregistry.class.php'); |
4 |
$registry = PCARegistry::singleton(); |
5 |
|
6 |
// store those core objects
|
7 |
$registry->storeCoreObjects(); |
8 |
|
9 |
// create a database connection
|
10 |
$registry->getObject('db')->newConnection('localhost', 'root', '', 'pcaframework'); |
11 |
|
12 |
// set the default skin setting (we will store these in the database later...)
|
13 |
$registry->storeSetting('default', 'skin'); |
14 |
|
15 |
// populate our page object from a template file
|
16 |
$registry->getObject('template')->buildFromTemplates('main.tpl.php'); |
17 |
|
18 |
// cache a query of our members table
|
19 |
$cache = $registry->getObject('db')->cacheQuery('SELECT * FROM members'); |
20 |
|
21 |
// assign this to the members tag
|
22 |
$registry->getObject('template')->getPage()->addTag('members', array('SQL', $cache) ); |
23 |
|
24 |
// set the page title
|
25 |
$registry->getObject('template')->getPage()->setTitle('Our members'); |
26 |
|
27 |
// parse it all, and spit it out
|
28 |
$registry->getObject('template')->parseOutput(); |
29 |
print $registry->getObject('template')->getPage()->getContent(); |
Si ahora vemos esta página en nuestro navegador web, los resultados de la consulta se muestran en la página:

Viniendo en la parte 3 ...
En la tercera parte nos desviaremos un poco del lado de desarrollo de nuestro Marco, y veremos cómo diseñar con nuestro marco en mente, y cómo dividir plantillas HTML para que sean adecuadas para nuestro marco. Cuando empecemos a construir nuestra primera aplicación con nuestro marco, veremos con más detalle algunos de los trabajos de estas clases. Finalmente, gracias por tus comentarios la última vez!
- Suscríbase a la fuente RSS de NETTUTS para obtener más artículos y artículos de desarrollo web diarios.