window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster υπάρχει ήδη') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Symfony: The Codest
The Codest
  • Σχετικά με εμάς
  • Υπηρεσίες
    • Ανάπτυξη λογισμικού
      • Ανάπτυξη Frontend
      • Backend Ανάπτυξη
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Μηχανικοί δεδομένων
      • Μηχανικοί cloud
      • Μηχανικοί QA
      • Άλλα
    • Συμβουλευτική
      • Έλεγχος & Συμβουλευτική
  • Βιομηχανίες
    • Fintech & Τραπεζική
    • E-commerce
    • Adtech
    • Healthtech
    • Κατασκευή
    • Εφοδιαστική
    • Αυτοκίνητο
    • IOT
  • Αξία για
    • CEO
    • CTO
    • Διευθυντής παράδοσης
  • Η ομάδα μας
  • Case Studies
  • Μάθετε πώς
    • Blog
    • Συναντήσεις
    • Διαδικτυακά σεμινάρια
    • Πόροι
Καριέρα Ελάτε σε επαφή
  • Σχετικά με εμάς
  • Υπηρεσίες
    • Ανάπτυξη λογισμικού
      • Ανάπτυξη Frontend
      • Backend Ανάπτυξη
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Μηχανικοί δεδομένων
      • Μηχανικοί cloud
      • Μηχανικοί QA
      • Άλλα
    • Συμβουλευτική
      • Έλεγχος & Συμβουλευτική
  • Αξία για
    • CEO
    • CTO
    • Διευθυντής παράδοσης
  • Η ομάδα μας
  • Case Studies
  • Μάθετε πώς
    • Blog
    • Συναντήσεις
    • Διαδικτυακά σεμινάρια
    • Πόροι
Καριέρα Ελάτε σε επαφή
Πίσω βέλος GO BACK
2022-06-28
Ανάπτυξη λογισμικού

Symfony: Symonyony: Επικοινωνία μικρουπηρεσιών μέρος Ι

The Codest

Sebastian Luczak

PHP Αρχηγός μονάδας

Διαβάστε το πρώτο μέρος της σειράς PHP που είναι αφιερωμένο στην επικοινωνία μικρουπηρεσιών στο πλαίσιο Symfony και στον πιο δημοφιλή τρόπο - την επικοινωνία AMQP με χρήση του RabbitMQ.

Η σύγχρονη αρχιτεκτονική εφαρμογών ανάγκασε τους προγραμματιστές να αλλάξουν τον τρόπο σκέψης για την επικοινωνία μεταξύ των διαφόρων στοιχείων των συστημάτων πληροφορικής. Κάποτε το θέμα ήταν απλούστερο - τα περισσότερα συστήματα δημιουργήθηκαν ως μονολιθικές δομές που συνδέονταν μεταξύ τους με ένα δίκτυο συνδέσεων επιχειρηματικής λογικής. Η διατήρηση τέτοιων εξαρτήσεων σε ένα PHP έργο ήταν μια τεράστια πρόκληση για PHP προγραμματιστές, και η αυξανόμενη δημοτικότητα των λύσεων SaaS και η τεράστια αύξηση της δημοτικότητας των cloud υπηρεσιών προκάλεσε το γεγονός ότι σήμερα ακούμε όλο και περισσότερο για μικρουπηρεσίες και αρθρωτότητα εφαρμογών.

Πώς ακριβώς, δημιουργώντας ανεξάρτητες μικρουπηρεσίες, μπορούμε να τις κάνουμε να ανταλλάσσουν πληροφορίες μεταξύ τους;

Αυτό το άρθρο είναι το πρώτο μιας σειράς αναρτήσεων σχετικά με επικοινωνία μικρο-υπηρεσιών στο Symfony πλαίσιο και καλύπτει τον πιο δημοφιλή τρόπο - την επικοινωνία AMQP με χρήση του RabbitMQ.

Στόχος

