使用具有相同名称的特征功能但可选

时间:2017-04-30 03:15:45

标签: php class traits php-7 php-traits

PHP Class Using Same Name as Trait Function

请参阅我刚才在上面提到的问题。这是我的原始代码。

trait sampletrait{
   function hello(){
      echo "hello from trait";
   }
}

class client{
   use sampletrait;

   function hello(){
      echo "hello from class";
      //From within here, how do I call traits hello() function also?
   }
}

由于问题的答案,我可以这样调用特质函数。

class client{
   use sampletrait {
       hello as protected sampletrait_hello;
   }

   function hello(){
      $this->sampletrait_hello();
      echo "hello from class";
   }
}

我的问题是,如果我的类客户端没有函数hello()但是想调用它可能吗?

所以例如......

trait sampletrait{
   function hello(){
      echo "hello from trait";
   }
}

class client{
   use sampletrait {
      hello as protected sampletrait_hello; 
   }
}

我知道我可以简单地说使用sampletrait;它会有功能,但在我的用例中我也不能这样做。是否可以使用别名,但如果类中不存在特征名,则仍然使用特征名吗?

额外信息

我的确切用例涉及PHP-ActiveRecord

我有一个叫做uniquecheck的特性

trait uniquecheck {

    //@JA - Used temporarely to determine if editing for the unique checker
    static $isEditing = false;

    //@JA - This is used by PHPActiveRecord to trigger events before validation on update calls only.
    static $before_validation_on_update = array('before_validation_on_update_callback');

    //@JA - This is function used as callback from PHPActiveRecord
    public function before_validation_on_update_callback(){
        self::$isEditing = true; //@JA - Requires Uniquecheck trait to work
    }

    //@JA - This function can do single and multi-unique checks.
    //@JA - This is programmed to be replaced at a later date when validates_uniqueness_of is fixed (http://www.phpactiverecord.org/projects/main/wiki/Validations#validates_uniqueness_of)
    //@JA - EXAMPLES
    //SINGLE    -- array('name','message' => 'Can't do this')
    //MULTIPLE  -- array( array('name1','name2'), 'message' => 'can't do this and that together')
    //@JA - To be clear multiple does not mean 2 different uniques but a unique on 2 columns.  Just use this function twice for 2 separate unique checks.
    public function uniquecheck($rules = array()) {

        $classname = get_class($this);

        //@JA - Basic validation to confirm assumptions for function properties
        if(count($rules)<=0){
            die('uniquecheck.php -> Property array can not be empty');
        }

        //@JA - If its an array use the MULTIPLE method
        if(is_array($rules[0])){
            //@JA - First create the condition string
            $conditionstring = '';
            $conditionarray = array();

            $uniques = $rules[0];
            foreach($uniques as $unique){
                $conditionstring .= "$unique = ? AND "; 
            }
            $conditionstring = substr($conditionstring, 0, -5);

            //@JA - Then generate the array we will use for the conditions
            $conditionarray['conditions'][] = $conditionstring;
            foreach($uniques as $unique){
                $conditionarray['conditions'][] = $this->read_attribute($unique);
            }

            $results = $classname::find('all',$conditionarray);

            if($classname::$isEditing == true){
                die('was editing');
            }else{
                die('was creating');
            }

            //@JA - If in edit mode, if the values are exactly the same as it was before then ignore this check.
            if (count($results)>=1) {
                foreach($uniques as $unique){
                    $this->errors->add($unique, $rules['message']);
                }
            }

        }else{ //@JA - Otherwise use the SINGLE method
            $unique = $rules[0];
            $results = $classname::find('all',array('conditions' => array("$unique = ?", $this->read_attribute($unique))));

            //@JA - If there is more then 1 result then its not unique!
            if (count($results)>=1) {
                $this->errors->add($unique, $rules['message']);
            }
        }       
    }
}

?>

我在我的模型客户端中使用它就像这样......

class Client extends ActiveRecord\Model {

    use foreignkeycheck;

    use uniquecheck {
       before_validation_on_update_callback as protected uniquecheck_before_validation_on_update_callback; 
    }

    static $before_destroy = array('before_destroy_callback');

