how can i page the second table? Or is this shape incorrect?
Here is my render function.
public function render()
{
$data = DB::table('view_log_acesso_telas')
->join('contact_std_parceiros_usuarios','view_log_acesso_telas.id_usuario','=','contact_std_parceiros_usuarios.id_usuario')
->select(
'contact_std_parceiros_usuarios.id_usuario',
'contact_std_parceiros_usuarios.nome',
'view_log_acesso_telas.data_inicio'
)
->groupBy(
'contact_std_parceiros_usuarios.id_usuario',
'contact_std_parceiros_usuarios.nome',
'view_log_acesso_telas.data_inicio'
)
->having('nome', 'LIKE', '%'.$this->search.'%')
->orderBy('view_log_acesso_telas.data_inicio','desc')
->orderBy('contact_std_parceiros_usuarios.nome','desc')
->paginate($this->perPage);
return view('livewire.relatorios.acessos.acessos-component',[
'data' => $data,
]);
}
public function detail($id_usuario,$data_inicio)
{
$this->showDetails = true;
$this->details = Acessos::where('id_usuario',$id_usuario)->where('data_inicio',$data_inicio)->paginate(10);
}
Please tell me how can I solve this?
Related
I have this code that returns column names of the className declared in the 2nd line :
public function listColumns(EntityManagerInterface $em ) {
$class = $em->getClassMetadata(Assure::class);
$fields = [];
if (!empty($class->discriminatorColumn)) {
$fields[] = $class->discriminatorColumn['name'];
}
$fields = array_merge($class->getColumnNames(), $fields);
foreach ($fields as $index => $field) {
if ($class->isInheritedField($field)) {
unset($fields[$index]);
}
}
foreach ($class->getAssociationMappings() as $name => $relation) {
if (!$class->isInheritedAssociation($name)){
foreach ($relation['joinColumns'] as $joinColumn) {
$fields[] = $joinColumn['name'];
}
}
}
return $fields;
}
I am trying to make this function parametrable so I can give it every time which table/className I am trying to get its columns
This is a possible solution to do what I want (extracting table column names ) differently :
public function listColumns2(EntityManagerInterface $em ) {
$conn = $this->getEntityManager()->getConnection();
$sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =
N'Assure' ";
$stmt = $conn->prepare($sql);
$stmt->execute();
return $stmt->fetchAllAssociative();
}
I have an entity, call it Stones and Stones has a ManyToMany relationship with Attributes.
So I query the entity to get the Stones and then I hydrate this to convert it into an array.
$result = $this->stoneRepository->find($stone_id);
if ( ! $result )
{
return false;
}
$resultArray = $this->doctrineHydrator->extract($result);
This works fine for the Stone entity however I noticed that the join (Attributes) remain as objects.
array (size=12)
'id' => int 1
'name' => string 'Agate' (length=5)
'title' => string 'Title' (length=5)
'attribute' =>
array (size=5)
0 =>
object(Stone\Entity\StAttribute)[1935]
private 'id' => int 2
private 'name' => string 'Hay fevor' (length=9)
private 'state' => boolean true
private 'created' => null
private 'modified' => null
1 =>
object(Stone\Entity\StAttribute)[1936]
private 'id' => int 15
private 'name' => string 'Libra' (length=5)
private 'state' => boolean true
private 'created' => null
private 'modified' => null
2 =>
etc.
What is the process to hydrate the Attribute objects?
Hydration is populating an object (entity) using an array which is opposite of the extraction.
Since you want the resultset in array format, you should prevent unnecessary hydration and extraction process which already occurs in the ORM level under the hood.
Try to use Query Builder Api instead of built-in find() method of the entity repository. This is not a single-line but really straightforward and faster solution, it should work:
$qb = $this->stoneRepository->createQueryBuilder('S');
$query = $qb->addSelect('A')
->leftJoin('S.attribute', 'A')
->where('S.id = :sid')
->setParameter('sid', (int) $stone_id)
->getQuery();
$resultArray = $query->getOneOrNullResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
This way, you will also prevent running additional SQL queries against database to fetch associated entities. (StAttribute in your case)
I thought I would follow up on this to show how this can be resolved using a CustomStrategy.
By far the easiest and fastest method was suggested by foozy. What I like about the solution is that when I use hydration in ApiGility for instance I can build custom queries which will produce the desired result in a very few lines of code.
The other solution I was working on was to add a custom strategy:
<?php
namespace Api\V1\Rest\Stone;
use DoctrineModule\Stdlib\Hydrator\Strategy\AbstractCollectionStrategy;
use Zend\Stdlib\Hydrator\Strategy\StrategyInterface;
class CustomStrategy extends AbstractCollectionStrategy
{
public function __construct($hydrator)
{
$this->hydrator = $hydrator;
}
/**
* #param mixed $values
* #return array|mixed
*/
public function extract($values)
{
$returnArray = [];
foreach ($values AS $value)
{
$returnArray[] = $this->hydrator->extract($value);
}
return $returnArray;
}
/**
* #param mixed $values
* #return mixed
*/
public function hydrate($values)
{
$returnArray = [];
foreach ($values AS $value )
{
$returnArray[] = $this->hydrator->hydrate($value);
}
return $returnArray;
}
}
Then from the service side I add various strategies to the hydrator like so:
$result = $this->stoneRepository->find($stone_id);
$this->doctrineHydrator->addStrategy("product", new CustomStrategy( $this->doctrineHydrator ) );
$this->doctrineHydrator->addStrategy("attribute", new CustomStrategy( $this->doctrineHydrator ) );
$this->doctrineHydrator->addStrategy("image", new CustomStrategy( $this->doctrineHydrator ) );
$this->doctrineHydrator->addStrategy("related", new CustomStrategy( $this->doctrineHydrator ) );
$resultArray = $this->doctrineHydrator->extract($result);
After which I created a custom entity:
<?php
namespace Api\V1\Rest\Stone;
class StoneEntity
{
public $id;
public $name;
public $description;
public $code;
public $attribute;
public $product;
public $image;
public function getArrayCopy()
{
return array(
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'code' => $this->code,
'attribute' => $this->attribute,
'product' => $this->product,
'image' => $this->image
);
}
public function exchangeArray(array $array)
{
$this->id = $array['id'];
$this->name = $array['name'];
$this->description = $array['description'];
$this->code = $array['code'];
$this->attribute = $array['attribute'];
$this->product = $array['product'];
$this->image = $array['image'];
}
}
And the final part is to exchange the returned data with the custom entity:
$entity = new StoneEntity();
$entity->exchangeArray($resultArray);
And finally to return the result:
return $entity;
To be honest, the above is just too long winded and my final solution as per the suggestion by foozy was this:
public function fetchOne($stone_id)
{
$qb = $this->stoneRepository->createQueryBuilder('S');
$query = $qb->addSelect('A','P','I','C')
->leftJoin('S.attribute', 'A')
->innerJoin('A.category', 'C')
->innerJoin('S.product' , 'P')
->innerJoin('S.image' , 'I')
->where('S.id = :sid')
->setParameter('sid', (int) $stone_id)
->getQuery();
$resultArray = $query->getOneOrNullResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
if ( ! $resultArray )
{
return false;
}
return $resultArray;
}
class Article extends Page { // Model
static $db = array(
'Date' => 'Date',
'Author'=>'Text'
);
private static $has_one = array(
);
function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Content.Main', $date = new DateField('Date'),'Content');
DateField::create('MyDate')->setConfig('showcalendar', true);
$fields->addFieldToTab('Root.Content.Main', new TextField('Author'), 'Content');
return $fields;
}
}
The above code should show datepicker but it is not showing.. Plz help me with this..
Try this:
$fields->addFieldToTab('Root.Content.Main', DateField::create('MyDate')->setConfig('showcalendar', true),'Content');
DateField::create() is a Factory Method for DateField, so it will return a DateField object.
I'm going to use Prestashop 1.5.4 web-service to get all products with their attributes such as description, name and etc. My problem is whenever I call web-service it returns to me only the products Ids. How can I get attributes too?
Edited :
code :
class ShopApi
{
public $client;
public function __construct()
{
$this->getClient();
}
public function getClient()
{
try {
// creating web service access
$this->client = new PrestaShopWebservice('http://wikibazaar.ir/', 'A38L095W0RHRXE8PM9CM01CZW7KIU4PX', false);
} catch (PrestaShopWebserviceException $ex) {
// Shows a message related to the error
echo 'error: <br />' . $ex->getMessage();
}
}
}
class ProductApi extends ShopApi
{
public function findAll()
{
$products = array();
/// The key-value array
$opt['resource'] = 'products';
$opt['display'] = '[description]';
$opt['limit'] = 1;
$xml = $this->client->get($opt);
$resources = $xml->products->children();
foreach ($resources as $resource)
$products[] = $resource->attributes();
return $products;
}
}
EDIT :
I've found that the response from webservice is ok. but there is a problem during parsing xml with simplexml_load_string() function. any idea?
it's $product var_dump :
SimpleXMLElement#1 ( [products] => SimpleXMLElement#2 ( [product] => SimpleXMLElement#3 ( [description] => SimpleXMLElement#4 ( [language] => SimpleXMLElement#5 ( [#attributes] => array ( 'id' => '1' ) ) ) ) ) )
I think that $opt['display'] = 'full'; would do the job
You can also select only some specific attribute e.g.
$opt['display'] = '[id,name]';
Take a look at the official documentation, you might find it interesting
I've been bashing my head against the wall trying to figure out why I can't get my fixture to load properly. When I attempt to run my test, my layout is rendered. If I comment out the fixture, the test runs properly. I've gone over this 100 times and I can't seem to see what's wrong.
Heres my Videosview.test.php
App::import('Model','Videosview');
class VideosviewTest extends Videosview {
var $name = 'Videosview';
//var $useDbConfig = 'test_suite';
}
class VideosviewTestCase extends CakeTestCase {
var $fixtures = array( 'app.videosview' );
function testIncrementTimer() {
$this->autoLayout = $this->autoRender = false;
$this->Videosview =& ClassRegistry::init('Videosview');
//$video_view = $this->find('first');
$result = $this->Videosview->increment_timer($video_view['Videosview']['video_id'],$video_view['Videosview']['user_id'],1);
$this->assertTrue(true);
}
}
This is my videosview_fixture.php
class VideosviewFixture extends CakeTestFixture {
var $name = 'Videosview';
var $import = array('model' => 'Videosview', 'records' => true);
}
Lot of strange code there, it looks like you don't understand how test are used. The problem doesn't come from your fixture import.
$this->assertTrue(true) will always return true. There is no need to declare VideosviewTest.
As I don't know what your increment_timer method is supposed to do I cannot write a test for it, but let's suppose it returns the value passed + 1:
function increment_timer($id = null){
return $id++;
}
Your test case should be
App::import('Model', 'Videosview');
class VideosviewTestCase extends CakeTestCase {
var $fixtures = array('app.videosview');
function startTest() {
$this->Videosview =& ClassRegistry::init('Videosview');
}
function endTest() {
unset($this->Videosview);
ClassRegistry::flush();
}
function testIncrementTimer() {
$input = 1;
// let's test increment_timer function by asserting true that return value is $input + 1, green bar
$this->assertTrue( $this->Videosview->increment_timer($input) == ($input+1), 'Should return 2' );
// let's test increment_timer function by asserting false that return value is $input + 2, green bar
$this->assertFalse( $this->Videosview->increment_timer($input) == ($input+2), 'Should not return 3' );
//the following returns an error as return value is not equal to $input + 2, Red bar
$this->assertTrue( $this->Videosview->increment_timer($input) == ($input+2), 'Should return 2' );
}
}
This is what you should get, and have expected