Να δημιουργήσετε δύο ανεξάρτητες εφαρμογές και να επιτύχετε την επικοινωνία μεταξύ τους χρησιμοποιώντας μόνο τον δίαυλο μηνυμάτων.

Η έννοια

Έχουμε δύο, φανταστικές, ανεξάρτητες εφαρμογές:
* app1: που στέλνει ειδοποιήσεις μέσω e-mail και SMS στους υπαλλήλους
* app2: που σας επιτρέπει να διαχειρίζεστε την εργασία των εργαζομένων και να τους αναθέτετε καθήκοντα.

Θέλουμε να δημιουργήσουμε ένα σύγχρονο και απλό σύστημα με το οποίο η ανάθεση εργασίας σε έναν εργαζόμενο σε app2 θα στείλει μια ειδοποίηση στον πελάτη χρησιμοποιώντας app1. Παρά τα φαινόμενα, αυτό είναι πολύ απλό!

Προετοιμασία

Για τους σκοπούς αυτού του άρθρου, θα χρησιμοποιήσουμε την τελευταία έκδοση του Symfony (έκδοση 6.1 κατά τη στιγμή της συγγραφής) και την τελευταία έκδοση του PHP (8.1). Με λίγα πολύ απλά βήματα θα δημιουργήσουμε ένα λειτουργικό τοπικό περιβάλλον Docker με δύο μικρουπηρεσίες. Το μόνο που θα χρειαστείτε είναι:
* έναν λειτουργικό υπολογιστή,
* εγκατεστημένο Docker + Περιβάλλον Docker Compose
* και ένα τοπικά διαμορφωμένο Symfony CLI και λίγο ελεύθερο χρόνο.

Περιβάλλον εκτέλεσης

Θα χρησιμοποιήσουμε τις δυνατότητες του Docker ως εργαλείο εικονικοποίησης εφαρμογών και κοντέινερ. Ας ξεκινήσουμε δημιουργώντας ένα δέντρο καταλόγου, ένα πλαίσιο για δύο Εφαρμογές Symfony, και να περιγράψουμε την υποδομή των περιβαλλόντων μας χρησιμοποιώντας το docker-compose.yml αρχείο.

 cd ~
 mkdir microservices-in-symfony
 cd microservices-in-symfony
 symfony new app1
 symfony new app2
 touch docker-compose.yml

Δημιουργήσαμε δύο καταλόγους για δύο ξεχωριστές εφαρμογές Symfony και δημιουργήσαμε ένα κενό docker-compose.yml αρχείο για να ξεκινήσει το περιβάλλον μας.

Ας προσθέσουμε τα ακόλουθα τμήματα στο docker-compose.yml file:

έκδοση: '3.8'

υπηρεσίες:
app1:
app1
build: app1/.
restart: on-failure
envfile: app1/.env
environment:
APPNAME: app1
tty: true
stdinopen: true

app2:
containername: app2
build: app2/.
restart: on-failure
envfile: app2/.env
environment:
APPNAME: app2
tty: true
stdinopen: true

rabbitmq:
containername: rabbitmq
εικόνα: rabbitmq:management
ports:
- 15672:15672
- 5672:5672
περιβάλλον:
- RABBITMQDEFAULTUSER=user
- RABBITMQDEFAULT_PASS=password

Πηγή κωδικός διαθέσιμο άμεσα: thecodest-co/microservices-in-symfony/blob/main/docker-compose.yml

Αλλά περιμένετε, τι συνέβη εδώ; Για όσους δεν είναι εξοικειωμένοι με το Docker, το παραπάνω αρχείο ρυθμίσεων μπορεί να φαίνεται αινιγματικό, ωστόσο ο σκοπός του είναι πολύ απλός. Χρησιμοποιώντας το Docker Compose δημιουργούμε τρεις "υπηρεσίες":

  • app1: το οποίο είναι ένας περιέκτης για την πρώτη εφαρμογή Symfony
  • app2: το οποίο είναι ο περιέκτης για τη δεύτερη εφαρμογή Symfony
  • rabbitmq: η εικόνα της εφαρμογής RabbitMQ ως ενδιάμεσο επίπεδο επικοινωνίας

