Comunidad PHPeros

Otros => Los Retos PHPeros => Mensaje iniciado por: WarezD@rK en 19 de Febrero de 2010, 00:55:44 am

Título: Reto #4 - Practicando con clases en PHP
Publicado por: WarezD@rK en 19 de Febrero de 2010, 00:55:44 am
A raíz del tutorial sobre clases y de la clase MySQL, una forera me ha pedido que ponga un ejercicio sencillo acerca de este tema, así que lo publico como reto.

Dificultad: Fácil
Se valorará: Estructuración, sintaxis y comentarios en el código. Se valorará también el control de errores.
Premio: La satisfacción de haber aportado algo a la comunidad.

Reto: Crear una clase "Calcular" la cual tendrá su constructor y 5 métodos (funciones) que serán: Sumar, restar, multiplicar, dividir y resultado.

Su ejecución deberá ser algo parecido a esto:

Código: [Seleccionar]
<?php
$operacion 
= new Calcular();
$operacion->operanteUno(5);
$operacion->operanteDos(3);
$operacion->multiplicar();
echo 
$operacion->resultado();
?>

La clase, variables y métodos se podrán llamar como queráis, siempre y cuando tengan un nombre coherente (una clase para realizar una operación que se llame "DrHouse" o "Pokemon" no es muy coherente, la verdad).

Ayuda:

Tutorial sobre clases: http://www.phperos.net/foro/index.php/topic,5093.0.html (http://www.phperos.net/foro/index.php/topic,5093.0.html)
Clase MySQL: http://www.phperos.net/foro/index.php/topic,5095.0.html (http://www.phperos.net/foro/index.php/topic,5095.0.html)

La gracia es que lo hagáis a partir de la información que hay exclusivamente en el foro y os aseguro que hay de sobras.
Si tenéis alguna duda acerca del reto o sobre su programación, exponedla en este hilo y a poder ser no copiéis, os estaréis engañando a vosotros mismos, yo dormiré igual de bien que siempre.



NOTA: No tengo problema en ir publicando retos más difíciles, solo depende de vuestras ganas de aprender.



