Aynı PHP kod alanlı ve alansız sürümlerini geliştirmek için strateji

9 Cevap php

PHP 5.2 için yazılmış kütüphane muhafaza ediyorum ve bunu PHP 5.3-alanlı sürümünü oluşturmak istiyorum. PHP 5.3 çok eski hale gelinceye kadar Ancak, ben de, bugüne kadar alansız sürümünü kullanmaya devam ediyorum bile Debian kararlı gemiler onu ;)

Ben yaklaşık 80 sınıfları Project_Directory_Filename adlandırma şeması (I \Project\Directory\Filename elbette onları değiştirmek istiyorum) ve sadece birkaç fonksiyonları ve sabitler (ayrıca proje adı öneki şu, oldukça temiz kod var .)

Soru: paralel alanlı ve alansız sürümlerini geliştirmek için en iyi yolu nedir?

  • Ben sadece depo çatal oluşturmak ve şubeler arasındaki değişiklikleri birleştirme tutmak gerekir? Ters bölü-serpilir kodu birleştirme zor olur durumlar var mı?

  • Ben 5.3 ya da tam tersi 5.2 sürümünü dönüştüren senaryo yazmak mı? Ben PHP dizgeciklerini kullanmalı mıyım? sed? C önişlemci?

  • Mevcut ad kullanmak ve eski PHP ile geriye dönük uyumluluk tutmak için daha iyi bir yolu var mı?


Update: Decided against use of namespaces after all.

9 Cevap

Ben bu harika bir fikir olduğunu 5.3 kodunu önişleme sanmıyorum. Kodunuzu yerine çizgi ayrılmış soneklerin ad kullanarak hariç, hiç neden kullanımı ad alanları ile PHP 5.2 ve 5.3 hem de işlevsel olarak aynı ise? Eğer ad kullanarak uğruna, ad kullanmak istediğiniz gibi bu durumda bana geliyor ..

Ben size ad alanlarına göç olarak, kodunuzu düzenleme hakkında 'biraz farklı düşünmek' başlar göreceksiniz düşünüyorum.

Bu nedenle, ben şiddetle ilk çözüm katılıyorum. Bir çatal oluşturun ve özellikleri ve onarımları backports yapın.

İyi şanslar!

Bu bir takip olduğunu my previous answer:

Ad simülasyon kodu oldukça istikrarlı var. Zaten (hala bazı sorunlar, ama temelde) çalışmak için Symfony2'ye alabilirsiniz. Orada dışında tüm durumlarda değişken ad çözünürlüğü gibi eksik bazı şeyler hala new $class. Rağmen

Şimdi bir dizin ve süreç boyunca ardışık tüm dosyaları yineleme bir senaryo yazdı: http://github.com/nikic/prephp/blob/master/prephp/namespacePortR.php


Usage Instructions

Requirements for your code to work

Sizin classnames _ karakteri içermemelidir. Eğer onlar yapmak dönüştürme sırasında, classnames belirsiz alabilir.

Sizin kod ad alanı içindeki herhangi bir global işlevleri veya sabitler Redeclare gerekir. Böylece tüm kod derleme zamanında çözülebileceği sağlanmaktadır.

Temelde bu kodunuzu sadece kısıtlamalar vardır. Ben ek kodu ekleyerek gerektirir çünkü varsayılan yapılandırmasında namespacePortR, $className = 'Some\\NS\\Class'; new $className gibi şeyleri çözmek olmayacak dikkat etmelisiniz rağmen. Bu kadar sonra yamalı olduğunu daha iyi (elle veya otomatik yama sistemi kullanılarak.)

Configuration

Biz hiçbir küresel işlev veya sabit size namespace listener olarak assumeGlobal class sabit ayarlamalısınız bir ad redeclared olduğu varsayımını yaptık gibi. Aynı dosyada _ için SEPARATOR sabit ayarlayın.

NamespacePortR ihtiyaçlarınızı karşılamak için konfigürasyon bloğunu değiştirin.


PS: script ?skip=int seçeneğini sağlanabilir. Bu ilk int dosyaları atlamak için bunu söyler. Eğer kılma modunu akıllı ayarladığınız takdirde, gerek olmamalıdır.

PHP 5.2 PHP 5.3 öykünen bir proje üzerinde çalışıyorum: prephp. Bu (gerçi henüz tamamlanmış değil.) Ad desteği içerir

Vasıfsız işlev çağrıları ve sabit aramaları genel ad için bir geri dönüş var: Şimdi, bu yazma deneyimi namespace resolution bir belirsizlik sorun var. Yani otomatik olarak kodu dönüştürmek olabilir sadece tam veya nitelikli tüm fonksiyon çağrıları / sabit aramaları ya da eğer işlevi yerleşik bir PHP olarak aynı adı taşıyan bir ad herhangi bir işlev veya sabit yeniden tanımlamak vermedi.