Για τη σωστή λειτουργία, χρειαζόμαστε ακόμη Dockerfile τα οποία αποτελούν την πηγή για την κατασκευή των εικόνων. Ας τα δημιουργήσουμε λοιπόν:

 touch app1/Dockerfile
 touch app2/Dockerfile

Και τα δύο αρχεία έχουν ακριβώς την ίδια δομή και μοιάζουν ως εξής:

ΑΠΟ php:8.1

COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
COPY . /app/
WORKDIR /app/

ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/

RUN chmod +x /usr/local/bin/install-php-extensions && sync &&
install-php-extensions amqp

RUN apt-get update
&& apt-get install -y libzip-dev wget --no-install-recommends
&& apt-get clean
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Εκτελέστε το docker-php-ext-install zip,

CMD bash -c "cd /app && composer install && php -a"

Ο πηγαίος κώδικας διατίθεται άμεσα: /thecodest-co/microservices-in-symfony/blob/main/app1/Dockerfile

Το παραπάνω αρχείο χρησιμοποιείται από το Docker Compose για τη δημιουργία ενός δοχείου από μια εικόνα PHP 8.1 με εγκατεστημένο το Composer και την επέκταση AMQP. Επιπλέον, εκτελεί το PHP intepreter σε λειτουργία append για να συνεχίσει να τρέχει ο περιέκτης στο παρασκήνιο.

Το δέντρο καταλόγων και αρχείων σας θα πρέπει τώρα να έχει την ακόλουθη μορφή:

 .
 ├── app1
 │ └── Dockerfile
 | (...) # Δομή εφαρμογής Symfony
 ├── app2
 │ └ └── Dockerfile
 | (...) # Δομή εφαρμογής Symfony
 └── docker-compose.yml

Η πρώτη μικρο-υπηρεσία Symfony

Ας ξεκινήσουμε με το app1 και την πρώτη εφαρμογή.
Στο παράδειγμά μας, πρόκειται για μια εφαρμογή που ακούει και καταναλώνει μηνύματα από την ουρά που στέλνει η app2 όπως περιγράφεται στις απαιτήσεις:

ανάθεση μιας εργασίας σε έναν εργαζόμενο στο app2 θα στείλει μια ειδοποίηση στον πελάτη

Ας ξεκινήσουμε προσθέτοντας τις απαιτούμενες βιβλιοθήκες. Το AMQP υποστηρίζεται εγγενώς για το symfony/messenger επέκταση. Θα εγκαταστήσουμε επιπλέον μονόλογος/μονόλογος να παρακολουθείτε τα αρχεία καταγραφής συστήματος για ευκολότερη ανάλυση της συμπεριφοράς των εφαρμογών.

 cd app1/
 symfony composer req amqp ampq-messenger monolog

Μετά την εγκατάσταση, ένα επιπλέον αρχείο προστέθηκε στο όνομα config/packages/messenger.yaml. Είναι ένα αρχείο ρυθμίσεων για το συστατικό Symfony Messenger και δεν χρειαζόμαστε το πλήρης διαμόρφωση.
Αντικαταστήστε το με το παρακάτω αρχείο YAML:

πλαίσιο:
Αγγελιοφόρος:
για να στέλνετε τα αποτυχημένα μηνύματα σε αυτή τη μεταφορά για μεταγενέστερο χειρισμό.
# failure_transport: failed

    transports:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        external_messages:
            dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
            options:
                auto_setup: false
                exchange:
                    name: messages
                    type: direct
                    default_publish_routing_key: from_external
                ουρές:
                    messages:
                        binding_keys: [from_external]