    //@gv hide columns that are not in use right now
    static $columnsToHide = array(
        'affiliate_code',
        'autopay',
        'stripe_customer_id',
        'quickbooks_client_id',
        'stripe_customer_info',
        'stripe_customer_info_last_update',
        'textingnumber'
    );
    static $easy_name = "Client";
    static $validates_presence_of = array(
        array('clienttype_id'),
        array('company_id'),
        array('contactfirstname'),
        array('contactlastname'),
        array('contactphonenumber')        
    );
    static $validates_size_of = array(
        array('contactfirstname', 'within' => array(1, 50)),
        array('contactlastname', 'within' => array(1, 50)),        
        array('contactaddress', 'within' => array(1, 120), 'allow_null' => false),
        array('companyaddress', 'within' => array(1, 120), 'allow_null' => true),
        array('companyname', 'within' => array(1, 75), 'allow_null' => true),                
    );
//    static $validates_uniqueness_of = array(
//        array('affiliate_code', 'allow_null' => true),
//        array(array('contactfirstname', 'contactlastname', 'contactemail', 'contactphonenumber', 'contactaddress'),
//            'message' => 'Can\'t have duplicate client.')
//    );

    static $validates_format_of = array(
        array('contactemail', 'with' => '/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}\b/sim',
            'message' => 'Must be a correctly formatted email.', 'allow_blank' => true, 'allow_null' => true),
        array('companyemail', 'with' => '/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}\b/sim',
            'message' => 'Must be a correctly formatted email.', 'allow_blank' => true, 'allow_null' => true),
        array('companyphonenumber', 'with' => '/^(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i', 
            'message' => 'Phone number is invalid', 'allow_blank' => true, 'allow_null' => true),
        array('contactphonenumber', 'with' => '/^(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i', 
            'message' => 'Phone number is invalid', 'allow_blank' => true, 'allow_null' => false)
    );

    //This allows you to use your own as well as still call the uniquechecks before_validation callback in case this method is not needed.
    public function before_validation_on_update_callback(){
        $this->uniquecheck_before_validation_on_update_callback();
    }

    public function before_destroy_callback(){

        $conn = SELF::connection();
        $conn->transaction();

        try {
            //USER *********
            //Delete the associated user as well.
            $related_users = User::find('all',array(
                'conditions' => array(
                    'client_id' => $this->id)
            ));

            foreach($related_users as $user){
                $user->delete();
            }

            //PROPERTIES ********
            //Delete all properties of the client, which in turn delets all routes & visits
            $related_properties = Property::find('all',array(
                'conditions' => array(
                    'client_id' => $this->id)
            ));

            foreach($related_properties as $property){
                $property->delete();
            }

            //Only have to delete the user, because deletes will cascade down
            $conn->commit();
        } catch (Exception $e) {            
            $conn->rollback();
        }

        return true; //will actually delete the client now.
    }

    public function validate() {
        //Thought about putting user validation in here, but decided against it.
        //Multi-unique check FAILS to work if the parameter is not passsed for one of the multi-uniques.  This is BUG in PHP Active Record.
        //Does not show message correctly for multi-uniques either.  This is ALSO a bug in PHP Active Record.

        //@JA - Uses multi-unique check.  Its only not allowed if all 4 of these values are the same since its obviously duplicate at that point
        $this->uniquecheck(array(array('company_id','contactfirstname', 'contactlastname', 'contactphonenumber', 'contactaddress'),'message' => 'Can\'t have duplicate client.'));

        $this->foreignkeycheck('Clienttype');
        $this->foreignkeycheck('Company');
        $this->foreignkeycheck('Affiliate', 'affiliate_code', true); //Special case where foreign key is not _id, true sent to indicate validate is optional only if a value is not null.
    }

    public function getReadableColumnNames($flip = false) {
        $readableColumns = array();

        $readableColumns["contactfirstname"] = "First Name";
        $readableColumns["contactlastname"] = "Last Name";
        $readableColumns["contactphonenumber"] = "Phone Number";
        $readableColumns["contactemail"] = "Email";
        $readableColumns["contactaddress"] = "Address";
        $readableColumns["companyaddress"] = "Company Address";
        $readableColumns["companyemail"] = "Company Email";
        $readableColumns["companyname"] = "Company Name";
        $readableColumns["companyphonenumber"] = "Company Phone #";
        $readableColumns["affiliate_code"] = "Affiliate #";
        $readableColumns["clienttype_id"] = "Client Type";
        $readableColumns["company_id"] = "Company";
        $readableColumns["stripe_customer_id"] = "Stripe Customer ID";
        $readableColumns["stripe_customer_info"] = "Stripe Customer Info";
        $readableColumns["stripe_customer_info_last_update"] = "Stripe Info Last Update";
        $readableColumns["welcome_email_sent"] = "Welcome Email Sent?";
        $readableColumns["autopay"] = "Auto Pay?";
        $readableColumns["active"] = "Active?";

        if ($flip == true) {
            $readableColumns = array_flip($readableColumns); //swap keys and values~
        }
        return $readableColumns;
    }

