I'm trying to figure out the essentials of Zend Adapter. The tutorials and explanations are confusing and needs more clarification. Can someone give me simple examples to fully understand how to work with SQL queries and how to get the desired SQL results?
especially, I'm interested in learning how to get
-- column names
-- table names
-- fetchAll entries
and etc.
Thank you,
Like a lot of other people you seem to be having difficulty with the quickstart, try the tutorial from Rob Allen it helped me get started.
You have multiple choices on how to connect to your table, the confusion with Zend_Db often begins here.
The easiest way when using one DB, in your application.ini file add these lines at a minmum:
resources.db.adapter = "pdo_Mysql"
resources.db.params.username = "user_name"
resources.db.params.password = "password"
resources.db.params.dbname = "db_name"
Alternatively you can connect to a database almost anywhere in your code using the Zend_Db_Adapter:
//using a normal constructor
$db = new Zend_Db_Adapter_Pdo_Mysql(array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
));
//using factory
$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
));
List of supported Databases
Using this in your application can be as simple as:
//fetchAll using Zend_Db_Adapter and plain SQL
$sql = 'SELECT * FROM bugs WHERE bug_id = ?';
$result = $db->fetchAll($sql, 2);
you can list the tables in a database:
$tables = $db->listTables();
or you can get a full table description (including column names), I included the comment block from the function in Zend_Db_Adapter_Abstract:
/**
* Returns the column descriptions for a table.
*
* The return value is an associative array keyed by the column name,
* as returned by the RDBMS.
*
* The value of each array element is an associative array
* with the following keys:
*
* SCHEMA_NAME => string; name of database or schema
* TABLE_NAME => string;
* COLUMN_NAME => string; column name
* COLUMN_POSITION => number; ordinal position of column in table
* DATA_TYPE => string; SQL datatype name of column
* DEFAULT => string; default expression of column, null if none
* NULLABLE => boolean; true if column can have nulls
* LENGTH => number; length of CHAR/VARCHAR
* SCALE => number; scale of NUMERIC/DECIMAL
* PRECISION => number; precision of NUMERIC/DECIMAL
* UNSIGNED => boolean; unsigned property of an integer type
* PRIMARY => boolean; true if column is part of the primary key
* PRIMARY_POSITION => integer; position of column in primary key
*
* #param string $tableName
* #param string $schemaName OPTIONAL
* #return array
*/
$describTable = $db->describeTable('myTable');
This info should get you started, however I find that a lot of the real power of Zend_Db resides in the Zend_Db_Table, Zend_Db_Table_Row and especially the Zend_Db_Select classes.
I urge you to take some time and figure them out.
As an example of what you might expect from Zend_Db_Table and Zend_Db_select (when not using more advanced mappers and domain objects, hopefully those will come later):
//When using DbTable models that extend Zend_Db_Table_Abstract the model already
//knows the name of the table and has full access to the Db adapter, allowing your code to
//be very brief and descriptive.
class Application_Model_DbTable_Weekend extends Zend_Db_Table_Abstract
{
//name of table, required if classname is not the same as the table name
protected $_name = 'weekend';
//primary key column of table, a good idea especially if primary key is not 'id'
protected $_primary = 'weekendid';
public function getWeekend($weekendId) {
//create select object
$select = $this->select();
$select->where('weekendid = ?', $weekendId);//placeholder syntax
$result = $this->fetchRow($select);
if (!$result) {
throw new Exception('Could not find weekend ID ' . $weekendId);
}
return $result;//returns a single row object
}
public function fetchAllWeekend() {
$select = $this->select();
$result = $this->fetchAll($select);
return $result; //returns array of row objects (rowset object)
}
}
Rob Allen's Zf tutorial will explain how DbTable models are setup and how they Work.
hope this helps...
Related
I have socialite login for facebook and google. I'm trying to store values in db. Some of them are stored and some no. I think I have tried everything, but can't find problem and solution.
I have function:
public function CreateUser($user, $provider)
{
$authUser = User::where('social_id', $user->id)->first();
if($authUser)
{
return $authUser;
}
$token = $this->generateRandomString();
return User::create([
'name' => $user->name,
'email' => $user->email,
'social' => $provider,
'social_id' => $user->id,
'username' => $this->user_slug($user->name),
'user_token' => $token,
'earnings' => 0,
'user_type' => 'vendor',
'verified' => 1,
]);
}
All Values except social and social_id are stored in database. I tried to store different values in different fields.
For example, if I store $provider value in 'name' field it works. if I try to store $provider value or any other value in 'social' field. DB dosn't store it. Same for 'social_id' field.
I tried saving same value in different fields - It works
I tried to save different values in fields 'social' and 'social_id' - It dosn't work.
I tried to rename these 2 fields - Still dosn't work
If I edit these fields from "phpmyadmin" then it works.
I tried to set fields with different options - It dosn't change anything
DB Photo
you should define which model attributes you want to make mass assignable. You may do this using the $fillable property on the model. For example, let's make the name attribute of our User model mass assignable:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['social', 'social_id'];
}
I saw in my debug menu that I have some duplicate select queries. In particular, this is the one that I got 4 times SELECT * FROM page_adminlang WHERE (language=bg) AND (page_id=1) in 4 different files. Is there a right way to prevent such situations and is this big hit on the site speed performance? Shall I retrieve the row in some variable like $page = PageAdmin::findOne(1) and than call it where I need and is this the right way? I red other articles but they were mainly for duplicate rows on insertion. Not familiar with MySQL performance tuning but want to go deeper in this area.Thank you in advance!
Option 1 - Configure MemCache Component
An Easier method is to enable db caching, then it won't matter, put a 5second duration at first.
In your component db connection settings set the following properties:
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=dbname',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
....
'enableQueryCache' => true,
'queryCacheDuration' => 5, // five seconds
....
]
]
See:
https://www.yiiframework.com/doc/guide/2.0/en/caching-data
https://www2.0/yii-db.yiiframework.com/doc/api/-connection
Option 2 - Custom query with cache
public function getResults()
{
// Cache expires every x seconds (60sec/min * 60min/hr * 6hrs)
$duration = 60*60*6;
$sql_query = "SELECT * FROM some_table";
return Yii::$app->db->createCommand($sql_query)->cache($duration)->queryAll();
}
I don't usually face that issue, but if I have to retrieve something from the database multiple times (and I know that won't change), I do something like that in my model
private $_myData = null;
public function getMyData() {
if ($this->_myData !== null) return $this->_myData;
$this->_myData = //query your data;
return $this->getMyData();
}
I need to import the data from a different database and transfer it to the new database. but the ID information of the members is required for the relationship. I have to carry them too.
Therefore, I have to fill in the ID column which is increased as AUTOINCREMENT.
My Migrate Controller
public function migrate(BackupUser $buser, User $user)
{
$backup_user = $buser->get();
foreach ($backup_user as $bulk) {
$user->create([
'id' => $bulk->uye_id,
'name' => $bulk->uye_nick,
'email' => $bulk->uye_mail,
'password' => $bulk->uye_sifre,
'created_at' => $bulk->uye_tarih
]);
}
}
when I do this, the AUTOINCREMENT increases normally and I can not get the ID information of the previous members.
What is the best way to do this?
By default, the id field for User is not fillable by mass assignment like you're doing. If you want to assign it, you must add 'id' to the array of fillable fields in the user class.
app/User.php
...
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'id', 'name', 'email', 'password',
];
...
I think you are trying to take database from joomla or wordpress to laravel.
If I need to do this . my approach would be to store first all base tables without id and then with stored id generated after insertion would be in related tables. So the steps would be
S1: store new `user` and get `id`
S2: relate with other table like `role` with `user_id`
Loop again till last row
I have a class Person with about 100 fields.
recently i added a new field:
/**
*
* #ORM\Entity
* #Vich\Uploadable
* #ORM\Entity(repositoryClass="My\VenderBundle\Repository\PersonRepository")
* #ORM\Table(name="my_vendor_person")
*/
class Person
{
....
/**
* My new property
*
* #var array $references
*
* #ORM\Column(name="references", type="array", nullable=true)
*/
protected $references;
The form type has been updated accordingly:
class PersonInvitationType extends AbstractType
{
private $context;
/**
* PersonNewType constructor.
* #param AuthorizationChecker $securityContext
*/
public function __construct(AuthorizationChecker $securityContext)
{
$this->context = $securityContext;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('references', CollectionType::class, array(
'entry_type' => Referencese::class,
'label' => 'References',
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'prototype_name' => 'references__name__',
'by_reference' => false,
'required' => false
))
But now I am getting the following error when submitting a form containing almost all fields of class Person:
An exception occurred while executing 'UPDATE my_vendor_person
SET references = ? WHERE id = ?' with params
["a:1:{s:7:\"myProperty0\";a:4:{s:4:\"name\";s:7:\"my name\";s:6:\"location\";
s:9:\"my location\";s:5:\"phone\";s:8:\"90898978978\";s:5:\"email\";
s:17:\"myemail#gmail.com\";}}", 765]:
Below that, the following is stated:
QLSTATE[42000]: Syntax error or access violation: 1118 Row size too large
(> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or
ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored
inline.
The form contains more fields of type array which contain more information then the above example. someone has an idea of what is happening here? Am Running Symfony 3.
UPDATE:
please find a pastbin of the dev.log here: http://pastebin.com/0qLm60x7
SECOND UPDATE:
please find the create table statement here: http://pastebin.com/PFy5jAbx
I'm trying to get a subset of results as a virtualField for use in my view. I may even be way off on how I'm approaching this, but here's what I've done so far:
I started with this question here: CakePHP virtualField find all not null which lead to this little beauty.
Now I have an issue where the find statement passing (Array) into the MySQL.
My code looks like:
class Transaction extends AppModel {
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->virtualFields['Accounts'] = $this->find("all", array("conditions" => array("account !=" => null)));
}
And I'm seeing:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Array' in 'field list'
SQL Query: SELECT `Transaction`.`id`, `Transaction`.`name`,
`Transaction`.`person_id`, `Transaction`.`account`, (Array)
AS `Transaction__Accounts` FROM `my_database`.`transactions`
AS `Transaction` WHERE `Transaction`.`person_id` = (2)
I've also tried $this->Transaction->find and "Transaction.account !=", to no avail. I've found some other issues with the (Array) but none that help my situation. Any pointers in the right direction would be great.
Problem: your query results are an array, and you're telling SQL to assign a field name to each query result containing that array - virtual fields are only made to contain single level variables like strings.
Solution: use a join structure onto itself with those conditions which will return a nested result set along with each of your results. Use CakePHP's model relationships to do this:
<?php
class Transaction extends AppModel {
var $hasMany = array(
'Accounts' => array(
'className' => 'Transaction',
'foreignKey' => false,
'conditions' => array('Accounts.account IS NOT NULL')
)
);
}
?>
Example output:
Array(
'Transaction' => array( // transaction data),
'Accounts' => array( // associated transaction data with account set to null
)
Now, as you can probably gather from that result, if you return 1000 rows from Transaction, you'll get all results from Accounts nested into each Transaction result. This is far from ideal. From here, you can either make the join conditions more specific to target relevant Accounts records, or this is not the right approach for you.
Other approaches could be:
Accounts model, uses Transaction database table, implicit find conditions are that account is null
Manual query to retrieve these results in the afterFind() method of your Transaction model, which will retrieve these results once, and you'll then return array_merge($accounts, $transactions)