Ο πηγαίος κώδικας διατίθεται άμεσα: thecodest-co/microservices-in-symfony/blob/main/app1/config/packages/messenger.yaml

Το Symfony Messenger χρησιμοποιείται για σύγχρονη και ασύγχρονη επικοινωνία σε εφαρμογές Symfony. Υποστηρίζει μια ποικιλία από μεταφορές, ή πηγές αλήθειας του επιπέδου μεταφοράς. Στο παράδειγμά μας, χρησιμοποιούμε την επέκταση AMQP που υποστηρίζει το σύστημα ουρών γεγονότων RabbitMQ.

Η παραπάνω διαμόρφωση ορίζει μια νέα μεταφορά με όνομα external_messages, το οποίο παραπέμπει στο MESSENGER_TRANSPORT_DSN μεταβλητή περιβάλλοντος και ορίζει απευθείας ακρόαση στο μηνύματα κανάλι στον δίαυλο μηνυμάτων. Σε αυτό το σημείο, επεξεργαστείτε επίσης το app1/.env και προσθέστε την κατάλληλη διεύθυνση μεταφοράς.

"`env

(...)
MESSENGERTRANSPORTDSN=amqp://user:password@rabbitmq:5672//messages
(...)
"
Μετά την προετοιμασία του πλαισίου της εφαρμογής και τη διαμόρφωση των βιβλιοθηκών, ήρθε η ώρα να υλοποιηθεί η επιχειρησιακή λογική. Γνωρίζουμε ότι η εφαρμογή μας πρέπει να ανταποκρίνεται στην ανάθεση μιας εργασίας σε έναν εργαζόμενο. Γνωρίζουμε επίσης ότι η ανάθεση μιας εργασίας στοapp2system αλλάζει την κατάσταση της εργασίας. Ας δημιουργήσουμε λοιπόν ένα μοντέλο που μιμείται την αλλαγή κατάστασης και ας το αποθηκεύσουμε στη διαδρομήapp1/Message/StatusUpdate.php`:
εικόνα
 {
public function __construct(protected string $status){}

public function getStatus(): string
{
    return $this->status,
}

}

Ο πηγαίος κώδικας διατίθεται άμεσα: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Message/StatusUpdate.php

Χρειαζόμαστε ακόμα μια κλάση που θα υλοποιεί την επιχειρησιακή λογική όταν η μικρουπηρεσία μας λαμβάνει το παραπάνω συμβάν από την ουρά. Ας δημιουργήσουμε λοιπόν μια Χειριστής μηνυμάτων στο app1/Handler/StatusUpdateHandler.php μονοπάτι:

εικόνα
 use PsrLogLoggerInterface,
use SymfonyComponentMessengerAttributeAsMessageHandler,

[AsMessageHandler]

class StatusUpdateHandler
{
public function __construct(
protected LoggerInterface $logger,
) {}

public function __invoke(StatusUpdate $statusUpdate): void
{
    $statusDescription = $statusUpdate->getStatus(),

    $this->logger->warning('APP1: {STATUS_UPDATE} - '.$statusDescription),

    // η υπόλοιπη επιχειρησιακή λογική, π.χ. αποστολή ηλεκτρονικού ταχυδρομείου στο χρήστη
    // $this->emailService->email()
}

}

Ο πηγαίος κώδικας διατίθεται άμεσα: /thecodest-co/microservices-in-symfony/blob/main/app1/src/Handler/StatusUpdateHandler.php

PHP κάνουν τα πράγματα πολύ πιο εύκολα και σημαίνουν ότι στη συγκεκριμένη περίπτωση δεν χρειάζεται να ανησυχούμε για την αυτόματη καλωδίωση ή τη δήλωση υπηρεσίας. Η μικροϋπηρεσία μας για το χειρισμό των γεγονότων του τομέα είναι έτοιμη, ήρθε η ώρα να ασχοληθούμε με τη δεύτερη εφαρμογή.

Δεύτερη μικρουπηρεσία Symfony

Θα ρίξουμε μια ματιά στο app2 κατάλογο και το δεύτερο Εφαρμογή Symfony. Η ιδέα μας είναι να στέλνουμε ένα μήνυμα στην ουρά όταν σε έναν εργαζόμενο ανατίθεται μια εργασία στο σύστημα. Ας κάνουμε λοιπόν μια γρήγορη διαμόρφωση του AMQP και ας ξεκινήσουμε τη δημοσίευση της δεύτερης μικρο-υπηρεσίας μας StatusUpdate συμβάντα στον δίαυλο μηνυμάτων.

Η εγκατάσταση των βιβλιοθηκών είναι ακριβώς η ίδια όπως και για την πρώτη εφαρμογή.

 cd ..
 cd app2/
 symfony composer req amqp ampq-messenger monolog

Ας βεβαιωθούμε ότι η app2/.env αρχείο περιέχει μια έγκυρη καταχώρηση DSN για το RabbitMQ:

(...)
 MESSENGER_TRANSPORT_DSN=amqp://user:password@rabbitmq:5672//messages
 (...)

Το μόνο που απομένει είναι να ρυθμίσετε το Symfony Messenger στο app2/config/packages/messenger.yaml file:

πλαίσιο:
Αγγελιοφόρος:
για να στέλνετε τα αποτυχημένα μηνύματα σε αυτή τη μεταφορά για μεταγενέστερο χειρισμό.
# failure_transport: failed

    transports:
        # https://symfony.com/doc/current/messenger.html#transport-configuration
        async:
            dsn: '%env(MESSENGER_TRANSPORT_DSN)%'

    routing:
        # Δρομολόγηση των μηνυμάτων σας στις μεταφορές
        'AppMessageStatusUpdate': async

Όπως μπορείτε να δείτε, αυτή τη φορά ο ορισμός της μεταφοράς δείχνει απευθείας στο async και ορίζει τη δρομολόγηση με τη μορφή της αποστολής των StatusUpdate μήνυμα στο διαμορφωμένο DSN. Αυτή είναι η μόνη περιοχή διαμόρφωσης, το μόνο που απομένει είναι η δημιουργία της λογικής και του επιπέδου υλοποίησης της ουράς AMQP. Για το σκοπό αυτό θα δημιουργήσουμε το δίδυμο StatusUpdateHandler και StatusUpdate τάξεις στο app2.

εικόνα
 use PsrLogLoggerInterface,
use SymfonyComponentMessengerAttributeAsMessageHandler,

[AsMessageHandler]

class StatusUpdateHandler
{
public function __construct(
private readonly LoggerInterface $logger,
) {}

public function __invoke(StatusUpdate $statusUpdate): void
{
    $statusDescription = $statusUpdate->getStatus(),

    $this->logger->warning('APP2: {STATUS_UPDATE} - '.$statusDescription),

    ## επιχειρησιακή λογική, π.χ. αποστολή εσωτερικής ειδοποίησης ή δημιουργία ουράς σε άλλα συστήματα.
}

}
εικόνα
 {
public function __construct(protected string $status){}

public function getStatus(): string
{
    return $this->status,
}

}


Ο πηγαίος κώδικας διατίθεται άμεσα: /thecodest-co/microservices-in-symfony/blob/main/app2/src/Message/StatusUpdate.php

Τέλος, το μόνο που πρέπει να γίνει είναι να δημιουργηθεί ένας τρόπος αποστολής ενός μηνύματος στον δίαυλο μηνυμάτων. Θα δημιουργήσουμε ένα απλό Εντολή Symfony για αυτό:

εικόνα
use SymfonyComponentConsoleAttributeAsCommand,
use SymfonyComponentConsoleCommandCommand,
use SymfonyComponentConsoleInputInputInterface,
use SymfonyComponentConsoleOutputOutputInterface,
use SymfonyComponentMessengerMessageBusInterface,

[AsCommand(

name: "app:send"

)]
class SendStatusCommand extends Command
{
public function construct(private readonly MessageBusInterface $messageBus, string $name = null)
{
parent::construct($name),
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
    $status = "Ο εργαζόμενος X έχει ανατεθεί στον Y",

    $this->messageBus->dispatch(
        message: new StatusUpdate($status)
    );

    return Command::SUCCESS,
}

}

Χάρη στην Εγχώνευση εξάρτησης μπορούμε να χρησιμοποιήσουμε μια περίπτωση της MessageBusInterface στην εντολή μας και να στείλουμε ένα StatusUpdate μήνυμα μέσω του αποστολή() στην ουρά μας. Επιπλέον, χρησιμοποιούμε επίσης τα χαρακτηριστικά PHP εδώ.

Αυτό είναι όλο - το μόνο που απομένει είναι να τρέξουμε το περιβάλλον Docker Compose και να δούμε πώς συμπεριφέρονται οι εφαρμογές μας.

Εκτέλεση του περιβάλλοντος και δοκιμές

Με το Docker Compose τα κοντέινερ με τις δύο εφαρμογές μας θα κατασκευαστούν και θα τρέξουν ως ξεχωριστές περιπτώσεις, το μόνο ενδιάμεσο επίπεδο θα είναι το rabbitmq και την υλοποίηση του διαύλου μηνυμάτων μας.

Από το ριζικό κατάλογο του έργου, ας εκτελέσουμε τις ακόλουθες εντολές:

cd ../ # βεβαιωθείτε ότι βρίσκεστε στον κύριο κατάλογο
 docker-compose up --build -d

Αυτή η εντολή μπορεί να πάρει κάποιο χρόνο, καθώς δημιουργεί δύο ξεχωριστά δοχεία με το PHP 8.1 + AMQP και τραβάει την εικόνα RabbitMQ. Κάντε υπομονή. Αφού χτιστούν οι εικόνες, μπορείτε να πυροδοτήσετε την εντολή μας από το app2 και να στείλετε κάποια μηνύματα σε μια ουρά.

 docker exec -it app2 php bin/console app:send

Μπορείτε να το κάνετε όσες φορές μπορείτε. Αρκεί να μην υπάρχει καταναλωτής τα μηνύματά σας δεν θα υποβληθούν σε επεξεργασία. Μόλις ενεργοποιήσετε το app1 και να καταναλώνετε όλα τα μηνύματα που θα εμφανίζονται στην οθόνη σας.

docker exec -it app1 php bin/console messenger:consume -vvv external_messages
εικόνα

Η πλήρης πηγαίος κώδικας μαζί με το README μπορούν να βρεθούν στο δημόσιο αποθετήριο μας The Codest Github

Περίληψη

Το Symfony με τις βιβλιοθήκες και τα εργαλεία του επιτρέπει μια γρήγορη και αποτελεσματική προσέγγιση για την ανάπτυξη σύγχρονων διαδικτυακές εφαρμογές. Με μερικές εντολές και λίγες γραμμές κώδικα είμαστε σε θέση να δημιουργήσουμε ένα σύγχρονο σύστημα επικοινωνίας μεταξύ εφαρμογών. Το Symfony, όπως PHP, είναι ιδανικό για ανάπτυξη διαδικτυακών εφαρμογών και χάρη στο οικοσύστημα και την ευκολία εφαρμογής του, το οικοσύστημα αυτό επιτυγχάνει μερικούς από τους καλύτερους δείκτες χρόνου διάθεσης στην αγορά.

Ωστόσο, το γρήγορο δεν σημαίνει πάντα καλό - στο παραπάνω παράδειγμα παρουσιάσαμε τον πιο απλό και γρήγορο τρόπο επικοινωνίας. Αυτό που οι πιο περίεργοι θα παρατηρήσουν σίγουρα είναι ότι υπάρχει έλλειψη αποσύνδεσης των γεγονότων του τομέα εκτός του επιπέδου εφαρμογής - στην τρέχουσα έκδοση διπλασιάζονται, και δεν υπάρχει πλήρης υποστήριξη για Φάκελος, μεταξύ άλλων δεν υπάρχει Γραμματόσημα. Για αυτούς και για άλλους, σας προσκαλώ να διαβάσετε το Μέρος ΙΙ, όπου θα καλύψουμε το θέμα της ενοποίησης της δομής του τομέα των εφαρμογών Symfony σε ένα περιβάλλον μικρουπηρεσιών και θα συζητήσουμε τη δεύτερη δημοφιλή μέθοδο επικοινωνίας μικρουπηρεσιών - αυτή τη φορά σύγχρονη, βασισμένη στο REST API.

πανό συνεργασίας

Σχετικά άρθρα

Ανάπτυξη λογισμικού

PHP 8.2: Τι νέο υπάρχει;

Η νέα έκδοση του PHP είναι προ των πυλών. Ποιες είναι οι νέες υλοποιήσεις που πρέπει να γνωρίζετε; Διαβάστε αυτό το άρθρο για να μάθετε!

The Codest
Sebastian Luczak PHP Αρχηγός μονάδας
Ανάπτυξη λογισμικού

PHP Ανάπτυξη. Symfony Console Component - Συμβουλές και κόλπα

Αυτό το άρθρο δημιουργήθηκε με σκοπό να σας δείξει τις πιο χρήσιμες και ανακτήσιμες συμβουλές και κόλπα σχετικά με την ανάπτυξη της κονσόλας Symfony.

The Codest
Sebastian Luczak PHP Αρχηγός μονάδας

Εγγραφείτε στη βάση γνώσεών μας και μείνετε ενήμεροι για την τεχνογνωσία από τον τομέα της πληροφορικής.

    Σχετικά με εμάς

    The Codest - Διεθνής εταιρεία ανάπτυξης λογισμικού με κέντρα τεχνολογίας στην Πολωνία.

    Ηνωμένο Βασίλειο - Έδρα

    • Γραφείο 303B, 182-184 High Street North E6 2JA
      Λονδίνο, Αγγλία

    Πολωνία - Τοπικοί κόμβοι τεχνολογίας

    • Πάρκο γραφείων Fabryczna, Aleja
      Pokoju 18, 31-564 Κρακοβία
    • Πρεσβεία του εγκεφάλου, Konstruktorska
      11, 02-673 Βαρσοβία, Πολωνία

      The Codest

    • Αρχική σελίδα
    • Σχετικά με εμάς
    • Υπηρεσίες
    • Case Studies
    • Μάθετε πώς
    • Καριέρα
    • Λεξικό

      Υπηρεσίες

    • Συμβουλευτική
    • Ανάπτυξη λογισμικού
    • Backend Ανάπτυξη
    • Ανάπτυξη Frontend
    • Staff Augmentation
    • Backend Developers
    • Μηχανικοί cloud
    • Μηχανικοί δεδομένων
    • Άλλα
    • Μηχανικοί QA

      Πόροι

    • Γεγονότα και μύθοι σχετικά με τη συνεργασία με εξωτερικό συνεργάτη ανάπτυξης λογισμικού
    • Από τις ΗΠΑ στην Ευρώπη: Γιατί οι αμερικανικές νεοσύστατες επιχειρήσεις αποφασίζουν να μετεγκατασταθούν στην Ευρώπη
    • Σύγκριση υπεράκτιων κόμβων ανάπτυξης τεχνολογίας: Ευρώπη (Πολωνία), ASEAN (Φιλιππίνες), Ευρασία (Τουρκία)
    • Ποιες είναι οι κορυφαίες προκλήσεις των CTOs και των CIOs;
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Πνευματικά δικαιώματα © 2025 από The Codest. Όλα τα δικαιώματα διατηρούνται.

    elGreek
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek