Доступ с свойствам класса

atv

Новичок
Для ПХП 5 есть ещё такое решение:

PHP:
<?php
//
// +------------------------------------------------------------------------+
// | PHP Version 5                                                          |
// +------------------------------------------------------------------------+
// | Copyright (c) 2004-2005 Tereshchenko Andrey. All rights reserved.      |
// +------------------------------------------------------------------------+
// | This source file is subject to version 3.00 of the PHP License,        |
// | that is available at http://www.php.net/license/3_0.txt.               |
// | If you did not receive a copy of the PHP license and are unable to     |
// | obtain it through the world-wide-web, please send a note to            |
// | [email protected] so we can mail you a copy immediately.                 |
// +------------------------------------------------------------------------+
// | Author: Tereshchenko Andrey <[email protected]>                |
// +------------------------------------------------------------------------+
//
// $Id: BaseObject.php,v 1.1.1.1 2005/02/19 09:45:21 anter Exp $
//

ini_set('track_errors', true);

/**
* @package      PHP_Application
* @subpackage   Common
*/
/**
* BaseObject is the ultimate ancestor of all objects and components.
*
* BaseObject provides a methods of control of access to properties of
* object. Similar functionality can be necessary not only to objects working
* in PApple environment, therefore it has been allocated into a separate class.
*
* As in PHP there are no special features for the control of access over
* properties of object, for this purpose the overloaded access to properties has
* been used, and also some agreements under the name of properties of object.
* Details about the overloaded access read in a manual on PHP.
*
* To take advantage of methods of the control of access, it is enough to create
* property which name begins with a sign on underlining "_", and a level of
* access "protected".
* For example:
* <code>
*   class Simple extends BaseObject
*   {
*       protected $_sampleVar = 'Sample Var';
*   }
*   $obj = new Simple;
*   print $obj->sampleVar;
* </code>
*
* Pay attention, that when there is an access to property outside of object,
* the sign on underlining is not necessary. Inside object to property access as
* directly (with "_"), and through the overloaded access (without "_")
* is possible.
*
* About that how to write own method of access to property, read in the
* description of methods __get() and __set().
*
* @author       Tereshchenko Andrey <[email protected]>
* @copyright    2004-2005 Tereshchenko Andrey
* @license      http://www.php.net/license/3_0.txt The PHP License, Version 3.0
* @category     PHP
* @version      $Revision: 1.1.1.1 $
* @package      PHP_Application
* @subpackage   Common
* @link         http://www.anter.com.ua/PApple
* @see          __get()
* @see          __set()
*/
abstract class BaseObject
{
    /**
    * Specifies the name of the object.
    *
    * @var      string
    * @name     name
    * @access   readonly
    */
    protected $_name = 'unknown';

    /**
    * Debug mode flag.
    *
    * @var      boolean
    */
    public $debug = false;

    /**
    * Contains revision of this class for runtime version control.
    *
    * Use PHP function version_compare() to check of class version.
    */
    const version = '$Revision: 1.1.1.1 $';
    
    /**
    * Displays the debugging message.
    *
    * The message is displayed if one of flags - a flag of object ($this->debug)
    * or a global flag ($GLOBALS['_PApple_debug']) is established.
    *
    * @param    string
    */
    protected function printDebug($message)
    {
        global $_PApple_debug;
        if ($this->debug || $_PApple_debug) {
            print "\n{$this->_name}::{$message}";
            flush();
        }
    }

    /**
    * Allows to expand functionality of a method __get().
    *
    * The method userGet() is called by a method __get() in that case when
    * for the specified property it is not found a method of access and
    * it is not defined in a class. By default the method userGet() throws
    * exception "undefined property". However, you can redefine a method
    * userGet(), and to manipulate with properties, which have not got under
    * action of a method __get(), at own discretion. An example of use of such
    * opportunity look in a class "I18N".
    *
    * @param    string      property name.
    * @return   mixed       property value.
    * @throws   EProperty   undefined property.
    * @see      userSet()
    */
    protected function userGet($prop)
    {
        throw new EProperty("undefined property '{$prop}'",
            EProperty::UNDEFINED_ERR, $this);
    }

