问题描述
请参阅上面我刚才问的问题.这是我的原始代码.
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.
这篇关于使用具有相同名称但可选的特征功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!