Zend framework 2 model for database, separate model for each table? - database

I looked through the manual of Zend Framework 2 about creating model to managing operations on table. Is the class with method exchangeArray() is necessary? It's only copy data :/ Can i create one model to manage a few tables?
I created two classes:
namespace Application\Model;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Adapter\AdapterAwareInterface;
abstract class AbstractAdapterAware implements AdapterAwareInterface
{
protected $db;
public function setDbAdapter(Adapter $adapter)
{
$this->db = $adapter;
}
}
and:
namespace Application\Model;
class ExampleModel extends AbstractAdapterAware
{
public function fetchAllStudents()
{
$result = $this->db->query('select * from Student')->execute();
return $result;
}
}
I also add entries in Module.php:
'initializers' => [
'Application\Model\Initializer' => function($instance, \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator){
if ($instance instanceof AdapterAwareInterface)
{
$instance->setDbAdapter($serviceLocator->get('Zend\Db\Adapter\Adapter'));
}
}
],
'invokables' => [
'ExampleModel' => 'Application\Model\ExampleModel'
],
I execute methods from model by:
$this->getServiceLocator()->get('ExampleModel')->fetchAllStudents();

You should do 2 things with your code. First, implement AdapterAwareInterface properly. Second, create an initializer which injects the adapter into your model. Consider the code below:
...
'initializers' => [
function($instance, ServiceLocatorInterface $serviceLocator){
if ($instance instanceof AdapterAwareInterface) {
$instance->setDbAdapter($serviceLocator->get('Zend\Db\Adapter\Adapter'));
}
}
]
...
abstract class AbstractModel implements AdapterAwareInterface
{
protected $db;
public function setDbAdapter(Adapter $adapter)
{
$this->db = adapter;
}
}
...
'invokables' => [
'ExampleModel' => 'Application\Model\ExampleModel'
]
As you can see from above, after all, you don't need a factory for each your model. You can either register invokables or create an Abstract Factory to instantiate your models. See an example below:
...
'abstract_factories' => [
'Application\Model\AbstractFactory'
]
...
class AbstractFactory implements AbstractFactoryInterface
{
public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
return class_exists('Application\Model\'.$requestedName);
}
public function createServiceWithName(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
$class = 'Application\Model\'.$requestedName();
return new $class
}
}
Hope this helps

Related

How to insert into a table based on an Eloquent relationship an array of foreign keys

I have two models TeamMember and ProjectRequest.
A TeamMember can have one ProjectRequest, that is why I created the following Eloquent relationship on TeamMember:
class TeamMember extends Model {
//
protected $table = 'team_members';
protected $fillable = ['project_request_id'];
// Relations
public function projectTeam() {
return $this->hasOne('\App\Models\ProjectRequest', 'project_request_id');
}
}
In my Controller I want to query both tables, however it returns the failure message.
What is important to know is that $request->projectTeam is an array of emails, looking like this:
array:2 [
0 => "mv#something.com"
1 => "as#something.com"
]
Meaning that I need to bulk insert into team_members table the project_request_ id for each team member where the emails are in the array.
How can I do that in the right way? The following is my attempt:
public function createProjectTeam(Request $request){
try {
$title = $request->projectTitle;
$TeamMember = $request->projectTeam;
$projectRequest = ProjectRequest::create(['project_title' => $title]);
$projectRequestId = $projectRequest->id;
$projectTeam = $this->teamMembers->projectTeam()->create(['project_request_id'=> $projectRequestId])->where('email', $TeamMember);
//$projectTeam = TeamMember::createMany(['project_request_id' => $projectRequestId])->where($TeamMember);
//dd($projectTeam);
return $projectRequest.$projectTeam;
} catch(\Exception $e){
return ['success' => false, 'message' => 'project team creation failed'];
}
}
There are a few things you can do.
Eloquent offers a whereIn() method which allows you to query where a field equals one or more in a specified array.
Secondly, you can use the update() method to update all qualifying team members with the project_request_id:
public function createProjectTeam(Request $request)
{
try {
$projectRequest = ProjectRequest::create(['project_title' => $request->projectTitle]);
TeamMember::whereIn('email', $request->projectTeam)
->update([
'project_request_id' => $projectRequest->id
]);
return [
'success' => true,
'team_members' => $request->projectTeam
];
} catch(\Exception $e) {
return [
'success' => false,
'message' => 'project team creation failed'
];
}
}
I hope this helps.

Laravel UUID from SQL Server Database Errors

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�Q׊3�^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.

Codeigniter autocheck db depending on session value

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();
}
}

Displaying array values in laravel 5.2

I have the following hasMany() relationship in App\User.php ,
public function partner_preference_occupation()
{
return $this-hasMany('App\Models\User\PartnerPreferenceOccupation', 'user_id');
}
The following is my PartnerPreferenceOccupation Model,
<?php
namespace App\Models\User;
use App\Models\BaseModel,
App\Models\ValidationTrait;
class PartnerPreferenceOccupation extends BaseModel {
use ValidationTrait;
public function __construct() {
parent::__construct();
$this->__validationConstruct();
}
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'partner_preferences_occupation';
protected $fillable = array('user_id', 'occupation_id');
protected $dates = array();
public $uploadPath = array();
protected function setRules() {
$this->val_rules = array();
}
protected function setAttributes() {
$this->val_attributes = array();
}
public function occupation_name() {
return $this->belongsTo('App\Models\Master\OccupationModel', 'occupation_id');
}
}
I want to display the array of occupation name in my view. I tried the following code, but it fails.
{{$obj->partner_preference_occupation ? $obj-partner_preference_occupation->occupation_name->name : null}}
The error is as follows,
Undefined property:Illuminate\Database\Eloquent\Collection::$occupation_name
How can I display them.Thanks in advance.
There is a typo in $obj-partner_preference_occupation->occupation_name->name
Should be $obj->partner_preference_occupation->occupation_name->name
Make sure that occupation_name exists in the collection. You can check by doing the following in your View:
dump( $obj->partner_preference_occupation );
It might help you identify where the issue lies.
Also, to display a collection as an array, you can use the toArray() method, e.g.:
$obj->partner_preference_occupation->toArray()
Ok I got it,
As it is an array of values to be fetched, I used foreach to display them in my view as,
#if($occ=$obj->partner_preference_occupation->lists('occupation_name'))
#foreach($occ as $oc)
{{$oc->name}}
#endforeach
#endif
occupatoin_name is the name of my relationship that I used in my model. And that worked for me :)

Symfony3 return array from query to json

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.

Resources