Nou in utilizarea composer

Salut, incerc sa utilizez si eu composer, dar ceva nu este in regula.Am inteles ca acesta ma ajuta in multe cazuri,si dezvoltarea codului e mult mai usoara.Astfel, mi-am bagat nasul si am urmatorul .json :

{
  "name": "vendor_name/bin",
  "description": "description",
  "minimum-stability": "stable",
  "license": "proprietary",
  "authors": [
    {
      "name": "Admin",
      "email": "[email protected]"
    }
  ],
  "require": {
    "php-tmdb/api": "^3.0",
    "imdbphp/imdbphp": "^6.4"
  },
  "autoload": {
    "psr-4": {
      "Dashboard\\": "wp/"
    }
  }
}

Am creat un folder in vendor, unde doresc sa creez clasele mele si sa le incarc cu autoload-ul.Folder-ul este “wp” iar fisierul este “bootstrap.php”, in el am urmatorul cod, de test:

<?php
namespace Dashboard;
class clear{
    public function create(){
        return wp_die("am ajuns la create() function");
    }
}
?>

Iar, in wordpress, in functions.php am incercat sa ajung la clasa mea, folosindu-ma de namespace.

<?php
require "bin/vendor/autoload.php";

use Dashboard\clear;


$test = new Dashboard\clear;

$test->create();

Primesc erori cum ca aceasta clasa nu exista, sau daca folosesc: use Dashboard\clear as cl; ori use Dashboard

Warning: The use statement with non-compound name ‘Dashboard’ has no effect in.

Mentionez ca si in namespace-uri sunt incepator.Ideea e ca nu pot ajunge la clasa, ori nu se incarca bine din json, ori eu nu o “caut” bine. Multumesc !!

Gândește-te în felul următor:

  • codul tău stă în src (sau includes sau inc sau wp sau ce mai vrei tu)
  • codul altora stă în vendor (și este administrat exclusiv de composer)

Acestea fiind spuse, pentru a avea autoload la clase, ai nevoie de câteva chestii:

  1. O clasă/fișier; (clasă, interfață, trait)
  2. Numele clasei este numele fișierului. Clasa și fișierul sunt case-sensitive. Chiar dacă nu (cred?) că PSR4 menționează asta, eu prefer ca toate fișierele ce conțin structuri OOP (clase/interfețe/trait) să fie cu majuscule, pentru a le diferenția de restul.
  3. Namespace-urile reflectă structura de directoare

Acestea fiind spuse, ca să respecți PSR4, structura ta ar trebui să fie cam așa:

/wp/Dashboard/Clear.php
/vendor/
index.php

Extra tips:

  1. De fiecare dată când modifici composer.json, trântești și un composer dump
  2. Dacă folosești use, nu este nevoie să mai folosești namespace-ul la instanțiere:
use Dashboard\clear;
- $test = new Dashboard\clear;
+ $test = new clear;
1 Like

Multumesc mult, a functionat. Acum, as mai avea o nelamurire, in cazul meu…Daca folosesc : use Dashboard, fara nicio clasa, si as dori sa o initializez eu separat,spre exemplu $clasa = new Clear (s-ar autointelege ca aceasta clasa Clear vine din acel Dashboard utilizat), imi zice ca The use statement with non-compound name 'Dashboard' has no effect , Iar daca folosesc use Dashboard\clear; functioneaza, astfel eu trebuie sa merg cu acest “use” pentru fiecare clasa ce-i apartine,deci nu-l pot incarca pe tot odata si apoi sa le chem. Nu stiu daca am explicat bine…

use este o modalitate de a informa PHP că vei folosi o clasă, interfață sau funcție, permițându-ți să faci și un alias. Nu poți include toate elementele dintr-un anumit namespace (cu use namespace\* de ex).

Va trebui ori să folosești tot FQN-ul (new \namespace\subnamespace\Clasă) la instanțiere ori la use.

Dacă ești în interiorul unui namespace, poți folosi un sub-namespace direct:

namespace foo;

- use foo\bar\baz\Class
+ use bar\baz\Class

Dar NU poți urca doar un singur nivel:

namespace bar;

use ..\baz\Class // <<<<<< NU poți face asta

