Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Bom dia. Vejam se conseguem me ajudar.
Estou criando um sistema MVC utilizando o mesmo esquema do Weslley da Code Education.
Esquema das pastas
/App
=> Controllers
- Home.php
=> Models
- Não há necessidade por enquanto, porque ainda não consigo interagir com essa camada
=> Views
-> Index
- home.phtml
- layout.phtml
=> Init.php
/public
- index.php
- .htaccess
/vendor
=> composer
=> SON
-> Controller
- Action.php
-> DB
- Table.php
-> DI
- Container.php
-> Init
- Bootstrap.php
=> autoload.php
Os arquivos
App\Controllers\Home
namespace App\Controllers;
use SON\Controller\Action;
use \SON\DI\Container;
class Home extends Action
{
// homepage
public function home()
{
$this->render('home');
}
}
App\Views\layout.phtml
<html>
<head>
<meta charset="utf-8">
<title>MVC</title>
<link rel="stylesheet" media="screen" href="../App/Views/css/style.css">
</head>
<body>
<section class="content">
<?= $this->content(); ?>
</section>
</body>
</html>
App\Views\Index\home.phtml
<h1>Página inicial da nossa aplicação</h1>
App\init
namespace App;
use SON\Init\Bootstrap;
class Init extends Bootstrap
{
protected function initRoutes()
{
/** Define the panel route */
$ar['home'] = ['route' => '/', 'controller' => 'home', 'action' => 'home'];
$this->setRoutes($ar);
}
public static function getDb()
{
$db = new \PDO("mysql:host=localhost;dbname=dbtest","root","");
return $db;
}
}
public\index
require_once '../vendor/autoload.php';
$init = new \App\Init;
vendor\SON\Controller\Action
namespace SON\Controller;
class Action
{
protected $view;
protected $action;
public function __construct() {
$this->view = new \stdClass;
}
public function render($action, $layout = true) {
$this->action = $action;
if($layout == true && file_exists("../App/Views/layout.phtml")):
include_once '../App/Views/layout.phtml';
else:
$this->content();
endif;
}
public function content() {
$atual = get_class($this);
$singleClassName = strtolower(str_replace("App\\Controllers\\", "", $atual));
include_once '../App/Views/' . $singleClassName . '/' . $this->action . '.phtml';
}
}
vendor\SON\DB\Table - Não é importante agora porque, como disse lá em cima, não faço a interação com a Model ainda
vendor\SON\DI\Container
namespace SON\DI;
class Container
{
public static function getClass($name)
{
$str_class = "\\App\\Models\\" . ucfirst($name);
$class = new $str_class(\App\Init::getDb());
return $class;
}
}
vendor\SON\Init\Bootstrap
namespace SON\Init;
abstract class Bootstrap
{
private $routes;
public function __construct()
{
$this->initRoutes();
$this->run($this->getUrl());
}
abstract protected function initRoutes();
protected function run($url)
{
array_walk($this->routes, function($route) use($url){
if($url == $route['route']){
$class = "App\\Controllers\\" . ucfirst($route['controller']);
$controller = new $class;
$controller->$route['action']();
}
});
}
protected function setRoutes(array $routes)
{
$this->routes = $routes;
}
protected function getUrl()
{
return parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH);
}
}
O autoload das classes é feito pelo composer e parece estar tudo certo.
Estou começando agora a trabalhar com MVC e o pior erro é o que não mostra nenhum resultado, não sei por onde seguir ou buscar a solução. Fiz diversas revisões e isso me ajudou até entender melhor o conceito e a estrutura do projeto. Setei a rota, criei a classe no controller da APP que faz o render do html, porém nada é impresso na tela.
Agradeço a quem puder dedicar um tempinho pra me ajudar a solucionar esse problema.
Então Gariel já tentei exibir os erros assim
error_reporting(E_ALL);
ini_set('display_errors', 1);
Mas não retorna nada
\public
error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once '../vendor/autoload.php';
$init = new \App\Init;
o composer.json está assim
{
"name": "son/mvc",
"require": {
"php": ">=5.3"
},
"description": "mvc project",
"minimum-stability": "stable",
"license": "proprietary",
"autoload": {
"psr-0": {
"SON": "vendor",
"App": "/"
}
},
"authors": [
{
"name": "author's name",
"email": "email@example.com"
}
]
}
Se houver algum erro de parser, o seu código de exibição de erros não funcionará. Por isso precisa alterar no php.ini.
Seu autoload não parece estar correto. Além do mais, utilize o autoload psr-4. Segue o exemplo:
{
"autoload": {
"psr-4": {
"App\\": "App/",
"SON\\": "vendor/SON/",
"": "" //fallback conforme as pastas
}
}
}
Assim está correto?
{
"name": "son/mvc",
"require": {
"php": ">=5.3"
},
"minimum-stability": "alpha",
"autoload": {
"psr-4": {
"App\\": "App/",
"SON\\": "vendor/SON/"
}
},
"config": {
"bin-dir": "bin"
}
}
Não estudei a fundo sobre as psr- mas entendi que são padrões de organização das classes dentro do meu programa, estou certo?
Notei que a psr-4 inclui e escapa a barra.
Também alterei o php.ini e defini
error_reporting=E_ALL;
A aplicação continua não exibindo nenhum erro na tela.
Na PSR-0 era uma obrigatoriedade todo o namespace ser uma pasta, mesmo que o vendor, em conjunto com os subnamespaces, fossem extenso, deveria existir uma pasta para ele.
Ja na PSR-4, essa obrigatoriedade foi removida. Você adiciona um namespace como prefixo (caso ele não exista como um file path) e, o restante, segue a mesma lógica da PSR-0 (criação de pastas para os namespaces).
Na PSR-0 era opcional, na PSR-4 é obrigatório.
Nos links abaixo há alguns exemplos:
^^ acabei de lê-los por alto, meu inglês ainda não está 100%.
Esses são padrões atuais válidos para se desenvolver frameworks?
O zend2, por exemplo, trabalha dessa maneira? Siginifica que devo sempre trabalhar com essa organização e nomenclatura de pastas para projetos web? Isso ai é o famoso padrão MVC na prática?
São apenas algumas dúvidas rs...
A forma como as tarefas são dividas e delegas aos responsáveis é fascinante.
Fazia do meu jeito, um pouco diferente, não desorganizado, mas pelo que vi, trabalhar sobre documentações torna tudo mais fácil e simples de implementar.
Esses são padrões atuais válidos para se desenvolver frameworks?
Sim, são. Mas sempre estão em constante atualização. O PSR-4 eu utilizo. Já PSR-1 e PSR-2 não são do meu gosto.
Lembrando que são dicas e conselhos da comunidade PHP. O que mais vale é o que você, em conjunto com sua equipe de desenvolvimento determinam.
O zend2, por exemplo, trabalha dessa maneira? Siginifica que devo sempre trabalhar com essa organização e nomenclatura de pastas para projetos web?
Para utilizar o autoload corretamente, deve utilizar aquela nomenclatura. Ainda há a inclusão do "_" (underline/underscore), que seria o padrão antes do PHP 5.3 de nomenclatura de classes portado para o mundo dos Namespaces. Sei que o Zend utiliza o autoload do composer, que é baseado na PSR. Agora não sei dizer se o Zend utiliza tudo de acordo com a PSR-4 ou se utiliza de forma mesclada (o que é possível).
Isso ai é o famoso padrão MVC na prática?
Não. O MVC, padrão arquitetural, é conhecido por promover a organização de código. Entretanto, apenas a organização, não garante que seja um código em MVC.
A questão de nomenclatura e namespaces é voltado mais para as questões de pacotes. No link abaixo há uma boa explicação sobre os pacotes:
http://forum.imasters.com.br/topic/448099-resolvidonamespace/?p=1772073
Por exemplo, no artigo que eu escrevi uns meses atras, disponibilizei, através do composer, utilizando a definição da PSR-4:
http://forum.imasters.com.br/topic/537066-tutorial-integridade-de-colecoes-com-uso-de-iterator/
Aqui você encontra o repositório do projeto: https://bitbucket.org/harbingerproject/iterator
Ainda quero lançar mais, até um sobre como disponibilizar no composer/packagist.
>
São apenas algumas dúvidas rs...
A forma como as tarefas são dividas e delegas aos responsáveis é fascinante.
Fazia do meu jeito, um pouco diferente, não desorganizado, mas pelo que vi, trabalhar sobre documentações torna tudo mais fácil e simples de implementar.
Sim, trabalhar com um padrão conhecido, e definido por uma comunidade, ajuda a ter o código organizado e mais acessível a outros programadores.
Existe alguma forma de exibir possíveis falhas além do php.ini?
Já revisei mais 3 vezes e não consigo encontrar o erro D=
Se liga só Gabriel
public\index
<?php
require_once '../vendor/autoload.php';
$init = new app\Init;
app\init
<?php
namespace app;
class Init
{
public function __construct()
{
echo 'Hello word!';
}
}
Ele não identifica a clase
Fatal error: Class 'app\Init' not found in D:\Server\public_html\mvc\public\index.php on line 4
vendor\composer\autoload_namespaces
<?php
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'SON' => array($vendorDir),
'App' => array($baseDir . '/'),
);
\composer.json
{
"name": "son/mvc",
"require": {
"php": ">=5.3"
},
"minimum-stability": "alpha",
"authors": [
{
"name": "Samuel",
"email": ""
}
],
"autoload": {
"psr-4": {
"SON\\": "vendor/SON/",
"app\\": "/"
}
},
"config": {
"bin-dir": "bin"
}
}
precisa colocar o início do namespace também:
"autoload": {
"psr-4": {
"SON\\": "vendor/SON/",
"app\\": "app/"
}
Agora sem o composer Gabriel, só pra eu entender melhor como trabalhar com classes e métodos abstratos dentro de um padrão MVC.
A estrutura
api
controllers
Foo.class.php
Init.php
public
index.php
public\index
require_once '../api/Init.php';
$init = new Init;
api\Init
<?php
namespace api;
use api\controllers\Foo;
class Init extends Foo
{
/**
* Autoload the class when an object of created from it
* @param $Class
*/
public function __autoload($Class)
{
$dir = 'store';
if(file_exists($dir . '/' . $Class . '.class.php')):
include_once $dir . '/' . $Class . '.class.php';
endif;
}
/**
* Set the routes used in this system
*/
public function initRoutes()
{
$route['home'] = ['route' => '/', 'controller' => 'home', 'action' => 'home'];
$this->setRoutes($route);
}
/**
* Connect wich database
* @return \PDO
*/
public static function getDb()
{
$db = new \PDO("mysql:host=localhost;dbname=appconection","root","");
return $db;
}
}
Fatal error: Class 'api\controllers\Foo' not found
To achando que esse __autoload tá zuado
É pessoal ainda to com esse dilema do arquivo não poder ser incluído porque não foi encontrado. Vou ter que descobrir porque fica impossível trabalhar incluindo tudo na mão sempre que precisar de um novo objeto.
Resolvi utilizando o autload do composer.
olá amigo estou tendo mesmo problema , como conseguiu resolver ?
Como estão as configurações de exibição de erro no php.ini? De uma verificada no log do apache também. Talvez tenha algo passando despercebido.
Como está a definição do autoload no composer.json?