使用具有相同名称但可选的特征功能 [英] Use Trait Function with Same Name but Optionally

查看:88
本文介绍了使用具有相同名称但可选的特征功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用与特质函数同名的PHP类

请参阅上面我刚才问的问题.这是我的原始代码.

Refer to the question I just asked above here. Here was my original code.

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?
   }
}

由于问题的答案,我可以像这样调用trait函数.

I can call the trait function like this thanks to the answer to the question.

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

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

我的问题是我的类客户端是否没有函数hello()但想调用它吗?

My question is if my class client did not have a function hello() but wanted to call it is this possible?

例如...

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

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

我知道我可以简单地说出use sampletrait;它将具有功能,但是在我的用例中,我也无法做到这一点.如果在类中不存在别名,是否可以使用别名但仍使用默认特征名称?

I'm aware that I could just simply say use sampletrait; and it would have the function but in my use case I can't do that either. Is it possible to have the aliased name but still use the trait name default if it does not exist in the class?

其他信息

我的确切用例涉及PHP-ActiveRecord

My exact use case involves PHP-ActiveRecord

我有一个称为uniquecheck的特征

I have a trait called 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']);
            }
        }       
    }
}

?>

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

I use this in my model Client like so...

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独特的检查错误,因为它不适用于我正在从事的项目的系统.

I am trying to use this to get around phpactiverecords unique check bug since it does not work in there system for a project I'm working on.

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

It uses a callback like this (before_validation_on_update_callback), where it has to have that name.

我想使用特征将其包含在我的所有模型中,以便轻松地进行唯一检查.

I wanted to use a trait to include it in all my models for unique checking easily.

请参考此内容( http://www.phpactiverecord.org/projects/main /wiki/Callbacks )

推荐答案

尝试在trait函数上设置public,然后在重命名时受保护

Try setting public on the trait function and then protected when you rename

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

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

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

如此处所说使用与以下名称相同的PHP类特性功能 hello和sampletrait_hello都将存在,但是由于hello是公共的,并且sampletrait_hello受保护,只有hello可以从外部范围调用.

As said here PHP Class Using Same Name as Trait Function both hello and sampletrait_hello will exist, but as hello is public and sampletrait_hello protected only hello will be callable from an outer scope.

如果您覆盖了hello,则可以在其中调用sampletrait_hello.

And if you overwrite hello, you will be able to call sampletrait_hello inside it.

这篇关于使用具有相同名称但可选的特征功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