Использование фаланги в качестве части представления приложения MVC

Чтобы обеспечить лучшее сотрудничество между парнем, разбирающимся в пользовательском интерфейсе, который знает HTML, и парнем, который знает .NET, мы думаем об архитектуре, в которой мы используем веб-приложение MVC и используем фалангу в качестве механизма просмотра.

Интеграция фалангира в качестве модели просмотра выглядит довольно просто, если не считать одного момента. Я не уверен, как передать модель скрипту страницы. Любые идеи, как это может быть достигнуто?

Одной из идей может быть вызов статического метода .NET из php-скрипта, но это кажется немного хакерским. Я хотел бы иметь возможность просто передать параметр скрипту, и скрипт сможет подобрать его в переменной.


person Robert    schedule 26.05.2011    source источник


Ответы (2)


Использование .NET на бэкенде и PHP (используя Phalanger) на внешнем интерфейсе выглядит как хороший сценарий. Я думаю, что лучший вариант — реализовать модель в .NET и использовать PHP для реализации контроллеров и представлений (либо напрямую, либо с использованием какой-либо среды PHP).

Вызов модели .NET из PHP, скомпилированного с помощью Phalanger, довольно прост, поскольку код PHP может обращаться к объектам .NET. Предположим, у вас есть C# DLL, содержащая пространство имен DemoDataLayer следующего типа:

public class Data {
  public List<Category> GetCategories() {
    var ret = new List<Category>();
    // Some code to load the data
    return ret;
  }
}

Затем вы можете сослаться на библиотеку C# с веб-сайта Phalanger (используя web.config) и использовать расширения PHP, предоставленные Phalanger, для использования класса Data, как если бы это был стандартный объект PHP:

<?
  import namespace DemoDataLayer;
  $dl = new Data;
  $categories = $dl->GetCategories();
?>
<ul>
<? foreach($categories as $c) { ?>
    <li><a href="products.php?id=<? echo $c->ID ?>"><? echo $c->Name ?></a></li>
<? } ?>
</ul>

Чтобы настроить ссылку, вам нужно добавить C# DLL в каталог bin и включить ее в элемент classLibrary. Используемый выше синтаксис import namespace представляет собой языковое расширение, специфичное для Phalanger (для использования пространств имен .NET), которое необходимо включить с помощью функции PhpClr:

<?xml version="1.0"?>
<configuration>
  <phpNet>
    <compiler>
      <set name="LanguageFeatures">
        <add value="PhpClr" />
      </set>
    </compiler>
    <classLibrary>
      <add assembly="DemoDataLayer" />
    </classLibrary>
  </phpNet>
</configuration>
person Tomas Petricek    schedule 26.05.2011
comment
Спасибо за ответ, Томас, но я надеялся сделать это наоборот: сделать так, чтобы код .NET вызывал php-скрипт и передал ему параметр для автоматического создания привязки, такой как $categories, чтобы минимизировать количество кода php .net, который имел быть написанным. Это возможно? - person Robert; 27.05.2011
comment
@Robert: Да, это тоже можно сделать (мне нужно проверить подробности). Вопрос в том, как вы хотите создать экземпляр PHP-кода? Если вы используете ASP.NET MVC, я предполагаю, что вы хотели бы иметь что-то вроде return PhpView("foo.php") в своем контроллере? (В настоящее время это не поддерживается, но звучит интересно, и это, безусловно, можно сделать!) - person Tomas Petricek; 28.05.2011
comment
У меня есть собственный mvc-подобный фреймворк, у которого есть собственный F#ish-способ вызова представлений, но в основном вы должны сделать что-то вроде return PhpView(foo.php) для вызова представления php. Я смотрел на это прямо сейчас, и это выглядит сложно, так как все, что связано с компиляцией скриптов, помечено как внутреннее. Похоже, нужно будет сделать кастомную сборку фаланги и изменить некоторые настройки видимости. - person Robert; 28.05.2011

Посетите http://phpviewengine.codeplex.com/.

Этот проект содержит следующий метод преобразования типов CLR в форму, которую могут использовать ваши PHP-скрипты:

    object PhpSafeType(object o)
    {
        // PHP can handle bool, int, double, and long
        if ((o is int) || (o is double) || (o is long) || (o is bool))
        {
            return o;
        }
        // but PHP cannot handle float - convert them to double
        else if (o is float)
        {
            return (double) (float) o;
        }
        // Strings and byte arrays require special handling
        else if (o is string)
        {
            return new PhpString((string) o);
        }
        else if (o is byte[])
        {
            return new PhpBytes((byte[]) o);
        }
        // Convert .NET collections into PHP arrays
        else if (o is ICollection)
        {
            var ca = new PhpArray();
            if (o is IDictionary)
            {
                var dict = o as IDictionary;
                foreach(var key in dict.Keys)
                {
                    var val = PhpSafeType(dict[key]);
                    ca.SetArrayItem(PhpSafeType(key), val);
                }
            }
            else
            {
                foreach(var item in (ICollection) o)
                {
                    ca.Add(PhpSafeType(item));
                }
            }
            return ca;
        }
        // PHP types are obviously ok and can just move along
        if (o is DObject)
        {
            return o;
        }
        // Wrap all remaining CLR types so that PHP can handle tham
        return PHP.Core.Reflection.ClrObject.WrapRealObject(o);
    }

Его можно использовать так...

// Get setup
var sc = new ScriptContext.CurrentContext;
var clrObject = /* Some CLR object */
string code = /* PHP code that you want to execute */

// Pass your CLR object(s) into the PHP context
Operators.SetVariable(sc,null,"desiredPhpVariableName",PhpSafeType(clrObject));

// Execute your PHP (the PHP code will be able to see the CLR object)
var result =            return DynamicCode.Eval(
                code,
                false,
                sc,
                null,
                null,
                null,
                "default",
                1,1,
                -1,
                null
                );

Это может даже обрабатывать анонимные типы. Например, вставьте следующее в приведенное выше.

var clrObject = new { Name = "Fred Smith" };
Operators.SetVariable(sc,null,"person",PhpSafeType(clrObject));

Затем вы можете получить доступ к этому в PHP:

echo $person->Name;

который, конечно же, выводит Fred Smith

person Justin    schedule 22.07.2011