    /**
    * Allows to expand functionality of a method __set().
    *
    * The method userSet() is called by a method __set() in that case when
    * for the specified property it is not found a method of access and
    * it is not defined in a class. By default the method userSet() throws
    * exception "undefined property". However, you can redefine a method
    * userSet(), and to manipulate with properties, which have not got under
    * action of a method __set(), at own discretion. An example of use of such
    * opportunity look in a class "I18N".
    *
    * @param    string      property name.
    * @param    mixed       property value.
    * @throws   EProperty   undefined property.
    */
    protected function userSet($prop, $value)
    {
        throw new EProperty("undefined property '{$prop}'",
            EProperty::UNDEFINED_ERR, $this);
    }

    /**
    * Overloading access for getting a property.
    *
    * This method is caused every time when there is an operation of reading
    * of property which is not determined in a class. The method __get()
    * directs this call to other method which is defined for operation of
    * reading from the specified property. If such method does not exist,
    * the method __get() itself returns value of the specified property.
    * If such property does not exist, the method userGet() is caused.
    *
    * To specify a method which will access to property, the agreement on the
    * name of such method is applied. The name of a method which is defined
    * for access to property, should begin with a string "getProp_" and then
    * a name of the specified property. For example: for property "sample"
    * the name of a method should be "getProp_sample()".
    *
    * @param    string      property name.
    * @return   mixed       property value.
    * @see      userGet()
    */
    public function __get($prop)
    {
        $methodName = "getProp_{$prop}";
        $propName = "_{$prop}";
        if (method_exists($this, $methodName)) {
            return $this->$methodName($prop);
        } elseif (isset($this->$propName)) {
            return $this->$propName;
        } else {
            return $this->userGet($prop);
        }
    }

    /**
    * Overloading access for setting a property.
    *
    * If such method does not exist it means, that the specified property is
    * accessible only to reading, exception therefore throws. If such property
    * does not exist, the method userSet() is caused.
    *
    * To specify a method which will access to property, the agreement on the
    * name of such method is applied. The name of a method which is defined
    * for access to property, should begin with a string "setProp_" and then
    * a name of the specified property. For example: for property "sample"
    * the name of a method should be "setProp_sample()".
    *
    * @param    string      property name.
    * @param    mixed       value to set.
    * @throws   EProperty   the property is readonly.
    */
    public function __set($prop, $value)
    {
        $methodName = "setProp_{$prop}";
        $propName = "_{$prop}";
        if (method_exists($this, $methodName)) {
            $this->$methodName($prop, $value);
        } elseif (isset($this->$propName)) {
            throw new EProperty("the property '{$prop}' is readonly",
                EProperty::READONLY_ERR, $this);
        } else {
            $this->userSet($prop, $value);
        }
    }
}

/**
* Returns name of caller function.
*
* @return   string  function name if present.
* @see      getCallerClass
*/
function getCallerMethod()
{
    $trace = debug_backtrace();
    return $trace[2]['function'];
}

/**
* Returns name of class of caller method.
*
* @return   string  class name if present.
* @see      getCallerMethod
*/
function getCallerClass()
{
    $trace = debug_backtrace();
    return $trace[2]['class'];
}


?>
 

pachanga

Новичок
Мне все же кажется, что нельзя сказать, какой именно способ "самый лучший". Опять же это просто набор "лучших практик"(best practices), каждая из которых подходит в определенной ситуации лучше другой.

Скажем, при переводе некоторой доменной модели в классы я лично стараюсь пользоваться четким интерфейсом, т.е getFoo/setFoo.

В случае с некоторыми чисто утилитарными классами (скажем, всевозможные контейнеры данных) излишняя четкость интерфейса просто ни к чему, и использование get("foo")/set("foo") вполне логично. Есть еще один аспект - скорость доступа к свойствам, если она критична, то, может, имеет смысл обращаться к ним напрямую. К примеру, в WACT во время генерации кода шаблона используется именно такой метод.
 

bkonst

.. хочется странного?...
Я не сказал бы, что
PHP:
...
function get_foo() { return $this->foo; };
...
$a = $object->get_foo();
будет заметно быстрее, чем
PHP:
$a = $object->foo;
Я совсем недавно профилировал большой проект, в котором широко использовались get/set функции и - по моим впечатлениям - потери были около процента.
 

texrdcom

Новичок
потери были около процента.
bkonst

у тебя клиенты сидят на localhost ? что тебя волнует 1%
?
Поверь если твоей проэкт на хосте фиг знает где то 1% не играет ни какой роли!
Оптимизировать надо то что надо и не более!.
 

bkonst

.. хочется странного?...
Я про то и говорил, что в этом случае выигрыш небольшой, а скрипт в конечном итоге получается гибче. :)
 
Сверху