    public function getDefaultColumns() {
        $defaultColumns = array();

        $defaultColumns[] = "contactfirstname"; //first sort order
        $defaultColumns[] = "contactlastname"; //second sort order
        $defaultColumns[] = "contactphonenumber";
        $defaultColumns[] = "contactemail"; //etc...

        return $defaultColumns;
    }

    public function getColumnExceptions() {
        $tableNames = array();

        return $tableNames;
    }

    public function getBatchActions() {
        $batchActions = array();

        //$batchActions['Text to Appear'] = 'ClassName' 
        //For JS File To Call Correct Function ^^^^
        //Order of array determines order in respective dropdown menu.

        $batchActions["Make Inactive"] = "batch_make_inactive";
        $batchActions["Send Email"] = "batch_send_email";
        $batchActions["Send Welcome Email"] = "batch_send_client_welcomeEmail";

        return $batchActions;
    }

    public function getRowActions() {
        $rowActions = array();

        $rowActions["Edit"] = array("edit_typename", true); //Call generic typename edit function, true means this is the item that shows first.
        $rowActions["View Pictures"] = array("view_pictures_for_client", false); //shortcut to prefill information for property~
        $rowActions["Add Property"] = array("add_property_for_client", false); //shortcut to prefill information for property~
        //$rowActions["Update Quickbooks"] = array("qb_update_customer", false); //shortcut to add customer to quickbooks if connected.
        $rowActions["Create User ID"] = array("create_userid_for_client", false); //shortcut method to create user_id straight from the client~
        $rowActions["Send Welcome Email"] = array("send_client_welcome_email", false);
        $rowActions["Make Inactive"] = array("allinactive_client", false); //will make the user inactive, property and user_id, along with recurring invoices, estimates, invoices that were referenced by client.
        $rowActions["Make Active"] = array("allactive_client", false);
        $rowActions["Delete"] = array("delete_typename", false);   //call to generic typename delete function
        //@gv Functions that do not work and not part of Release 1.0
        //$rowActions["Add Estimate"]         = array("add_estimate_for_client",false); //shortcut to prefill information for property~
        //$rowActions["Add Invoice"]          = array("add_invoice_for_client",false); //shortcut to prefill information for property~
        //$rowActions["Add To Quickbooks"]    = array("qb_add_customer",false); //shortcut to add customer to quickbooks if connected.
        //$rowActions["Make Inactive"]        = array("inactive_typename",false);   //Way to filter results if you desired by clients that are not relevant anymore.
        //$rowActions["Send Email"]           = array("send_client_email",false);
        //$rowActions["Send Text"]            = array("text_client",false);

        return $rowActions;
    }

    public function getColumnInterestedColumns() {
        $columnInterestedColumns = array();

        $columnInterestedColumns["clienttype_id"] = array("name");
        $columnInterestedColumns["company_id"] = array("companyname");
        $columnInterestedColumns["client_id"] = array("contactfirstname", "contactlastname"); //external reference.

        return $columnInterestedColumns;
    }

    //This function indicates to the UI what fields are dependent upon others for purpose of 'flow' for new and edit areas.
    //Happens in 2 areas, on initial PHP creation uses this to hide the field, and upon the restricted fields parent values taking on a value or losing a value.
    public function getColumnRestrictions() {
        global $user;
        $restrictedColumns = array();

        //$restrictedColumns["property_id"] =   array("client_id");//this means that property_id can not show in UI until client_id is set.

        return $restrictedColumns;
    }
}

?>

我正在尝试使用它来解决phpactiverecords唯一的检查错误,因为它不适用于我正在处理的项目的系统。

它使用这样的回调(before_validation_on_update_callback),它必须具有该名称。

我想使用特性将其包含在我的所有模型中,以便轻松进行独特检查。

请参阅此(http://www.phpactiverecord.org/projects/main/wiki/Callbacks

1 个答案:

答案 0 :(得分:1)

尝试在特征功能上设置公共,然后在重命名时保护

trait sampletrait{
   public function hello(){
      echo "hello from trait";
   }
}

class client{
   use sampletrait {
      hello as protected sampletrait_hello; 
   }
}

$c = new client();
$c->hello();

正如这里所说PHP Class Using Same Name as Trait Function,hello和sampletrait_hello都会存在,但是如果hello是public而且sampletrait_hello受保护只有hello可以从外部范围调用。

如果你覆盖你好,你就可以在里面调用sampletrait_hello。