Gata, am inteles. Multumesc mult de tot, oricum singura chestie PRO care o vad e ca poti crea mai multe clase cu acelasi nume, si te poti organiza putin mai usor.

…e vitala, de fapt.

Poți instanția clasa clear folosind “a fully qualified class name”:

<NamespaceName>(<SubNamespaceNames>)*<ClassName>

$test = new \Dashboard\clear;

Altfel, clasa e cautată în namespace-ul curent.

Poți importa clasa folosind operatorul use (echivalentul symbolic link pentru namespaces) și apoi folosi varianta scurtă:

use Dashboard\clear;
$test = new clear;

Nelămurirea ta provine de la faptul că lipsește backslash-ul de la începutul importului. Manualul PHP spune că e “unnecessary and not recommended”, iar standardul PSR-4 îl marchează ca “disallowed”, pentru că importurile sunt automat “fully qualified”.

1 Like

Salut,acum ma lovesc de alta problema, totul a functionat ok, dar cand am incercat sa fac o ierarhie, namespace Dashboard/Clear; ,a luat-o razna, la modul ca Uncaught Error: Class 'Dashboard\Clear\Cleaner'

Codul

use Dashboard\Clear;
$clear = new  Clear\Cleaner();

Functioneaza doar daca ma duc direct catre fisierul original, require dashboard/clear.php , daca merg cu autoload-ul, nu mai ajung acolo.

    "autoload": {
        "psr-4": {
            "Dashboard\\": "Dashboard/*",
            "Plugins\\": "Plugins"
        }
    },

Am incercat si cu "Dashboard\\Clear\\": "Dashboard/*", , cu * sa fara, niciun rezultat.

Am dat composer dump-autoload, a regenerat fisierele, dar tot degeaba.

La use trebuie să specifici FQN al clasei.

Dacă ai clasa Cleaner în namespace-ul Dashboard\Clear, trebuie să specifici:

use Dashboard\Clear\Cleaner;
$clear = new  Cleaner();

sunt bou rau, multumesc. Problema e ca sunt si plecat la munca, am un program de toata jena, nu am timp sa ma documentez suficient si dau bataie sa fac si eu ceva…Sarbatori fericite !

E buna autocritica, dar nici chiar asa :smiley:

FQN al clasei iti trebuie cand instantiezi clasa, nu neaparat cand folosesti “use”;

namespace Dashboard\Clear;

class Cleaner{
    function __construct(){
        echo "See!";
    }
}

namespace App;

use Dashboard\Clear;

$class = new Clear\Cleaner();

Modalitatea asta e folosita mai ales cand ai clase cu acelasi nume in namespace-uri diferite.

use App\Entity;
use App\Model;

$productEntity = new Entity\Product();
$productModel = new Model\Product();

Bineinteles poti sa folosesti si aliases, fiecare cum vrea, dar in modul asta scrii mai putin.

@Cata1991 in general best practice este sa ai un singur root de autoload pentru folderul src.

poti sa incerci asa

"autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }

si toate clasele o sa stea in folderul src si atata timp cat respecti ce a zis @iamntz mai sus ca namespace-urile sa respecte structura de fisiere nu o sa ai probleme.

Manualul zice altceva:

The ability to refer to an external fully qualified name with an alias

Dacă nu ar trebui să fie așa, use ar funcționa ca un soi de glob, ceea ce nu prea se întâmplă :slight_smile:

Dacă treaba aia merge în Laravel/Symfony, s-ar putea ca framework-ul să facă ceva scamatorii.

ori use bla\bla\class; new class() ori direct new bla\bla\class()

ps: merge si ce ai spus tu, dar nu prea ai ocazia sa-l folosesti asa.
mai des am vazut folosit cu alias decat de inclus tot namespace-ul

Ce am zis eu functioneaza nativ in php de pe vremea php 5.3.

Testat aici.

Chiar si in manual ai exemplul

$obj = new namespace\Another; // instantiates object of class foo\Another

use != include

de ce nu asa?

doar sunt curios.

si logic ca use nu-i acelasi lucru cu include.

ps: nvm, imi scapase partea cu acelasi nume, ns diferit.