SilverStripe 3.6.5 - связывает загруженные файлы из внешней формы SilverStripe с объектом данных

У меня есть объект данных под названием «Project», который имеет отношение $ has_many к другому объекту данных под названием «ProjectExpenseForm». В интерфейсе сайта находится форма SilverStripe, которая используется для обновления некоторых полей проекта. Новые файлы и изображения также можно загружать через интерфейсную форму.

Я использую модуль SilverStripe Dropzone Master (https://github.com/unclecheese/silverstripe-dropzone) для создания поля загрузки в форме внешнего интерфейса. Мне удалось заставить его работать, чтобы он сохранял все загрузки в правильную папку в каталоге ресурсов (у каждого проекта есть папка для загруженных файлов, а настройка - assets / projects / [идентификатор проекта] / files /). Однако я не уверен, как прикрепить / связать эти загруженные файлы с проектом. Хорошо, что они загружаются в нужную папку, но если файлы не связаны с проектом, это нехорошо.

Вот код интерфейсной формы:

public function UpdateMyProjectProfileForm()
{
    $fieldsArr = array();
    $member = Member::currentUser();

    if (!$member) {
        return "<div class='text-danger'>Error: must be logged in to view this page.</div>";
    }
    $request = $this->getRequest();
    $projectName = $request->param('ProjectName');
    $projectNameID = explode("-", $projectName);

    $projectNameID = $projectNameID[0];

    if ($member->inGroup('project-lead')) {
        $project = Project::get()
            ->filter(
                array(
                    "ProjectLeadID" => $member->ID,
                    "ID" => $projectNameID
                )
            )
            ->first();
        $name = ReadonlyField::create('Name', 'Name of Project', $project->Name);
        $firstName = ReadonlyField::create('FirstName', 'First Name of Project Manager', $project->FirstName);
        $lastName = ReadonlyField::create('LastName', 'Last Name of Project Manager', $project->LastName);
        $phone = ReadonlyField::create('Phone', "Phone Number", $project->Phone);
        $emailAddress = ReadonlyField::create('Email', "Manager Email", $project->Email);
        $notes = TextareaField::create('Notes', 'Notes', $project->Notes);
        $projectSummary = TextareaField::create('ProjectSummary', "Project Summary", $project->ProjectSummary);
        $imageUploader = FileAttachmentField::create('MyFile', 'Upload a file')
            ->setView('grid')
            ->setMultiple(true)
            ->setFolderName("projects/".$project->ID.'/expenses'); //THIS WORKS - Stores the file(s) uploaded to the proper directory

        array_push($fieldsArr, $name);
        array_push($fieldsArr, $firstName);
        array_push($fieldsArr, $lastName);
        array_push($fieldsArr, $phone);
        array_push($fieldsArr, $emailAddress);
        array_push($fieldsArr, $notes);
        array_push($fieldsArr, $projectSummary);
        array_push($fieldsArr, $imageUploader);
        $fields = new FieldList($fieldsArr);

        $updateButton = FormAction::create('update', 'Update')
            ->addExtraClass("btn btn-default commonBtn");

        $actions = new FieldList($updateButton);
        $required = new RequiredFields(
            array('Name', 'Notes', 'ProjectSummary')
        );

        $form = new Form($this, $projectName . '/UpdateMyProjectProfileForm', $fields, $actions, $required);

        $form->setFormMethod('POST', true);

        return $form;
    }
}

public function update($data, Form $form)
{
    $member = Member::currentUser();

    $request = $this->getRequest();
    $projectName = $request->param('ProjectName');
    $projectNameID = explode("-", $projectName);
    $projectNameID = $projectNameID[0];

    $project = Project::get()
        ->filter(
            array(
                "ProjectLeadID" => $member->ID,
                "ID" => $projectNameID
            )
        )
        ->first();

    if ($data['Name'] == "") {
        $form->addErrorMessage("Name", "Project Name is required.", "text-danger");
        return $this->redirectBack();
    }

    if ($data['Notes'] == "") {
        $form->addErrorMessage("Notes", "Notes is required.", "text-danger");
        return $this->redirectBack();
    }

    if ($data['ProjectSummary'] == "") {
        $form->addErrorMessage("ProjectSummary", "Project Summary is required.", "text-danger");
        return $this->redirectBack();
    }

    $member = Member::currentUser();

    if (!$member) {
        $form->addErrorMessage("FirstName", "Error: user profile not found.", "text-danger");
        return $this->redirectBack();
    }

    $project->Name = $data['Name'];
    $project->Notes = $data['Notes'];
    $project->ProjectSummary = $data['ProjectSummary'];
    $project->write();

    $form->sessionMessage("Project profile successfully updated.", 'text-success');

    return $this->redirectBack();
}

Вот класс проекта:

public function UpdateMyProjectProfileForm()
{
    $fieldsArr = array();
    $member = Member::currentUser();

    if (!$member) {
        return "<div class='text-danger'>Error: must be logged in to view this page.</div>";
    }
    $request = $this->getRequest();
    $projectName = $request->param('ProjectName');
    $projectNameID = explode("-", $projectName);

    $projectNameID = $projectNameID[0];

    if ($member->inGroup('project-lead')) {
        $project = Project::get()
            ->filter(
                array(
                    "ProjectLeadID" => $member->ID,
                    "ID" => $projectNameID
                )
            )
            ->first();
        $name = ReadonlyField::create('Name', 'Name of Project', $project->Name);
        $firstName = ReadonlyField::create('FirstName', 'First Name of Project Manager', $project->FirstName);
        $lastName = ReadonlyField::create('LastName', 'Last Name of Project Manager', $project->LastName);
        $phone = ReadonlyField::create('Phone', "Phone Number", $project->Phone);
        $emailAddress = ReadonlyField::create('Email', "Manager Email", $project->Email);
        $notes = TextareaField::create('Notes', 'Notes', $project->Notes);
        $projectSummary = TextareaField::create('ProjectSummary', "Project Summary", $project->ProjectSummary);
        $imageUploader = FileAttachmentField::create('MyFile', 'Upload a file')
            ->setView('grid')
            ->setMultiple(true)
            ->setFolderName("projects/".$project->ID.'/expenses');

        array_push($fieldsArr, $name);
        array_push($fieldsArr, $firstName);
        array_push($fieldsArr, $lastName);
        array_push($fieldsArr, $phone);
        array_push($fieldsArr, $emailAddress);
        array_push($fieldsArr, $notes);
        array_push($fieldsArr, $projectSummary);
        array_push($fieldsArr, $imageUploader);
        $fields = new FieldList($fieldsArr);

        $updateButton = FormAction::create('update', 'Update')
            ->addExtraClass("btn btn-default commonBtn");

        $actions = new FieldList($updateButton);
        $required = new RequiredFields(
            array('Name', 'Notes', 'ProjectSummary')
        );

        $form = new Form($this, $projectName . '/UpdateMyProjectProfileForm', $fields, $actions, $required);

        $form->setFormMethod('POST', true);

        return $form;
    }
}

public function update($data, Form $form)

{
    $member = Member::currentUser();

    $request = $this->getRequest();
    $projectName = $request->param('ProjectName');
    $projectNameID = explode("-", $projectName);
    $projectNameID = $projectNameID[0];

    $project = Project::get()
        ->filter(
            array(
                "ProjectLeadID" => $member->ID,
                "ID" => $projectNameID
            )
        )
        ->first();

    if ($data['Name'] == "") {
        $form->addErrorMessage("Name", "Project Name is required.", "text-danger");
        return $this->redirectBack();
    }

    if ($data['Notes'] == "") {
        $form->addErrorMessage("Notes", "Notes is required.", "text-danger");
        return $this->redirectBack();
    }

    if ($data['ProjectSummary'] == "") {
        $form->addErrorMessage("ProjectSummary", "Project Summary is required.", "text-danger");
        return $this->redirectBack();
    }

    $member = Member::currentUser();

    if (!$member) {
        $form->addErrorMessage("FirstName", "Error: user profile not found.", "text-danger");
        return $this->redirectBack();
    }

    $project->Name = $data['Name'];
    $project->Notes = $data['Notes'];
    $project->ProjectSummary = $data['ProjectSummary'];
    $project->write();

    $form->sessionMessage("Project profile successfully updated.", 'text-success');

    return $this->redirectBack();
}

Класс проекта (многое было удалено - я просто сохранил соответствующие части):

<?php

class Project extends DataObject
{

    private static $db = array(
        'Name'              => 'varchar(255)',,
        'FirstName'         => 'varchar(255)',
        'LastName'          => 'varchar(255)',
        'ProjectSlug'       => 'varchar(255)',
        'Email'             => 'varchar(255)',
        'Phone'             => 'varchar(255)',
        'Notes'             => 'Text',
        'ProjectSummary'     => 'Text',
    );

    // One-to-one relationship with gallery page
    private static $has_one = array(
        'MainImage' => 'Image',
        "Status" => 'ProjectStatus',
        'ProjectLead' => 'ProjectLead'
    );
    private static $has_many = array(
        'AdditionalProjectImages' => 'AdditionalProjectImage',
        'ProjectExpenseForms' => 'ProjectExpenseForm',
    );
    // Tell the datagrid what fields to show in the table
    private static $summary_fields = array(
        'ID' => 'ID',
        'Name' => 'Project',
    );

    // tidy up the CMS by not showing these fields

    public function getCMSFields()
    {
        $fields = parent::getCMSFields();
        $fields->removeByName("ProjectExpenseForms");
        $fields->removeByName("AdditionalProjectImages");

        $fields->addFieldToTab("Root.Main", new TextField("ProjectSlug", "Project Slug"));



        $projectMainImgUploadField = new UploadField("MainImage", "Project Main Image");
        $projectMainImgUploadField->setFolderName("projects/".$this->ID.'/images');
        $fields->addFieldToTab('Root.Main', $projectMainImgUploadField);
        $fields->addFieldToTab("Root.Main", new TextField("Name", "Project Name"));
        $fields->addFieldToTab("Root.Main", new TextField("FirstName", "First Name"));
        $fields->addFieldToTab("Root.Main", new TextField("LastName", "Last Name"));
        $fields->addFieldToTab("Root.Main", new TextField("Phone", "Phone Number"));
        $fields->addFieldToTab("Root.Main", new TextField("Email", "Email Address"));
        $fields->addFieldToTab("Root.Main", new TextareaField("Notes", "Notes"));
        $fields->addFieldToTab("Root.Main", new TextareaField("ProjectSummary", "Project Summary"));

        //EXPENSE FORMS
        $expensesGridFieldConfig = GridFieldConfig_RecordEditor::create();

        $expensesGridFieldConfig->addComponent(new GridFieldBulkUpload());
        $expensesGridFieldConfig->addComponent(new GridFieldSortableRows('SortOrder'));
        $expensesGridFieldConfig->getComponentByType('GridFieldBulkUpload')
            ->setUfSetup('setFolderName',"projects/" . $this->ID . "/expenses")
            ->setUfConfig('sequentialUploads', true);
        $expensesGridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(array(
            // field from drawer class => label in UI
            'ID' => 'ID',
            'Title'=> 'Title'
        ));

        $expensesGridField = new GridField(
            "ProjectExpenseForms",
            "Project Expense Forms",
            $this->ProjectExpenseForms()->sort("SortOrder"),
            $expensesGridFieldConfig
        );

        $fields->addFieldToTab('Root.Project Expense Forms', $expensesGridField);

    public function getExpenses(){
        return $this->ProjectExpenseForms();
    }

    public function onBeforeWrite()
    {
        parent::onBeforeWrite();
        if ($this->StatusID == "" || $this->StatusID == 0 || is_null($this->StatusID)) {
            $siteConfig = SiteConfig::current_site_config();

            $this->StatusID = $siteConfig->DefaultProjectStatusID;
        }
        //email the assigned grantor
        if ($this->isChanged('ProjectGrantorID', DataObject::CHANGE_VALUE) && $this->ProjectGrantorID != 0) {
            $this->sendGrantorEmail();
        }
    }
    public function onAfterWrite()
    {
        parent::onAfterWrite();
        //If the project does not have the appropriate folders already created, it's time to create them.
        Folder::find_or_make("/projects/" . $this->ID . "/expenses");
        Folder::find_or_make("/projects/" . $this->ID . "/images");
    }
}

class ProjectAdmin extends ModelAdmin
{

    private static $managed_models = array('Project');
    private static $url_segment = 'Projects';
    private static $menu_title = 'Projects';

}

и класс ProjectExpenseForm (многое было удалено - я просто включил соответствующие части):

<?php

class ProjectExpenseForm extends DataObject {

    private static $db = array(
        'SortOrder' => 'Int',
    );

    // One-to-one relationship with gallery page
    private static $has_one = array(
        'ProjectExpenseFile'   => 'File',
        'Project'              => 'Project'
    );

    // tidy up the CMS by not showing these fields
    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $projectExpenseUploadField = new UploadField("ProjectExpenseFile", "Project Expense File");
        $projectExpenseUploadField->setFolderName("projects/".$this->ProjectID.'/expenses');
        $fields->addFieldToTab('Root.Main', $projectExpenseUploadField);
        $fields->removeFieldFromTab("Root.Main","SortOrder");

        return $fields;
    }

}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
407
2

Ответы 2

Поскольку вы знаете, в какой папке сохраняются файлы на assets/projects/[project id]/files/, и файлы уникальны для этого проекта, вы можете просмотреть файлы в цикле и использовать DB::query, чтобы связать их с проектом.

В методе update файла UpdateMyProjectProfileForm я бы сделал что-то вроде.

$folderPath = 'assets/projects/' . $projectNameID . '/files/';
$folder = DataList::create('Folder')->filter('Filename', $folderPath)->first();
if ($folder) {
    $images = DataList::create('Image')->filter('ParentID', $folder->ID);
    foreach ($images as $image) {
        DB::query('INSERT INTO Project_AdditionalProjectImages (ProjectID, AdditionalProjectImagesID) VALUES (' . $projectNameID . ',' . $image->ID . ')');
    }
}

Вы также можете добавить ProjectLeadID в запрос, чтобы сделать его более безопасным. Вам нужно будет проверить имя вашей таблицы, так как Project_AdditionalProjectImages может быть неправильным.

Вам нужно передать отношение к File AttachmentField вместо MyFile

$imageUploader = FileAttachmentField::create('MyFile', 'Upload a file')

В вашем случае это AdditionalProjectImages, потому что вы так назвали его в своем has_many.

 private static $has_many = array(
        'AdditionalProjectImages' => 'Image'
    )

Они должны указывать на класс изображения вместо AdditionalProjectImage.

Итак, ваш FileAttachmentField должен выглядеть так:

$imageUploader = FileAttachmentField::create('AdditionalProjectImages', 'Upload a file')

И поскольку каждому $ has_many нужен $ has_one, вам нужен has один в классе изображения. Итак, вам нужно расширение:

ImageExtension extends Image
{
     public static $has_one = [
         'ProjectImages' => 'Project'
     ];
}

Запустите dev / build / flush, Silverstripe прикрепит / свяжет эти загруженные файлы с вашим проектом, если вы сделаете это, как указано выше.

На всякий случай, если вы не знаете, что есть новый форум для silverstripe: SilverStripe Форум, а также есть слабый канал для пользователей silverstripe.

Я пробовал это, но получаю сообщение об ошибке: «Неперехваченное исключение: не найдено has_one в классе« Image », для отношения has_many от« Project »к« Image »требуется has_one в« Image »». Я создал класс расширения для Image так же, как вы предложили. Хотя, не уверен, почему после изображения для расширения стоит ()?

Dejsa Cocan 10.04.2018 21:54

Я бы попробовал 'AdditionalProjectImages' => 'ImageExtension' вместо 'AdditionalProjectImages' => 'Image'.

Gavin Bruce 11.04.2018 13:32

@GavinBruce Я попробовал, и он устранил ошибку, но при загрузке файлов они по-прежнему не связаны с проектом: \

Dejsa Cocan 11.04.2018 17:44

Мое плохое "нет" () для расширения

Greg 808 12.04.2018 12:29

У Das Image есть ProjectImagesID? И собственно его dev / build /? Flush.

Greg 808 12.04.2018 12:42

Вы брали эти уроки https://www.silverstripe.org/learn/lessons/v3. Мне потребовалось время, чтобы понять орму, но как только вы ее получите, вы никогда не захотите работать без нее.

Greg 808 12.04.2018 15:38

Другие вопросы по теме