I have a entity named "View" and this entity has a attribute named "datetime" (the name of entity and field are not relevant).
I would like to set a default value to it inside CakePHP instead of defining it on database.
On my entity class I defined:
namespace App\Model\Entity;
use Cake\ORM\Entity;
use Cake\I18n\Time;
class View extends Entity
{
protected $_accessible = [
'*' => true,
'id' => false,
];
protected function _getDatetime($datetime)
{
return Time::now();
}
}
And when I try to save it in a method of Model Table class (ViewTable):
public function registerView(User $user){
$view = $this->newEntity();
$view->user = $user;
$this->save($view);
}
Nothing happens, my "datetime" field is saved as '0000-00-00 00:00:00'.
My question is: How can I set a default value for a entity so when I call $this->newEntity() the field comes with this default value?
I would do it in ViewsTable::beforeSave
beforeSave($event, $entity, $options)
{
if(!$entity->isNew() && !$entity->datetime)
{
$entity->datetime = Time::now();
}
return true;
}
Related
I don't really know what words or terms I would search. I have also read the documentation in laravel 5.7, https://laravel.com/docs/5.7/eloquent-relationships#many-to-many-polymorphic-relations.
But still I couldn't find the thing that I want.
The result that I am expecting is this in MySQL:
SELECT id as product_id, (SELECT name FROM products WHERE id = transactions.product_id), created_at FROM transactions WHERE user_id = 1
This is the result of the mysql query:
I already have a model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Transactions extends Model
{
protected $table = 'transactions';
protected $fillable = [
'user_id', 'product_id'
];
public function product()
{
return $this->hasOne('App\Products')->select('name');
}
}
?>
Then in my controller:
public function transactions()
{
$transactions = new Transactions::where('user_id',Auth::id())->product;
return view('transactions', ['transactions' => $transactions]);
}
You should use belongsTo() relation. Transaction belongs to one product, product has many transactions.
Also, you can (or better should) rename model to a singlular. Then you don't need to use protected $table.
It is not necessarily to select only name.
Transaction model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Transaction extends Model
{
protected $fillable = ['user_id', 'product_id'];
public function product()
{
return $this->belongsTo('App\Product');
}
}
Controller:
public function transactions()
{
$transactions = Transaction::with('product')
->where('user_id', Auth::id())
->get();
return view('transactions', ['transactions' => $transactions]);
}
View:
#foreach($transactions as $transaction)
echo $transaction->product_id; //attribute product_id of transaction
echo $transaction->product->id; //attribute id of product
echo $transaction->product->name; //attribute name of product
#endforeach
I am having issues with a Laravel application using an existing database where MS SQL UUIDs are used. My application has a customer:
class Customer extends Model
{
protected $table = 'ERP.Customer';
public $timestamps = false;
protected $primaryKey = 'CustID';
protected $keyType = 'string';
protected $fillable = [
'CustID',
'SysRowID',
'CustNum',
'LegalName',
'ValidPayer',
'TerritoryID',
'Address1',
'Address2',
'Address3',
'City',
'State',
'Zip',
'Country',
'SalesRepCode',
'CurrencyCode',
'TermsCode',
'CreditHold',
'FaxNum',
'PhoneNum',
'CustomerType'
];
public function SalesTer()
{
return $this->belongsTo(SalesTer::class,'TerritoryID', 'TerritoryID');
}
public function Shipments()
{
return $this->hasMany(Shipment::class, 'CustNum', 'CustNum');
}
public function Equipments()
{
return $this->hasMany(Equipment::class,'CustNum', 'CustNum');
}
public function Customer_UD()
{
return $this->hasOne(Customer_UD::class,'ForeignSysRowID', 'SysRowID');
}
}
Which (in the native ERP application) has a UD table which end users can used to customise the Customer entity:
class Customer_UD extends Model
{
protected $table = 'ERP.Customer_UD';
protected $primaryKey = 'ForeignSysRowID';
public $timestamps = false;
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = [
'ForeignSysRowID',
'MakesCans_c',
'MakesEnds_c',
'Industry_c'
];
public function Customer()
{
return $this->hasOne(Customer::class,'SysRowID', 'ForeignSysRowID');
}
}
CustomerController:
public function show($CustID)
{
if(Customer::find($CustID))
{
$Customer = Customer::find($CustID);
$Customer_UD = $Customer->Customer_UD()
->get();
$Shipments = $Customer->Shipments()
->where('Voided', '0')
->get();
$Equipments = $Customer->Equipments()
->with('Part') // load the Part too in a single query
->where('SNStatus', 'SHIPPED')
->get();
return view('Customer.show', ['NoCust' => '0'],
compact('Equipments', 'Customer','Shipments', 'Parts', 'Customer_UD'));
}
else
{
return view('Customer.show', ['NoCust' => '1']);
}
}
The Customer has (for whatever reason) a CustID (which people use to refer to the customer) a CustNum (which is not used outside of the database and a SysRowID. The SysRowID is used to link the Customer table with the Customer_UD table.
An example row from Customer_UD is:
My issue is that when trying to return the UD fields along with the Customer fields I get an error:
SQLSTATE[HY000]: General error: 20018 Incorrect syntax near ''.
[20018] (severity 15) [select * from [ERP].[Customer_UD] where [ERP].
[Customer_UD].[ForeignSysRowID] = '���_�X�O�Q3�^w' and [ERP].
[Customer_UD].[ForeignSysRowID] is not null]
I thought it was odd, so I commended out the Customer_UD lines in the CustomerController and simply tried to display the Customer UUID field in the show blade:
SysRowID: {{$Customer->SysRowID}}
I get nothing, no errors but no data. I created a controller and index blade for the Customer_UD model and can display all of the Customer_UD database fields apart from the UUID field.
I don't actually want to display the UUID fields - but do need to use them to build the relationships. Can anyone help point me in the right direction?
I found that adding:
'options' => [
PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER => true,
],
To the database configuration in config\database.php resolved the issue.
I'm trying to force my app to check every time it loads a model or controller depending on which is my session value.
This is actually running, but just when I get throw this model.
class News_model extends CI_Model {
public function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}
But I do not war to include that __construct code to all my models or controllers.
I've tried to add on my autoload.php
$autoload['model'] = array('General');
Where my General code is something like this.
class General extends CI_Model {
function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
}
How can I do it?
You can do it by creating a base model which will be extended by your models that require the database check.
I have simplified the checking and loading code. A simple ternary determines the string to use and stores it in the variable $dbname. That variable is used to load the database, i.e. $this->load->database($dbname);.
I don't believe you need the second argument to load::database() which means you don't need to set $this->db explicitly. If I'm wrong, use
$this->db = $this->load->database($dbname, TRUE);
Below is the "base" model. The prefix of the file name is determined in config.php with the setting $config['subclass_prefix'] = 'MY_'; Adjust your base model's file and class name to match the 'subclass_prefix' you use.
/application/core/MY_Model.php
<?php
class MY_Model extends CI_Model
{
public function __construct()
{
parent::__construct();
$dbname = $this->session->dbname == 'db1' ? 'db1' : 'db2';
$this->load->database($dbname);
}
}
Use the above to create other models like so...
class News_model extends MY_Model
{
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}
I am using Symfony3.1 with FOS UsersBundle and I want some added fields to be loaded as specific Entity.
In RegistrationType I have
->add('country', ChoiceType::class, array(
'label' => 'label.country',
'required' => false,
'placeholder' => 'label.select_country',
'choices' => array(
'France' => '7v8tqr',
),
))
In my Entity User I have
/**
* #ORM\OneToOne(targetEntity="Country")
* #ORM\JoinColumn(name="country", referencedColumnName="short")
*/
protected $country;
I can't use the EntityType as it loads every available entity and I use the same kind of field for provinces and cities which are quite huge (I manage their content with javascript).
When I load a registered user, the country field is served as a Country Entity but when I register a new user or modify an existing one, I only have the string "short" which causes an error Expected value of type "AppBundle\Entity\Country" for association field "AppBundle\Entity\User#$country", got "string" instead..
Is there a solution ?
Thanks to #mcriecken who led me in the right direction, I have implemented the following solution, using an EventListener
in services.yml
app_user.registration:
class: AppBundle\EventListener\UserRegistrationListener
arguments: ['#doctrine.orm.entity_manager']
tags:
- { name: kernel.event_subscriber }
and the EventListener UserRegistrationListener.php
<?php
namespace AppBundle\EventListener;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Doctrine\ORM\EntityManager;
class UserRegistrationListener implements EventSubscriberInterface
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* {#inheritDoc}
*/
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
);
}
public function onRegistrationSuccess(FormEvent $event)
{
$form = $event->getForm()->getData();
//Gets the locations
$form->setCountry($this->getCountry($form->getCountry()));
$form->setProvince($this->getProvince($form->getProvince()));
$form->setCity($this->getCity($form->getCity()));
}
//Loads the country as an entity
public function getCountry($short)
{
if ($short == null) return null;
$repository = $this->em->getRepository('AppBundle:Country');
return $repository->findOneByShort($short);
}
//Loads the province as an entity
public function getProvince($short)
{
if ($short == null) return null;
$repository = $this->em->getRepository('AppBundle:Province');
return $repository->findOneByShort($short);
}
//Loads the city as an entity
public function getCity($short)
{
if ($short == null) return null;
$repository = $this->em->getRepository('AppBundle:City');
return $repository->findOneByShort($short);
}
}
Then at the end my FOS User object contains COuntry, Province and City as Objects and it can be saved to DB :-)
I have problem, i can't return my posts array to json becouse symfony returns array with entity object?
Its my code:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$posts = $em->getRepository('AppBundle:Post')->findAll();
return $this->json($posts);
}
I use $this->json is return json data, feature added on sf3.
But this is my result:
[
{},
{},
{}
]
i want to load my posts.
ps. i know, i can use Query builder, and method toArray or something, but is any method to use and DRY? Thx
Because entity can have multiple boundaries, proxy objects and related entities, I personally prefer to explicitly specify what is about to be serialized, like this:
use JsonSerializable;
/**
* #Entity
*/
class SomeEntity implements JsonSerializable
{
/** #Column(length=50) */
private $title;
/** #Column(length=50) */
private $text;
public function jsonSerialize()
{
return array(
'title' => $this->title,
'text' => $this->text,
);
}
}
And then it's as simple as json_encode($someEntityInstance);.
You can use JMSSerializerBundle as well to accomplish your task DRY.
Also, there is an option to write your own serializer to normalize the data.
UPDATE:
If you want multiple representations of a JSON, it can be achieved like this:
use JsonSerializable;
/**
* #Entity
*/
class SomeEntity implements JsonSerializable
{
// ...
protected $isList;
public function toList()
{
$this->isList = TRUE;
return $this;
}
private function jsonSerializeToList()
{
return [ // array representing list... ]
}
public function jsonSerialize()
{
if( $this->isList ) {
$normalized = $this->jsonSerializeToList();
} else {
$normalized = array(
'title' => $this->title,
'text' => $this->text,
);
}
return $normalized;
}
}
And called as json_encode($someEntityInstance->toList());. Any way, this is a bit dirty, so I suggest to be consistent with an idea of the interface.
A best solution is to enable the serializer component in Symfony:
#app/config/config.yml
framework:
serializer: ~
Note: the serializer component is disabled by default, you have to uncomment the config line in app/config/config.yml file.