Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá pessoal!
A minha dúvida fica por conta de como aninhar os registros em entidades que possuem relacionamentos.
Quanto se trata de entidades individuais (Aluno, Professor, Secretaria) fica fácil - basicamente varrer os atributos dela e povoar.
Aluno
---alu_id
---alu_nome
disparada a consulta, retorna:
[0] => Array
(
[alu_id] => 1
[alu_nome] => "José de Souza"
)
[1] => Array [alu_id] => 1
[alu_nome] => "Marcos da Silva"
)
$class_name = $this->getClassName($obj);
$class_vars = get_class_vars(get_class($obj));
foreach($check as $c)$Obj = new $class_name;
foreach ($class_vars as $field => $value) $Obj->$field = $c[$field];
}
}
$objs[] = $Obj;
}
return $objs
Agora o problema fica por conta de entidades que tem relações (Secretaria -> Orgão -> Conexões/Logradouros)
por conta da lógica de aninhar os registros:
Secretaria
---Órgãos
------Conexões
------Logradouros
Vejamos o registro:
[0] => Array
(
[sec_id] => 1
[sec_idmae] => 0
[sec_secretaria] => Secretaria de Assistência Social
[sec_fk_usu_id] => 1
[sec_datacriacao] => 2012-08-20 09:11:12
[org_id] => 6
[org_fk_sec_id] => 1
[org_orgao] => Centro da Juventude
[org_fk_usu_id] => 1
[org_datacriacao] => 2012-08-22 09:49:49
[con_id] =>
[con_fk_org_id] =>1
[con_fk_contip_id] => 1 (3G)
[con_fk_usu_id] => 1
[con_datacriacao] => 2012-08-21 10:04:50
[con_fk_consta_id] => 1 (Ativa)
[con_statusdata] => 2012-08-21 10:04:50
[orglog_id] => 6
[orglog_fk_org_id] => 6
[orglog_cep] => 87010-340
[orglog_logradouro] => R 44444444
[orglog_numero] => 832
[orglog_bairro] => ZONA 02
[orglog_fk_usu_id] => 1
[orglog_datacriacao] => 2012-08-22 09:49:50
)
Peço ajuda de vocês para entender quais atributos adicionais precisariam ter as entidades Secretaria (Mãe), Órgão (Filha e Mãe) e Conexões/Logradouros (Filhas) e como interpretá-las.
E aí pessoal, o que acham?
Obrigado pela atenção.
>
A única coisa seria reorganizar o array de entrada para que bata com a árvore hierárquica que você quer usar.
kkkk faz 2 semanas q estou tentando fazer isso
manual da pra fazer..q nem você fez ali..o aninhamento..
alguma ideia?
Neste exemplo, estou assumindo que o valor do print_r que você enviou anteriormente está na váriavel $row:
// separando os elementos em categorias
$assoc = array();
foreach($row as $key => $value){
preg_match('@([a-z]+)_(\w+)@',$key,$reg);
$assoc[$reg[1]][$reg[2]] = $value;
}
// procurando as associações
foreach($assoc as $keyRow => &$element){
foreach($element as $keyElement => $value){
if(preg_match('@fk_((\w+)_id)@',$keyElement,$reg) && array_key_exists($reg[2], $assoc)){
$assoc[$reg[2]][$keyRow][] = &$element;
$assoc[$keyRow]['_added'] = true;
}
}
}
// removendo os que foram adicionados em outros niveis
foreach($assoc as $key => &$item){
if(array_key_exists('_added', $item)){
unset($item['_added']);
unset($assoc[$key]);
}
}
print_r($assoc);
Com os valores que você enviou, a saída deverá ser parecida com esta:
Array
(
[sec] => Array
(
[id] => 1
[idmae] => 0
[secretaria] => Secretaria de Assistência Social
[fk_usu_id] => 1
[datacriacao] => 2012-08-20 09:11:12
[org] => Array
(
[0] => Array
(
[id] => 6
[fk_sec_id] => 1
[orgao] => Centro da Juventude
[fk_usu_id] => 1
[datacriacao] => 2012-08-22 09:49:49
[con] => Array
(
[0] => Array
(
[id] =>
[fk_org_id] => 1
[fk_contip_id] => 1 (3G)
[fk_usu_id] => 1
[datacriacao] => 2012-08-21 10:04:50
[fk_consta_id] => 1 (Ativa)
[statusdata] => 2012-08-21 10:04:50
)
)
[orglog] => Array
(
[0] => Array
(
[id] => 6
[fk_org_id] => 6
[cep] => 87010-340
[logradouro] => R 44444444
[numero] => 832
[bairro] => ZONA 02
[fk_usu_id] => 1
)
)
)
)
)
)
@braços e fique com Deus!
Edit: correção da saida de exemplo
>
Neste exemplo, estou assumindo que o valor do print_r que você enviou anteriormente está na váriavel $row:
Hugo, isso realmente está interessante.
Só um detalhe, pelo q entendi no code, ele buscaria 2 níveis.
Alguma idéia de como fazer para "n" níveis?
Eu tive que aumentar registro, veja:
Secretaria
---Órgãos
------Conexões
---------Conexão Tipo
---------Conexão Status
------Logradouros
[8] => Array
(
[sec_id] => 6
[sec_idmae] => 1
[sec_secretaria] => C.R.A.S.
[sec_fk_usu_id] => 1
[sec_datacriacao] => 2012-08-20 09:25:41
[org_id] => 1
[org_fk_sec_id] => 6
[org_orgao] => CRAS2
[org_fk_usu_id] => 1
[org_datacriacao] => 2012-08-20 10:45:43
[orglog_id] => 2
[orglog_fk_org_id] => 1
[orglog_cep] => 87010-350
[orglog_logradouro] => AV ANCHIETA
[orglog_numero] => 533
[orglog_bairro] => ZONA 02
[orglog_fk_usu_id] => 1
[orglog_datacriacao] => 2012-08-20 10:46:51
[con_id] => 1
[con_fk_org_id] => 1
[con_fk_contip_id] => 2
[con_fk_usu_id] => 1
[con_datacriacao] => 2012-08-24 11:30:19
[con_fk_consta_id] => 1
[con_statusdata] => 2012-08-24 11:30:56
[contip_id] => 2
[contip_tipo] => ADSL
[contip_tabela] => tbl_conexao_adsl
[consta_id] => 1
[consta_status] => Ativa
)
A minha idéia inicial foi a seguinte:
class Secretaria
{
public $sec_id;
public $sec_idmae;
public $sec_secretaria;
public $sec_fk_usu_id;
public $sec_datacriacao;
public $hasMany_Orgao;
}
class Orgao
{
public $org_id;
public $org_fk_sec_id;
public $org_orgao;
public $org_fk_usu_id;
public $org_datacriacao;
public $hasMany_Conexao;
public $hasMany_Orgao_Logradouro;
}
class Orgao_Logradouro
{
public $orglog_id;
public $orglog_fk_org_id;
public $orglog_cep;
public $orglog_logradouro;
public $orglog_numero;
public $orglog_bairro;
public $orglog_fk_usu_id;
public $orglog_datacriacao;
}
class Conexao
{
public $con_id;
public $con_fk_org_id;
public $con_fk_contip_id;
public $con_fk_usu_id;
public $con_datacriacao;
public $con_fk_consta_id;
public $con_statusdata;
public $hasOne_Conexao_Tipo;
public $hasOne_Conexao_Status;
}
class Conexao_Tipo
{
public $contip_id;
public $contip_tipo;
public $contip_tabela;
}
class Conexao_Status
{
public $consta_id;
public $consta_status;
}
function getPK($entity)$obj = new $entity;
$vars = get_class_vars(get_class($obj));
foreach($vars as $field => $value) return $field;
break;
}
}
function populate($entity, $r)$class = new $entity;
$vars = get_class_vars(get_class($class));
foreach ($vars as $field => $value) $class->$field = $r[$field];
}
elseif(strpos($field, "hasMany_") === false)
{
if($r[getPK(str_replace("hasOne_","",$field))])
{
$class->$field = populate(str_replace("hasOne_","",$field), $r);
}
}
else
{
if($r[getPK(str_replace("hasMany_","",$field))])
{
$arr = array();
$arr[$r[getPK(str_replace("hasMany_","",$field))]] = populate(str_replace("hasMany_","",$field), $r);
$class->$field = $arr;
}
}
}
return $class;
}
//ignição1
foreach($rows as $r)
{
$arrg[] = populate("Secretaria", $r);
}
//ignição2
//foreach($rows as $r)
//{
// if(!isset($arrg[$r['sec_id']]))
// {
// $arrg[$r["sec_id"]] = populate("Secretaria", $r);
// }
//}
Mas isso tem problemas. 2 casos: na ignição 1 ele retorna os registros virgens, sem aninhamento.
Já na ignição 2, ele fica perfeito. Porém so exibe 1 registro/nó.
Veja os resultados:
Ignição 1:
Ignição 2:
Só pra você se situar,
eu fiz uma lógica manual que monta tudo corretíssimamente rsrsrs:
foreach($rows as $r)
{
if(!isset($objs[$r['sec_id']]))
{
$objs[$r['sec_id']] = new Secretaria();
$objs[$r['sec_id']]->sec_secretaria = $r["sec_secretaria"];
} $objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']] = new Orgao();
$objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->org_orgao = $r["org_orgao"];
} $objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Orgao_Logradouro[$r["orglog_id"]] = new Orgao_Logradouro();
$objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Orgao_Logradouro[$r["orglog_id"]]->orglog_logradouro = $r['orglog_logradouro'];
} $objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Conexao[$r['con_id']] = new Conexao();
$objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Conexao[$r['con_id']]->con_datacriacao = $r['con_datacriacao'];
$objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Conexao[$r['con_id']]->hasOne_Conexao_Tipo = new Conexao_Tipo();
$objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Conexao[$r['con_id']]->hasOne_Conexao_Tipo->contip_tipo = $r["contip_tipo"];
$objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Conexao[$r['con_id']]->hasOne_Conexao_Status = new Conexao_Status();
$objs[$r['sec_id']]->hasMany_Orgao[$r['org_id']]->hasMany_Conexao[$r['con_id']]->hasOne_Conexao_Status->consta_status = $r["consta_status"];
}
}
Não sei dizer.. mas parece tão perto kkkk...
O que você acha??
Abraços.
Você tentou juntar os dois exemplos que te mandei?
O primeiro das entidades e o segundo de montar o array recursivo?
Não, ele não se limita a dois níveis.
Ele usa os nomes das propriedades para fazer o aninhamento das informações.
Só juntei os dois exemplos que te mandei.
@braços
>
Você tentou juntar os dois exemplos que te mandei?
O primeiro das entidades e o segundo de montar o array recursivo?
Não, ele não se limita a dois níveis.
Ele usa os nomes das propriedades para fazer o aninhamento das informações.
Só juntei os dois exemplos que te mandei.
@braços
Hugo, eu fiz isso msmo.. mas acho q tem um erro aí.. veja:
-modifiquei o valor de $str para o resultado q tem o registro aumentado
-adicionei no test.php
-include 'ConexaoStatus.php';
-include 'ConexaoTipo.php';
-criei 2 arquivos:
ConexaoTipo.php
namespace example {
include_once __DIR__ . DIRECTORY_SEPARATOR . 'Base.php';
class ConexaoTipo extends Base {
public $id;
public $tipo;
}
}
/ End of file ConexaoTipo.php /
/ Location: ConexaoTipo.php /
ConexaoStatus.php
<?php
namespace example {
include_once __DIR__ . DIRECTORY_SEPARATOR . 'Base.php';
class ConexaoStatus extends Base {
public $id;
public $status;
}
}
/ End of file ConexaoStatus.php /
/ Location: ConexaoStatus.php /
e por ultimo adicionei as variaveis no Conexao.php:
namespace example {
include_once __DIR__ . DIRECTORY_SEPARATOR . 'Base.php';
class Conexao extends Base {
public $id;
public $fk_org_id;
public $fk_contip_id;
public $fk_usu_id;
public $datacriacao;
public $fk_consta_id;
public $statusdata;
/**
* @var array
* @ReferencedClass \example\ConexaoStatus
*/
public $constatus = array();
/**
* @var array
* @ReferencedClass \example\ConexaoTipo
*/
public $contipo = array();
}
}
/ End of file Conexao.php /
/ Location: Conexao.php /
mas acho q isso ta errado... pq nao seria @var array... em se tratando de um rel 1:1 -> 1 conexao so tem 1 status e so 1 tipo.
Poderia informar como eu configuro?
Abraço.
Como dito anteriormente, ele usa os nomes das propriedades para montar os elementos aninhados.
Veja (reduzi para ficar mais fácil):
[sec_id] => 1
[sec_idmae] => 0
[sec_secretaria] => Secretaria de Assistência Social
[sec_fk_usu_id] => 1
[sec_datacriacao] => 2012-08-20 09:11:12
[org_id] => 6
[org_fk_sec_id] => 1 <-- aqui vemos que este "org" pertence a uma "sec"
[org_orgao] => Centro da Juventude
[org_fk_usu_id] => 1
[org_datacriacao] => 2012-08-22 09:49:49
O padrão que ele procura é:
Este é o processo feito no meu post #4. Dê uma boa estudada nele, tente entender bem este código que é praticamente ali que a mágica acontece :thumbsup:
Depois, que os nomes das propriedades estão devidamente aninhados, ele passa pra o processo de popular (método populate) as propriedades do objeto com os indices do array. Veja que os indices tem o mesmo nome das propriedades das classes. Para que o método populate funcione, é imprescindível que as propriedades do objeto tenham o mesmo nome dos indices do array. Analise como o script exposto no post #4 está criando o array para que você possa criar as propriedades nos objetos.
@braços e fique com Deus!
>
Como dito anteriormente, ele usa os nomes das propriedades para montar os elementos aninhados.
[sec_id] => 6
[sec_idmae] => 1
[sec_secretaria] => C.R.A.S.
[sec_fk_usu_id] => 1
[sec_datacriacao] => 2012-08-20 09:25:41
[org_id] => 1
[org_fk_sec_id] => 6
[org_orgao] => CRAS2
[org_fk_usu_id] => 1
[org_datacriacao] => 2012-08-20 10:45:43
[orglog_id] => 2
[orglog_fk_org_id] => 1
[orglog_cep] => 87010-350
[orglog_logradouro] => AV ANCHIETA
[orglog_numero] => 533
[orglog_bairro] => ZONA 02
[orglog_fk_usu_id] => 1
[orglog_datacriacao] => 2012-08-20 10:46:51
[con_id] => 1
[con_fk_org_id] => 1
[con_fk_contip_id] => 2
[con_fk_usu_id] => 1
[con_datacriacao] => 2012-08-24 11:30:19
[con_fk_consta_id] => 1
[con_statusdata] => 2012-08-24 11:30:56
[contip_id] => 2
[contip_tipo] => ADSL
[contip_tabela] => tbl_conexao_adsl
[consta_id] => 1
[consta_status] => Ativa
Hugo, bem, pelo q identifiquei, de acordo com o seu padrão, só os nomes das variáveis no Conexao.php q estavam erradas:
De:
/**
* @var array
* @ReferencedClass \example\ConexaoStatus
*/
public $constatus = array();
/**
* @var array
* @ReferencedClass \example\ConexaoTipo
*/
public $contipo = array();
Corrigido para:
/**
* @var array
* @ReferencedClass \example\ConexaoTipo
*/
public $contip = array();
/**
* @var array
* @ReferencedClass \example\ConexaoStatus
*/
public $consta = array();
Mas mesmo assim não funciona. Agora, o q não saquei foi q contip está como array... mas contip é 1:1, entao teria q ser um objeto nao? Essa parte não ficou clara... se (Secretaria) org <-> id (Orgao) ... se (Orgao) con <-> id (Conexao) ... seria (Conexao) contip <-> id (ConexaoTipo), mas como object ao inves de array ???
Abraço.
1 - Pelo exemplo que mostrei, não há 1 : 1. Somente 1 : n. Se quiser fazer 1 : 1, você terá que, de alguma forma, informar que não pode aceitar mais de uma ocorrencia, no método populate. Sugestão: use uma anotação (como usei para identificar qual classe usar).
2 - veja:
[org_fk_sec_id]
A logica que usei no meu exemplo, indica que "org" pertence a uma "sec".
Logo:
[con_fk_contip_id]
Indica que uma "con" pertence a uma "contip".
Se quiser fazer ao contrário, terá também que indicar isso.
Para ver como fica, dê um print_r($assoc) depois do terceiro foreach. Então verá como fica a árvore aninhada.
@braços
Edit: como sou um cara bacana (ehehehe) fiz um exemplo de inversão para você. Mude o segundo foreach para o abaixo (e altere os objetos, se necessário).
// procurando as associações
$invers = array('consta','contip');
foreach($assoc as $keyRow => &$element){
foreach($element as $keyElement => $value){
if(preg_match('@fk_((\w+)_id)@',$keyElement,$reg) && array_key_exists($reg[2], $assoc)){
if(!in_array($reg[2],$invers)){
$assoc[$reg[2]][$keyRow][] = &$element;
$assoc[$keyRow]['_added'] = true;
} else {
$assoc[$keyRow][$reg[2]][] = &$assoc[$reg[2]];
$assoc[$reg[2]]['_added'] = true;
}
}
}
}>
1 - Pelo exemplo que mostrei, não há 1 : 1. Somente 1 : n. Se quiser fazer 1 : 1, você terá que, de alguma forma, informar que não pode aceitar mais de uma ocorrencia, no método populate. Sugestão: use uma anotação (como usei para identificar qual classe usar).
Hugo, a parte que atolou a coisa foi essa:
class Conexao extends Base
{
public $id;
public $fk_org_id;
public $fk_contip_id;
public $fk_usu_id;
public $datacriacao;
public $fk_consta_id;
public $statusdata;
public $contip; // Povoar com o tipo da conexão.
}
Eu acho que você quis dizer q a Conexão pertence a Conexao tipo.. no contexto de que estivéssemos listando conexoes por tipo/status. Acho que o q causo a confusão foi que há 2 contextos:
Relatório de Secretarias, orgaos e suas conexões:
Secretaria da Fazenda - Receita Federal - Conexão1 (ADSL) (Ativa)
Relatório de Tipos/Status de Conexões:
Conexões Ativas: Conexão1
Conexões ADSL: Conexão1
Veja que estamos usando o primeiro contexto, então acho que $fk_contip_id e $fk_consta_id são inativos nesse contexto.
Veja um fragmento de nossa $row:
[contip_id] => 2
[contip_tipo] => ADSL
[contip_tabela] => tbl_conexao_adsl
[consta_id] => 1
[consta_status] => Ativa
Basicamente era só atribuir esses dados aí no atributo $contip da Class Conexao.
Isso que eu não consegui fazer no post #7.
Abraço.
Tentou alterar para o que eu sugeri no #10?
>
Tentou alterar para o que eu sugeri no #10?
hmm cara..
só posso dizer uma coisa:
você atingiu um nivel tal de manipulação dos estados físicos da matéria,
que conseguiria até fazer cair neve no norte do saara.
xD
muito amazing!!!!
no caso, a sua nota é: Deeeeeeeeeeeeezzzzzzz!!
kkk
muito grato pela atenção e pela paciência brother!
cumprimentos!!!
sem crise mano :thumbsup:
@braços e fique com Deus!
Bom, eu faria um objeto base e minhas classes herdariam ele.
Assim ficaria mais fácil.
A única coisa seria reorganizar o array de entrada para que bata com a árvore hierárquica que você quer usar.
Exemplo de classes (PHP 5.3!):
example\Base
namespace example {
class Base {
/**
* Método para popular recursivamente usando um array como fonte.
*
* @param array $source
* @author Hugo Ferreira da Silva
example\Secretaria
namespace example {
include_once __DIR__ . DIRECTORY_SEPARATOR . 'Base.php';
class Secretaria extends Base {
example\Orgao
namespace example {
include_once __DIR__ . DIRECTORY_SEPARATOR . 'Base.php';
class Orgao extends Base {
example\Conexao
namespace example {
include_once __DIR__ . DIRECTORY_SEPARATOR . 'Base.php';
class Conexao extends Base {
Testando a bagaça (test.php, no mesmo diretorio dos outros arquivos):
// dados basicos da secretaria
$data = array(
'nome' => 'Secretaria 1',
'endereco' => 'Endereço Secretaria 1',
'telefone' => 'Telefone Secretaria 1',
// orgaos vinculados a esta secretaria
// - cada item é um orgão
// - aqui temos dois orgaos
// criamos e populamos uma secretaria
Saida do exemplo:
example\Secretaria Object
(
Espero que ajude!
@braços e fique com Deus!