Intermitent Naming Conflict

ぃ、小莉子 提交于 2019-12-13 04:46:57

问题


I call for collective wisdom on this one. I am having the following extremely weird bug.

I have a model named File.php. I have used it in several places in my app. But now it doesn't seem to work.

In this case, it works in my Template.php:

        $this->Behaviors->load('Containable');

    $this->contain(
        array(
            'User',
            'TemplatesUserType' => array(
                    'UserType',
                    'FilesTemplatesUserType'=>array('File')
            )
        )
    );
    $template=$this->find('first',array('conditions'=>array('Template.id'=>$template_id,"Template.user_id"=>$user['User']['id'])));

This also works in FilesTemplatesUserTypesController:

            $this->FilesTemplatesUserType->File->recursive=-1;
            $file=$this->FilesTemplatesUserType->File->findByName($name);

            if(gettype($file)=="array" && count($file)>0){
                $file_id=$file["File"]["id"];
            }
            else{
                $this->FilesTemplatesUserType->File->create();
                $this->FilesTemplatesUserType->File->save(array("File"=>array("name"=>$name)));
                $file_id=$this->FilesTemplatesUserType->File->getInsertID();
            }

            $this->request->data["FilesTemplatesUserType"]["file_id"]=$file_id;
        }

        $this->FilesTemplatesUserType->create();
        $this->FilesTemplatesUserType->save($this->request->data);

Both cases work, perfectly fine. But now, from model Document.php, it fails throwing a 500 internal server error:

$this->Behaviors->load("Containable");
    $this->contain(array(
            "UsersVersion"=>array(
                    "conditions"=>array("UsersVersion.user_id !="=>$user["User"]["id"]),
                    "User"
            ),
            "Draft"=>array(
                    "fields"=>array("Draft.id,Draft.template_id,Draft.name"),
                    "Template"=>array(
                            "fields"=>array("Template.id, Template.name, Template.user_id"),
                            "TemplatesUserType"=>array(
                                    "DraftsUser"=>array(
                                        "User"
                                    ),
                                    "FilesTemplatesUserType"=>array("FilesUsersVersion","File")
                            )
                    )
            )
        )
    );
    $draft=$this->findById($document_id);

But it is until I remove the "File" that works.

To debug, I tried this in the same file:

$model=$this->Draft->Template->TemplatesUserType->FilesTemplatesUserType->File;
    $model->recursive=-1;

    $file=$model->findByName("Ident");

It throws an error at line 88 in CORE/Utility/File.php indicating that $path has: array("class"=>"File","alias"=>"File") instead of a string and the following error message: Fatal error: Call to undefined method File::findByName() in C:\Inetpub\vhosts\*******.com\httpsdocs\eolas\app\Controller\DocumentsController.php on line 245

To make matters more confusing, this works from my Template.php model:

$model=$this->TemplatesUserType->FilesTemplatesUserType->File;
    $model->recursive=-1;

    $file=$model->findByName("Ident");

It appears that somehow the error occurs depending on the recursive level that the model File is being called and that is when it might get in conflict with File.php Utility class.

My question is: Why is it working perfectly in some places and until now is failing? Is there something to CakePHP inner workings that I am hitting correctly by chance and now I am losing it?

I hope you can steer me in the right direction (and not to have to change my model name, =P).

Thank you very much in advance!


回答1:


As stated in my answer to your previous question you cannot have a model named File as there is already a class named File in CakePHP's core code. You need to use an alternative name for your model. Think of File as a reserved word.

The reason why your code is sometimes working comes down to whether your model or Cake's File utility is touched first. In the case where your code is failing File is being used as the utility class rather than your model so isn't compatible.

Think about it: if Cake tries to initiate an instance of the class File (i.e. new File(/* some params */)) which File class will it use in your code? The fact that this is unclear should give you the clue that you shouldn't be using a model with the same name as the utility class. I suspect your error logs contain more errors/warnings about your code as a result of this.

Unfortunately you have no choice but to change the name of your model. However, you may be able to change some of the renamed model class' attributes so that it still behaves as the File model (this is untested as I've never needed to do this, but might be worth a try). For example, rename the class (and filename) to AppFile and then set the $name, $alias and $table properties so that the model behaves as File:-

<?php
class AppFile extends AppModel {

    public $name = 'File';

    public $alias = 'File';

    public $table = 'files';

}


来源:https://stackoverflow.com/questions/34214074/intermitent-naming-conflict

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!