Eğer kesinlikle bu uygulama (bunlardan hangisi seçtiğiniz) yapıştırılır eğer bu kodu dönüştürmek için oldukça kolay olacaktır. Bu prephp ad alanları taklit için kod bir alt kümesi olacaktır. Eğer uygulanması ile yardıma ihtiyacınız varsa, bana sormak için ücretsiz düştü, ben ilgi olurdu ;)

PS: The namespace emulation code of prephp henüz tamamlanmadı ve adamcağız olabilir. Ama size bazı anlayışlar verebilir.

Burada bulmak mümkün olacak düşünüyorum iyi cevap:

Step 1: Create a directory called 5.3 her dizin için içinde PHP5.3 kodu / w ve bunu tüm 5.3 özgü kod sopa.

Step 2: Take a class you want to put in a namespace and do this in 5.3/WebPage/Consolidator.inc.php:

namespace WebPage;
require_once 'WebPageConsolidator.inc.php';

class Consolidator extends \WebpageConsolidator
{
    public function __constructor()
    {
        echo "PHP 5.3 constructor.\n";

        parent::__constructor();
    }
}

Step 3: Use a strategy function to use the new PHP 5.3 code. Place in non-PHP5.3 findclass.inc.php:

// Copyright 2010-08-10 Theodore R. Smith <phpexperts.pro>
// License: BSD License
function findProperClass($className)
{
    $namespaces = array('WebPage');

    $namespaceChar = '';
    if (PHP_VERSION_ID >= 50300)
    {
        // Search with Namespaces
        foreach ($namespaces as $namespace)
        {
            $className = "$namespace\\$className";
            if (class_exists($className))
            {
                return $className;
            }
        }

        $namespaceChar = "\\";
    }

    // It wasn't found in the namespaces (or we're using 5.2), let's search global namespace:
    foreach ($namespaces as $namespace)
    {
        $className = "$namespaceChar$namespace$className";
        if (class_exists($className))
        {
            return $className;
        }
    }

    throw new RuntimeException("Could not load find a suitable class named $className.");
}

Step 4: Rewrite your code to look like this:

<?php
require 'findclass.inc.php';

$includePrefix = '';
if (PHP_VERSION_ID >= 50300)
{
        $includePrefix = '5.3/';
}

require_once $includePrefix . 'WebPageConsolidator.inc.php';

$className = findProperClass('Consolidator');
$consolidator = new $className;

// PHP 5.2 output: PHP 5.2 constructor.
// PHP 5.3 output: PHP 5.3 constructor. PHP 5.2 constructor.

Sizin için will çalışma. It performans akıllıca bir cludge, ama sadece biraz, ve 5.3 destekleyen durdurmaya karar verdiğinizde ortadan yapılacaktır.

İşte buldum ne:

Düzenli ifadeler ile bunu bir kabus. Sadece birkaç basit ifadeler ile yapılır bunun en alabilirsiniz, ama sonra davalar bir katil vardır kenar. Ben zar zor bir kod tabanı ile çalışır korkunç, kırılgan bir karmaşa ile sona erdi ettik.

Bu yerleşik simgeleştiricisine ve dilin sadece basitleştirilmiş alt kümesini kolları basit recursive asıllı ayrıştırıcı yapılabilir bulunuyor.

Onu muhafaza boşluk ile yararlı sözdizimi ağacı (I kod insan okunabilir olmak için çıkan istedim kurmak için çok fazla çalışma görünüyordu çünkü, - ben oldukça çirkin tasarım (çoğunlukla sadece belirteçleri değişen veya yeniden yayan bir çözümleyici ve trafo) ile sona erdi ettik .)

Bunun için phc denemek istedim, ama Boost kütüphanesinin gerekli sürümünü inşa onun configure ikna edemedim.

Ben henüz bu için Antlr denemedim, ama muhtemelen görevlerin bu tür için en iyi araçtır.

Ben (diğerleri) çizgi adlandırma kuralı kullanılan büyük kod tabanı ile yaptım, ve bir autoloader yerine require_once, bir sürü, bir autoloader tanımlamak, ve {eklemek için ne [(1)] İsim alanları ile güzel olmak için kendi isimlerini değiştirdikten sonra sınıfları eski adı adlar tanımlama dosyaları} hatları.

Ben o yüzden üzerinde hata tespit birlikte gittik ve yürütme autoloader eşyalarımı almak istiyorum, çünkü dahil sırasına bağlı değildi ve namespace şeyler require_once ifadeleri kaldırarak başladı.