Un saludo :)
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: x.mara.x en 19 de Febrero de 2010, 13:00:26 pm
Buenas, despues de un poco de lio lo logre
Calculadora (http://marahost.comze.com/calcucl.php)
calculadoraClass.php
<?php
class calculadora {
var $operacion;
var $numero1;
var $numero2;
var $resultado;
public function sumar($xxnumero1,$xxnumero2) {
$this->resultado = $xxnumero1+$xxnumero2;
return $this->resultado;
}
public function restar($xxnumero1,$xxnumero2) {
$this->resultado = $xxnumero1-$xxnumero2;
return $this->resultado;
}
public function mult($xxnumero1,$xxnumero2) {
$this->resultado = $xxnumero1*$xxnumero2;
return $this->resultado;
}
public function dividir($xxnumero1,$xxnumero2) {
$this->resultado = $xxnumero1/$xxnumero2;
return $this->resultado;
}

}
?>
calcucl.php
<?php
include('calculadoraClass.php');
?>

<form name="form1" method="post" action="">
  <p>
    <label>
      <input type="text" name="numero1" id="calcucl.php">
    </label>
    <label>
      <select name="operacion" id="operacion">
        <option value="x">X</option>
        <option value="/">/</option>
        <option value="-">-</option>
        <option value="+">+</option>
      </select>
    </label>
    <input type="text" name="numero2" id="numero2">
  </p>
  <p>
    <label>
      <input type="submit" name="ok" id="ok" value="Calcular">
    </label>
  </p>
</form>
<?php
if(isset($_POST['ok'])) {
$num1 = $_POST['numero1'];
$num2 = $_POST['numero2'];
$varcalcu = new calculadora();
if(is_numeric($num1) && is_numeric($num2)) {
switch ($_POST['operacion']) { // empezamos un switch que nos enviara a la funcion que corresponde a la operacion
case "+":
$varcalcu->sumar($num1,$num2);
break;
case "-":
$varcalcu->restar($num1,$num2);
break;
case "x":
$varcalcu->mult($num1,$num2);
break;
case "/":
$varcalcu->dividir($num1,$num2);
break;
}
echo $varcalcu->resultado;
} else {
echo"Los valores de los numeros deben ser númericos!";
}
}
?>
Si hay algo que esta de sobra/podria ser mejorado en el codigo avisame :D
El codigo no lo explique porque me parece bastante sencillo, de todas maneras expliqué el uso del switch.
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: WarezD@rK en 19 de Febrero de 2010, 14:32:15 pm
Está bastante bien, aunque veo un par de cosas mejorables en tu código, pero esperaré a ver si alguien más se anima a participar.
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 19 de Febrero de 2010, 20:02:14 pm

class calculadora {
private $numero1;
private $numero2;
private $resultado;
function __construct($numero1 = 0, $numero2 = 0) {
$this->numero1 = (is_numeric($numero1) ? $numero1 : 0);
$this->numero2 = (is_numeric($numero2) ? $numero2 : 0);
}
public function numeros($numero1, $numero2) {
$this->numero1 = (is_numeric($numero1) ? $numero1 : $this->numero1);
$this->numero2 = (is_numeric($numero2) ? $numero2 : $this->numero2);
}

public function operar($operacion) {
switch($operacion) {
case 's': $this->resultado = $this->numero1+$this->numero2; break;
case 'r': $this->resultado = $this->numero1+$this->numero2; break;
case 'm': $this->resultado = $this->numero1*$this->numero2; break;
case 'd': $this->resultado = ($this->numero2 == 0 ? $this->numero1 : $this->numero1/$this->numero2); break;
default: $this->resultado = 0;
}
}
public function verResultado() {
return $this->resultado;
}
}

Esa es la clase, la calculadora sería:

<?php
if($_POST) {
include('calculadora.class.php');
$calculadora = new calculadora();
$calculadora->numeros($_POST['num1'], $_POST['num2']);
$calculadora->operar($_POST['op']);
echo 'El resultado es: '.$calculadora->verResultado();
}
?>
<form action="" method="post">
<input type="text" name="num1" /> <select name="op"><option value="s">+</option><option value="r">-</option><option value="m">x</option><option value="d">:</option></select> <input type="text" name="num2" />
<br />
<input type="submit" name="submit" value="Operar" />
</form>


Tengo dudas con eso de los valores por defecto en el constructor... xD

Salu2
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 19 de Febrero de 2010, 20:35:35 pm
Bueno, no participare porque west me robo la idea xdd.. Veo un error en el código de west y es que usas 1 función para definir pudiendolo hacer en el contructor... Además de que en el contructor siempre te dara TRUE porque solo cojera los valores por default.
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 19 de Febrero de 2010, 20:38:10 pm
Bueno, no participare porque west me robo la idea xdd.. Veo un error en el código de west y es que usas 1 función para definir pudiendolo hacer en el contructor... Además de que en el contructor siempre te dara TRUE porque solo cojera los valores por default.
No te entendí lo segundo.
Pero la función, si te refieres en el form, es simplemente por darle algún uso...
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 19 de Febrero de 2010, 20:45:32 pm
Lo que quiero decirte es que quites esta parte:
public function numeros($numero1, $numero2) {
$this->numero1 = (is_numeric($numero1) ? $numero1 : $this->numero1);
$this->numero2 = (is_numeric($numero2) ? $numero2 : $this->numero2);
}

Y para definir las variables haz esto:

$calculadora = new calculadora($numero1,$numero2);

Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 19 de Febrero de 2010, 20:57:58 pm
Lo que quiero decirte es que quites esta parte:
public function numeros($numero1, $numero2) {
$this->numero1 = (is_numeric($numero1) ? $numero1 : $this->numero1);
$this->numero2 = (is_numeric($numero2) ? $numero2 : $this->numero2);
}

Y para definir las variables haz esto:

$calculadora = new calculadora($numero1,$numero2);

Sí, sí, lo sé, pero como el reto requería una función para eso, lo puse así, además no seamos tan tiquismiquis que al fin y al cabo casi con una función va que chuta
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 19 de Febrero de 2010, 21:12:16 pm
West pero tampoco tan asi xdd

Veo un error en el código de mara, lo primero es que para llamar a una variable no es $varcalcu->resultado sino $this->resultado, lo segundo esque para que vas a poner el resultado de nuevo si en cada funcion se retorna el resultado.
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 19 de Febrero de 2010, 21:21:37 pm
West pero tampoco tan asi xdd

Veo un error en el código de mara, lo primero es que para llamar a una variable no es $varcalcu->resultado sino $this->resultado, lo segundo esque para que vas a poner el resultado de nuevo si en cada funcion se retorna el resultado.
No, porque accede desde fuera de la clase, la cual almacena en $varcalcu
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 19 de Febrero de 2010, 22:20:50 pm
No, porque accede desde fuera de la clase, la cual almacena en $varcalcu
Eso no tiene que ver.
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 19 de Febrero de 2010, 22:22:00 pm
Eso no tiene que ver.
Eso sí tiene que ver...

$pepe = new user('pepe');
echo $pepe->mostrarTrabajo();

Ahí NO EXISTE $this! la clase es $pepe!
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 19 de Febrero de 2010, 22:25:53 pm
Eso sí tiene que ver...

$pepe = new user('pepe');
echo $pepe->mostrarTrabajo();

Ahí NO EXISTE $this! la clase es $pepe!
Porque es una función.
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 19 de Febrero de 2010, 22:28:37 pm
Porque es una función.
Y DALE QUE DALE!
Mira este código de la clase MySQL de Warez@Dark:

<?php
$consultas = new mysqlQuery(array("UPDATE tabla SET nombre = 'WarezD@rK'",
                                                 "UPDATE tabla SET apellidos = 'PHPeros'",
                                                 "UPDATE tabla SET edad = '22'",
                                                 "UPDATE tabla SET pais= 'España'",
                                                 "UPDATE tabla SET ciudad = 'Barcelona'"));
$consultas->send();
?>

...
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 19 de Febrero de 2010, 22:39:38 pm
Y DALE QUE DALE!
Mira este código de la clase MySQL de Warez@Dark:

<?php
$consultas = new mysqlQuery(array("UPDATE tabla SET nombre = 'WarezD@rK'",
                                                 "UPDATE tabla SET apellidos = 'PHPeros'",
                                                 "UPDATE tabla SET edad = '22'",
                                                 "UPDATE tabla SET pais= 'España'",
                                                 "UPDATE tabla SET ciudad = 'Barcelona'"));
$consultas->send();
?>

...
Es verdad lo que decias..
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 19 de Febrero de 2010, 22:44:23 pm
Re*****, porque es una función, ahora mismo te subo un archivo y te lo pruebo.
$consultas->send();
Eso no es una función?
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 19 de Febrero de 2010, 23:11:00 pm
$consultas->send();
Eso no es una función?
Si, una funcion de la classe. Y ya vi que es verdad lo que decias..
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: WarezD@rK en 20 de Febrero de 2010, 04:35:25 am
Bueno, como prometí, ya he llegado a casa y voy a repasar los códigos de mara y west.
Veo que no hay muchos comentarios en el código. La verdad es que esta parte es muy importante porque ayuda a terceras personas a entender el algoritmo y en casos donde la clase es muy extensa, se vuelve algo indispensable, sobretodo en proyectos donde participan varias personas.

Me centraré exclusivamente en las clases que es de lo que trata el reto, los formularios es algo que tenemos más que aprendido y que domináis a la perfección.

Empezamos con la clase de mara:

He visto que has publicado el código y he podido probar tu clase. Como dije, era muy importante el control de errores y en este caso he encontrado un pequeño fallo con el tema de la división por 0. Es algo en lo que solemos fallar y no basta con comprobar si el código es numérico. Dividiendo 0 / 0 obtenemos este resultado:

Warning: Division by zero in /home/a7465051/public_html/calculadoraClass.php  on line 20

Veo que no has declarado las variables como privadas. Aunque no es ningún error te recomendaria por seguridad declararlas como privadas, ya que no va a ser necesario modificarlas desde fuera de la clase. También sobra la variable "$operacion", no es necesaria dentro de la clase. La variable que declares para utilizarla en la ejecución, no es necesaria declararla dentro:

Código: [Seleccionar]
<?php
private $numero1;
private 
$numero2;
private 
$resultado;
?>

Has entendido muy bien cómo funcionan las funciones dentro de una clase y los métodos para realizar las operaciones están muy bien:

Código: [Seleccionar]
<?php
public function sumar($xxnumero1$xxnumero2)
{
    
$this->resultado $xxnumero1 $xxnumero2;
    return 
$this->resultado;
}
?>

Por otro lado, no has creado un constructor y aunque no era estrictamente necesario, lo pedía para que viérais cómo funciona. En este caso sería:

Código: [Seleccionar]
<?php
function __construct()
{
    
$this->numero1 0;
    
$this->numero2 0;
    
$this->resultado 0;
}
?>

Te ha faltado una función que pedía para mostrar el resultado, que en este caso sería:

Código: [Seleccionar]
<?php
public function resultado()
{
    echo 
$this->resultado;
}
?>

En general, creo que has entendido bastante bien cómo funcionan las clases, aunque hubiese preferido que el control de errores fuese parte de la clase y no algo ajeno a ella, ya que el fin de las clases es reducir el código a la hora de trabajar con ellas. Me gustaría hacer otro reto un poco más difícil y ver cómo te desenvuelves con la programación orientada a objetos, seguro que lo harías bien.

Sigamos con la clase de west:

Veo que tú sí has pensado en la división entre 0. Es un detalle importante y un error bastante común. En ese aspecto todo bien.

Lo que no has entendido muy bien es para qué sirve el constructor y cómo se utiliza. El constructor sirve para establecer unos valores por defecto o ejecutar cierto algoritmo al crear el objeto que hace referencia a la clase. En este caso no debías pasarle ninguna variable a la función y sobra el ($numero1 = 0, $numero2 = 0) y tampoco era necesario comprobarlas. Simplemente había que inicializar las variables:

Código: [Seleccionar]
<?php
function __construct()
{
    
$this->numero1 0;
    
$this->numero2 0;
    
$this->resultado 0;
}
?>

Debido al diseño de tu constructor, su función "choca" con la función numeros(), ya que hacen algo parecido y es un poco paradójico. Hay dos opciones, establecer los valores al crear el objeto (new Calculadora(5, 3)) o establecerlos utilizando un método (numeros(5, 3)). En este caso pedía hacerlo con un método y tú lo has hecho de las dos formas.

He visto que las operaciones las realiza en un mismo método y mi intención era que fuese un método por cada operación, de esta manera sería más fácil ver el funcionamiento de la clase.

El método para mostrar el resultado perfecto.

En general creo que está bastante bien teniendo en cuenta que no te hacía mucha gracia la programación orientada a objetos y sería interesante verte programar alguna clase más.



A continuación os haré un boceto de cómo tenía pensado yo este reto. No es que sea lo correcto, porque hay muchas formas de programar, pero es lo que tenía en mente y en vez de hacerlo con dos operantes, lo haré compatible con más de dos, ya que sería un poco repetitivo y así variamos un poco. Veamos qué lío me sale:

Código: [Seleccionar]
<?php
/*
Clase Calcular para PHPeros.net
Reto #4: Practicando con clases en PHP
*/

class Calcular
{
# Declaramos 3 variables
# privadas para nuestra clase.
private $operantes;
private $resultado;
private $error;

# Creamos un constructor
# que las inicialice.
function __construct()
{
$this->operantes = array(105);
$this->resultado 0;
$this->error false;
}

# Diseñamos un método PRIVADO
# para mostrar el error que solo
# podrá ser utilizado dentro de nuestra clase.
private function verError()
{
return "Error: ".$this->error;
}

# Diseñamos un método para establecer
# los operantes y comprobar su tipo.
public function operantes($xOperantes)
{
# Creamos una variable boleana
# de control que devolverá TRUE
# en caso de que algún valor no
# sea numérico.
$xHayError false;

# Comprobamos si los valores
# se encuentran dentro de una array.
if(is_array($xOperantes))
{
# Comprobamos si hay más de 1
# operante, lógicamente.
if(count($xOperantes) >= 2)
{
# Recorremos los valores uno a uno
foreach($xOperantes as $xNumero)
{
# Comprobamos si son del tipo numérico.
if(!is_numeric($xNumero))
{
$xHayError true;
break;
}
}

# Comprobamos si ha habido algún error
# al recorrer el array.
if($xHayError)
{
$this->error "Debes introducir exclusivamente valores numéricos.";
echo $this->verError();
}
else
{
$this->operantes $xOperantes;
}
}
else
{
$this->error "Debe haber como mínimo 2 operantes.";
echo $this->verError();
}
}
else
{
$this->error "Para hacerlo más divertido, los operantes deben estar dentro de un array.";
echo $this->verError();
}
}

# Diseñamos un método que recorra
# el array y sume sus valores.
public function sumar()
{
# Si no ha ocurrido ningún error
# al establecer los operantes.
if(!$this->error)
{
# Inicializamos el resultado a 0.
$xResultado 0;

# Recorremos el array y realizamos
# la operación correspondiente al método.
foreach($this->operantes as $xNumero)
{
$xResultado $xResultado $xNumero;
}

# Almacenamos el resultado en
# la variable global.
$this->resultado $xResultado;
}
}

# Diseñamos un método que recorra
# el array y reste sus valores.
public function restar()
{
# Si no ha ocurrido ningún error
# al establecer los operantes.
if(!$this->error)
{
# Inicializamos el resultado con
# el doble del primer valor, de manera
# que al restar la primera vez, obtengamos
# el primer valor íntegro.
$xResultado $this->operantes[0] * 2;

# Recorremos el array y realizamos
# la operación correspondiente al método.
foreach($this->operantes as $xNumero)
{
$xResultado $xResultado $xNumero;
}

# Almacenamos el resultado en
# la variable global.
$this->resultado $xResultado;
}
}

# Diseñamos un método que recorra
# el array y multiplique sus valores.
public function multiplicar()
{
# Si no ha ocurrido ningún error
# al establecer los operantes.
if(!$this->error)
{
# Inicializamos el resultado a 1
# para que al multiplicar el primer
# operante, devuelva su valor íntegro.
$xResultado 1;

# Recorremos el array y realizamos
# la operación correspondiente al método.
foreach($this->operantes as $xNumero)
{
$xResultado $xResultado $xNumero;
}

# Almacenamos el resultado en
# la variable global.
$this->resultado $xResultado;
}
}

# Diseñamos un método que recorra
# el array y divida sus valores.
public function dividir()
{
# Creamos una variable de control
# que devolverá TRUE en case de que
# algún operante sea 0.
$xHayError false;

# Si no ha ocurrido ningún error
# al establecer los operantes.
if(!$this->error)
{
# Inicializamos el resultado
# con el primer operante elevado
# al cuadrado, para que devuelva
# su valor íntegro.
$xResultado $this->operantes[0] * $this->operantes[0];

# Recorremos el array y realizamos
# la operación correspondiente al método.
foreach($this->operantes as $xNumero)
{
# Comprobamos si algún
# operante es igual a 0.
if($xNumero != 0)
{
$xResultado $xResultado $xNumero;
}
else
{
$xHayError true;
break;
}
}

if($xHayError)
{
$this->error "No puedes dividir valores entre 0.";
echo $this->verError();
}
else
{
# Almacenamos el resultado en
# la variable global.
$this->resultado $xResultado;
}
}
}

# Diseñamos un método para
# devolver el resultado.
public function verResultado()
{
# Si no ha ocurrido ningún error
# al establecer los operantes.
if(!$this->error)
{
return "El resultado es: ".$this->resultado;
}
}
}
?>

De esta forma, si lo que queremos es, por ejemplo, dividir múltiples valores, su ejecución sería tan sencilla como:

Código: [Seleccionar]
<?php
$operacion 
= new Calcular();
$operacion->operantes(array(10025));
$operacion->dividir();
echo 
$operacion->verResultado();
?>

Incluye el control de errores, por lo que no es necesario comprobar nada al utilizar la clase, todo se genera desde dentro.

Os adjunto mi clase.



Gracias por vuestro interés en mi reto y espero que haya sido instructivo.
Un saludo :)
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: westwest en 20 de Febrero de 2010, 12:07:28 pm
creo que ya entendí mejor lo del constructor ^^
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Focux en 20 de Febrero de 2010, 14:51:57 pm
Buen aporte, deberías poner más retos de este tipo para poder aprender más.
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Farresito en 07 de Noviembre de 2010, 16:01:09 pm
Te dejo un Karma+ porque, a pesar de no haber participado, has hecho un esfuerzo en corregir los errores ;)
Título: Re:Reto #4 - Practicando con clases en PHP
Publicado por: Physlet en 14 de Noviembre de 2010, 19:33:30 pm
Coloca otro reto de programación orientada a objetos, me gustaría participar.

Por cierto, no era necesario inicializar en 0 con el constructor, ya hasta donde yo recuerdo al llamar al constructor $obj = new Calcular(); todos los atributos son inicializados.