Bugüne kadar oldukça iyi çalıştı.

Peki bu "iyi" yolu ise, bilmiyorum, ama teoride, sizin 5.3 migrate kodu almak için bir komut dosyası kullanabilirsiniz ve (hatta potansiyel PHP kullanarak) 5.2 içine backport.

Lütfen ad dosyalar üzerinde bir şey dönüştürmek yapmak isterim:

namespace \Project\Directory\Filename;

class MyClass {
  public $attribute;

  public function typedFunction(MyClass $child) {
    if ($child instanceof MyClass) {
      print 'Is MyClass';
    }
  }
}

Bir şey gibi:

class Project_Directory_Filename_MyClass {
  public $attribute;

  public function typedFunction(Project_Directory_Filename_MyClass $child) {
    if ($child instanceof Project_Directory_Filename_MyClass) {
      print 'Is MyClass';
    }
  }
}

Ve ad kodunu size dönüştürmek gerekir:

$myobject = new Project\Directory\Filename\MyClass();

Için:

$myobject = new Project_Directory_Filename_MyClass();

Tüm includes ve requires aynı kalacaktı, ben neredeyse 'instanceof etrafında karmaşık dönüşüm yapmak için tüm sınıfları ve ad Cache çeşit tutmak gerekir düşünüyorum da Eğer bunları kullanmak 've parametreleri yazdınız. Ben görebiliyorum trickiest şeydir.

Kendi başıma bu test değil, ama bu php 5.2 -> php 5.3 conversion script bir göz alabilir.

Bu 5.3 olarak aynı değil mi -> 5.2, ama belki orada bazı yararlı şeyler bulacaksınız.

Bizim DMS Software Reengineering Toolkit olasılığı oldukça sıra çözüm uygulayabilirsiniz. Bu yüzey-sözdizimi açısından kodlu AST dönüşümler için AST kullanarak, güvenilir bir kaynak kod dönüşümleri gerçekleştirmek için tasarlanmıştır.

Bir PHP Front End hangi PHP kodu yenileyiciye tam, kesin PHP çözümleyici, AST oluşturucu, ve AST olduğunu vardır. DMS ("mümkünse sütun numaraları korumayı") AST prettyPrinting veya sadakat baskı sağlar.

Bu kombinasyon, PHP 4 ve 5 için güvenilir PHP kaynak kodu manipülasyon çeşitli araçlar uygulamak için kullanılmıştır.

(Biraz inanmaz yorumuna cevaben) EDIT:

OP'ın çözüm için, aşağıdaki DMS dönüşüm kural işin en yapmalıdır:

rule replace_underscored_identifier_with_namespace_path(namespace_path:N)
   :namespace_path->namespace_path
"\N" -> "\complex_namespace_path\(\N\)" 
if N=="NCLASS_OR_NAMESPACE_IDENTIFIER" && has_underscores(N);

This rule finds all "simple" identifiers that are used where namespace paths are allowed, and replaces those simple identifiers with the corresponding namespace path constructed by tearing the string for the identifier apart into consitutent elements separated by underscores. One has to code some procedural help in DMS's implementation langauge, PARLANSE, to check that the identifier contains underscores ("has_underscores"), and to implement the tear apart logic by building the corresponding namespace path subtree ("complex_namespace_path").

Kural kural metin olarak yazılır. Soyut dil nonterminallerin (bu durumda, "namespace_path" karşılık ağaçları belirlenmesi ve tam adı uzay yolu temsil daha karmaşık ağaçları ile basit olanları değiştirerek çalışır, ancak kural kendisi ayrıştırılır DMS ağaçları inşa etmek yoluyla PHP ağaçları uygun olması gerekir.

DMS kural uygulama mantığı trivially PHP çözümleyici tarafından üretilen AST boyunca her yerde bu kuralı uygulayabilirsiniz.

Bu cevap PHP langauge oluşturan tüm karmaşık şeyler karşısında aşırı basit görünebilir, ancak tüm diğer karmaşıklığı DMS tarafından kullanılan PHP dildeki tanımında gizlidir; Bu tanım sözcük ve gramer tanımların bazı 10.000 hatları, ama zaten test edilmiş ve çalışıyor. Tüm DMS makine ve bu 10K hatları, basit regexes güvenilir iş yapamaz neden göstergeleridir. (O bu hakkı elde etmek için gereken ne kadar makine şaşırtıcıdır, ben 1995 yılından beri DMS üzerinde çalışıyoruz).

DMS yapabilirsiniz see a nice simple example bir dil, yöneten / tanımlar nasıl yapar all makinelerini görmek istiyorum.