torch::deploy¶
torch::deploy
is a system that allows you to run multiple embedded Python
interpreters in a C++ process without a shared global interpreter lock. For more
information on how torch::deploy
works internally, please see the related
arXiv paper.
Warning
This is a prototype feature. Only Linux x86 is supported, and the API may change without warning.
Getting Started¶
Installing torch::deploy
¶
torch::deploy
is not yet built by default in our binary releases, so to get
a copy of libtorch with torch::deploy
enabled, follow the instructions for
building PyTorch from source.
When running setup.py
, you will need to specify USE_DEPLOY=1
, like:
export CMAKE_PREFIX_PATH=${CONDA_PREFIX:-"$(dirname $(which conda))/../"}
export USE_DEPLOY=1
python setup.py bdist_wheel
python -mpip install dist/*.whl
Creating a model package in Python¶
torch::deploy
can load and run Python models that are packaged with
torch.package
. You can learn more about torch.package
in the
torch.package
documentation.
For now, let’s create a simple model that we can load and run in torch::deploy
.
from torch.package import PackageExporter
import torchvision
# Instantiate some model
model = torchvision.models.resnet.resnet18()
# Package and export it.
with PackageExporter("my_package.pt") as e:
e.intern("torchvision.**")
e.extern("sys")
e.save_pickle("model", "model.pkl", model)
Now, there should be a file named my_package.pt
in your working directory.
Note
Currently, torch::deploy
supports only the Python standard library and
torch
as extern
modules in torch.package
. In the future we plan
to transparently support any Conda environment you point us to.
Loading and running the model in C++¶
Let’s create a minimal C++ program to that loads the model.
#include <torch/deploy.h>
#include <torch/script.h>
#include <iostream>
#include <memory>
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "usage: example-app <path-to-exported-script-module>\n";
return -1;
}
// Start an interpreter manager governing 4 embedded interpreters.
torch::deploy::InterpreterManager manager(4);
try {
// Load the model from the torch.package.
torch::deploy::Package package = manager.loadPackage(argv[1]);
torch::deploy::ReplicatedObj model = package.loadPickle("model", "model.pkl");
} catch (const c10::Error& e) {
std::cerr << "error loading the model\n";
return -1;
}
std::cout << "ok\n";
}
This small program introduces many of the core concepts of torch::deploy
.
An InterpreterManager
abstracts over a collection of independent Python
interpreters, allowing you to load balance across them when running your code.
Using the InterpreterManager::loadPackage
method, you can load a
torch.package
from disk and make it available to all interpreters.
Package::loadPickle
allows you to retrieve specific Python objects
from the package, like the ResNet model we saved earlier.
Finally, the model itself is a ReplicatedObj
. This is an abstract handle to
an object that is replicated across multiple interpreters. When you interact
with a ReplicatedObj
(for example, by calling forward
), it will select
an free interpreter to execute that interaction.
Building and running the application¶
Assuming the above C++ program was stored in a file called, example-app.cpp, a minimal CMakeLists.txt file would look like:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(deploy_tutorial)
find_package(Torch REQUIRED)
add_executable(example-app example-app.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
The last step is configuring and building the project. Assuming that our code directory is laid out like this:
example-app/
CMakeLists.txt
example-app.cpp
We can now run the following commands to build the application from within the
example-app/
folder:
mkdir build
cd build
# Point CMake at the built version of PyTorch we just installed.
SITE_PACKAGES="$(python -c 'from distutils.sysconfig import get_python_lib; print(get_python_lib())')"
cmake -DCMAKE_PREFIX_PATH="$SITE_PACKAGES/torch" ..
cmake --build . --config Release
Now we can run our app:
./example-app /path/to/my_package.pt
Executing forward
in C++¶
One you have your model loaded in C++, it is easy to execute it:
// Create a vector of inputs.
std::vector<torch::jit::IValue> inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));
// Execute the model and turn its output into a tensor.
at::Tensor output = model(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
Notably, the model’s forward function is executing in Python, in an embedded
CPython interpreter. Note that the model is a ReplicatedObj
, which means
that you can call model()
from multiple threads and the forward method will
be executed on multiple independent interpreters, with no global interpreter
lock.


Uni Lingo
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type.
Download on the
Download on the
Download on the
Download on the


Different kind of memories can be accessed by threads during their execution, and can be classified regarding their degree of privacy and their speed (See table [tab:memoryHierarchyScope]). All threads have free access to global memory or also called device memory . Threads within the same block have access to so called shared memory that can be used for cooperation between thread of the same block and, at the end, each thread has his own local and private registers. There are other two memory spaces that can be addressed by all threads: constant and texture memories each specialized for different usage, but the shared characteristic is that they are persistent across kernels launch 26.


A spinner is a compound component with three
subcomponents: two small buttons and an
editor.
The editor can be any JComponent
,
but by default it is implemented
as a panel that contains a
formatted text field.
The spinner's possible and current values
are managed by its model.
Here is a picture of an application named SpinnerDemo
that has three spinners used to specify dates:
SpinnerDemo.java
.
The Month spinner displays the name
of the first month in the user's locale.
The possible values for this spinner
are specified using
an array of strings.
The Year spinner displays one value of a range of integers,
initialized to the current year.
The Another Date spinner displays one value
in a range of Date
objects
(initially the current date)
in a custom format
that shows just a month and year.
To create a spinner, first create its model and then pass the model into the JSpinner constructor. For example:
String[] monthStrings = getMonthStrings(); //get month names SpinnerListModel monthModel = new SpinnerListModel(monthStrings); JSpinner spinner = new JSpinner(monthModel);
SpinnerListModel
is a model whose values are
defined by an array of objects or a List
object.
The Month spinner in the SpinnerDemo
example
uses this model,
initialized with an array derived from the value
returned by the getMonths
method of the java.text.DateFormatSymbols
class.
See
SpinnerDemo.java
for details.
SpinnerNumberModel
supports sequences of numbers
which can be expressed as double
objects,
int
objects,
or Number
objects.
You can specify the minimum and maximum allowable values,
as well as the step size —
the amount of each increment or decrement.
The Year spinner uses this model,
created with the following code:
SpinnerModel model = new SpinnerNumberModel(currentYear, //initial value currentYear - 100, //min currentYear + 100, //max 1); //step
SpinnerDateModel
supports sequences of Date
objects.
You can specify the minimum and maximum dates,
as well as the field
(such as Calendar.YEAR
)
to increment or decrement.
Note, however, that some types of look and feel
ignore the specified field,
and instead change the field
that appears selected.
The Another Date spinner uses this model, created with the following code:
Date initDate = calendar.getTime(); calendar.add(Calendar.YEAR, -100); Date earliestDate = calendar.getTime(); calendar.add(Calendar.YEAR, 200); Date latestDate = calendar.getTime(); model = new SpinnerDateModel(initDate, earliestDate, latestDate, Calendar.YEAR);
When you set the spinner's model,
the spinner's editor is automatically set.
The Swing API provides an editor class
corresponding to each of the three model classes listed above.
These classes —
JSpinner.ListEditor,
JSpinner.NumberEditor, and
JSpinner.DateEditor —
are all subclasses of the
JSpinner.DefaultEditor class that feature editable formatted text fields.
If you use a model that does not have an editor associated with it,
the editor is by default
a JSpinner.DefaultEditor
instance
with a non-editable formatted text field.
To change the formatting used in a standard spinner editor, you can create and set the editor yourself.
The JSpinner.NumberEditor
and JSpinner.DateEditor
classes
have constructors that allow you to
create an editor that formats its data in a particular way.
For example, the following code
sets up the Another Date spinner
so that instead of using the default date format,
which is long and includes the time,
it shows just a month and year
in a compact way.
spinner.setEditor(new JSpinner.DateEditor(spinner, "MM/yyyy"));
ComboBoxDemo2
example.
Click the Launch button
to run ComboBoxDemo2 using
Java™ Web Start
(download JDK 6).
Alternatively, to compile and run the example yourself,
consult the example index.
To change the formatting
when using a default editor,
you can obtain the editor's formatted text field
and invoke methods on it.
You can call those methods using the
getTextField
method
defined in the JSpinner.DefaultEditor
class.
Note that the Swing-provided editors are not
formatted text fields.
Instead, they are the JPanel
instances
that contain
a formatted text field.
Here is an example of getting and invoking methods on
the editor's formatted text field:
//Tweak the spinner's formatted text field. ftf = getTextField(spinner); if (ftf != null ) { ftf.setColumns(8); //specify more width than we need ftf.setHorizontalAlignment(JTextField.RIGHT); } ... public JFormattedTextField getTextField(JSpinner spinner) { JComponent editor = spinner.getEditor(); if (editor instanceof JSpinner.DefaultEditor) { return ((JSpinner.DefaultEditor)editor).getTextField(); } else { System.err.println("Unexpected editor type: " + spinner.getEditor().getClass() + " isn't a descendant of DefaultEditor"); return null; } }
The easiest route to creating a custom spinner model
is to create a subclass
of an existing AbstractSpinnerModel
subclass
that already does most of what you need.
An alternative is to implement your own class
by extending
AbstractSpinnerModel
class,
which implements the event notifications
required for all spinner models.
The following subclass of SpinnerListModel
implements a spinner model
that cycles through an array of objects.
It also lets you specify a second spinner model
that will be updated whenever the cycle begins again.
For example, if the array of objects is a list of months,
the linked model could be for a spinner that displays the year.
When the month flips over from December to January the year is incremented.
Similarly, when the month flips back from January to December
the year is decremented.
public class CyclingSpinnerListModel extends SpinnerListModel { Object firstValue, lastValue; SpinnerModel linkedModel = null; public CyclingSpinnerListModel(Object[] values) { super(values); firstValue = values[0]; lastValue = values[values.length - 1]; } public void setLinkedModel(SpinnerModel linkedModel) { this.linkedModel = linkedModel; } public Object getNextValue() { Object value = super.getNextValue(); if (value == null) { value = firstValue; if (linkedModel != null) { linkedModel.setValue(linkedModel.getNextValue()); } } return value; } public Object getPreviousValue() { Object value = super.getPreviousValue(); if (value == null) { value = lastValue; if (linkedModel != null) { linkedModel.setValue(linkedModel.getPreviousValue()); } } return value; } }
The CyclingSpinnerListModel
model
is used for the Month spinner in the SpinnerDemo2
example,
an example that is almost identical to the SpinnerDemo
.
Click the Launch button
to run SpinnerDemo2 using
Java™ Web Start
(download JDK 6).
Alternatively, to compile and run the example yourself,
consult the example index.
As we mentioned before, if you implement a spinner model
that does not descend from
SpinnerListModel
,
SpinnerNumberModel
, or
SpinnerDateModel
,
then the spinner's default editor is
a non-editable instance of JSpinner.DefaultEditor
.
As you have already seen,
you can set a spinner's editor
by invoking the setEditor
method on the spinner
after the spinner's model property has been set.
An alternative to using setEditor
is to
create a subclass of the JSpinner
class
and override its createEditor
method
so that it returns a particular kind of editor
whenever the spinner model is of a certain type.
In theory at least, you can use any JComponent
instance
as an editor.
Possibilities include using a
subclass of a standard component
such as JLabel
,
or a component you have implemented from scratch,
or a subclass of
JSpinner.DefaultEditor
.
The only requirements
are that the editor must
be updated to reflect changes in the spinner's value,
and it must have a reasonable preferred size.
The editor should generally also
set its tool tip text
to whatever tool tip text has been specified
for the spinner.
An example of implementing an editor is provided in the next section.
SpinnerDemo3
,
which is based on SpinnerDemo
and uses a change listener
to change the color of some text
to match the value of the Another Date spinner.
Click the Launch button
to run SpinnerDemo3 using
Java™ Web Start
(download JDK 6).
Alternatively, to compile and run the example yourself,
consult the example index.
public class SpinnerDemo3 extends JPanel implements ChangeListener { protected Calendar calendar; protected JSpinner dateSpinner; ... public SpinnerDemo3() { ... SpinnerDateModel dateModel = ...; ... setSeasonalColor(dateModel.getDate()); //initialize color //Listen for changes on the date spinner. dateSpinner.addChangeListener(this); ... } public void stateChanged(ChangeEvent e) { SpinnerModel dateModel = dateSpinner.getModel(); if (dateModel instanceof SpinnerDateModel) { setSeasonalColor(((SpinnerDateModel)dateModel).getDate()); } } protected void setSeasonalColor(Date date) { calendar.setTime(date); int month = calendar.get(Calendar.MONTH); JFormattedTextField ftf = getTextField(dateSpinner); if (ftf == null) return; //Set the color to match northern hemisphere seasonal conventions. switch (month) { case 2: //March case 3: //April case 4: //May ftf.setForeground(SPRING_COLOR); break; ... default: //December, January, February ftf.setForeground(WINTER_COLOR); } } ... }
...//Where the components are created: JSpinner spinner = new JSpinner(new GrayModel(170)); spinner.setEditor(new GrayEditor(spinner)); class GrayModel extends SpinnerNumberModel { ... } class GrayEditor extends JLabel implements ChangeListener { public GrayEditor(JSpinner spinner) { setOpaque(true); ... //Get info from the model. GrayModel myModel = (GrayModel)(spinner.getModel()); setBackground(myModel.getColor()); spinner.addChangeListener(this); ... updateToolTipText(spinner); } protected void updateToolTipText(JSpinner spinner) { String toolTipText = spinner.getToolTipText(); if (toolTipText != null) { //JSpinner has tool tip text. Use it. if (!toolTipText.equals(getToolTipText())) { setToolTipText(toolTipText); } } else { //Define our own tool tip text. GrayModel myModel = (GrayModel)(spinner.getModel()); int rgb = myModel.getIntValue(); setToolTipText("(" + rgb + "," + rgb + "," + rgb + ")"); } } public void stateChanged(ChangeEvent e) { JSpinner mySpinner = (JSpinner)(e.getSource()); GrayModel myModel = (GrayModel)(mySpinner.getModel()); setBackground(myModel.getColor()); updateToolTipText(mySpinner); } }
The following tables list some of the commonly used API for using spinners. If you need to deal directly with the editor's formatted text field, you should also see The FormattedTextField API. Other methods you might use are listed in the API tables in The JComponent Class.
| Class or Interface | Purpose |
|---|---|
| JSpinner | A single-line input field that allows the user to select a number or object value from an ordered sequence. |
| SpinnerModel | The interface implemented by all spinner models. |
| AbstractSpinnerModel | The usual superclass for spinner model implementations. |
| SpinnerListModel | A subclass of AbstractSpinnerModel whose values are
defined by an array or a List .
|
| SpinnerDateModel | A subclass of AbstractSpinnerModel that supports
sequences of Date instances.
|
| SpinnerNumberModel | A subclass of AbstractSpinnerModel that supports
sequences of numbers.
|
| JSpinner.DefaultEditor | Implements an uneditable component that displays the spinner's value. Subclasses of this class are generally more specialized (and editable). |
| JSpinner.ListEditor | A subclass of JSpinner.DefaultEditor whose values are
defined by an array or a List .
|
| JSpinner.DateEditor | A subclass of JSpinner.DefaultEditor that supports
sequences of Date instances.
|
| JSpinner.NumberEditor | A subclass of JSpinner.DefaultEditor that supports
sequences of numbers.
|
| Constructor or Method | Purpose |
|---|---|
|
JSpinner() JSpinner(SpinnerModel) |
Creates a new JSpinner . The no-argument constructor
creates a spinner with an integer SpinnerNumberModel
with an initial value of 0 and no minimum or maximum limits. The
optional parameter on the second constructor allows you to specify
your own SpinnerModel .
|
|
void setValue(java.lang.Object) Object getValue() |
Sets or gets the currently displayed element of the sequence. |
|
Object getNextValue() Object getPreviousValue() |
Gets the object in the sequence that comes before or after the
object returned by the getValue method.
|
|
SpinnerModel getModel() void setModel(SpinnerModel) |
Gets or sets the spinner's model. |
|
JComponent getEditor() void setEditor(JComponent) |
Gets or sets the spinner's editor,
which is often an object of type JSpinner.DefaultEditor .
|
| protected JComponent createEditor(SpinnerModel) | Called by the JSpinner constructors
to create the spinner's editor.
Override this method to associate an editor
with a particular type of model.
|
| Constructor or Method | Purpose |
|---|---|
| JSpinner.NumberEditor(JSpinner, String) | Creates a JSpinner.NumberEditor instance
that displays and allows editing of
the number value of the specified spinner.
The string argument
specifies the format to use to display the number.
See the API documentation for
DecimalFormat for information about decimal format strings.
|
| JSpinner.DateEditor(JSpinner, String) | Creates a JSpinner.DateEditor instance
that displays and allows editing of
the Date value of the specified spinner.
The string argument
specifies the format to use to display the date.
See the API documentation for
SimpleDateFormat for information about date format strings.
|
|
JFormattedTextField getTextField() (defined in JSpinner.DefaultEditor )
|
Gets the formatted text field that provides the main GUI for this editor. |
| Method | Purpose |
|---|---|
|
void setList(List) List getList() |
Sets or gets the List that defines the sequence for this model.
|
| Method | Purpose |
|---|---|
|
void setValue(Object) Date getDate() Object getValue() |
Sets or gets the current Date for this sequence.
|
|
void setStart(Comparable) Comparable getStart() |
Sets or gets the first Date in this sequence.
Use null to specify that
the spinner has no lower limit.
|
|
void setEnd(Comparable) Comparable getEnd() |
Sets or gets the last Date in this sequence.
Use null to specify that
the spinner has no upper limit.
|
|
void setCalendarField(int) int getCalendarField() |
Sets or gets the size of the date value increment used by
the getNextValue and getPreviousValue
methods.
This property is not used when the user explicitly
increases or decreases the value;
instead, the selected part of the formatted text field
is incremented or decremented.
The specified parameter must be one of the following
constants, defined in Calendar :
ERA , YEAR ,
MONTH , WEEK_OF_YEAR , WEEK_OF_MONTH ,
DAY_OF_MONTH , DAY_OF_YEAR , DAY_OF_WEEK ,
DAY_OF_WEEK_IN_MONTH , AM_PM , HOUR_OF_DAY ,
MINUTE , SECOND , MILLISECOND .
|
| Method | Purpose |
|---|---|
|
void setValue(Object) Number getNumber() |
Sets or gets the current value for this sequence. |
|
void setMaximum(Comparable) Comparable getMaximum() |
Sets or gets the upper bound for numbers in this sequence. If the
maximum is null , there is no upper bound.
|
|
void setMinimum(Comparable) Comparable getMinimum() |
Sets or gets the lower bound for numbers in this sequence. If the
minimum is null , there is no lower bound.
|
|
void setStepSize(Number) Number getStepSize() |
Sets or gets the increment used by getNextValue and
getPreviousValue methods.
|
| Example | Where Described | Notes |
|---|---|---|
SpinnerDemo
|
This section | Uses all three standard spinner model classes. Contains the code to use a custom spinner model, but the code is turned off by default. |
SpinnerDemo2
|
This section | A SpinnerDemo subclass
that uses the custom spinner model
for its Months spinner.
|
SpinnerDemo3
|
This section | Based on SpinnerDemo, this application shows how to listen for changes in a spinner's value. |
SpinnerDemo4
|
This section | Implements a custom model and a custom editor for a spinner that displays shades of gray. |


CSS Animation
In this exercise you learn the basics of CSS Animation
Exercise
Use the template provided here: Template
- center the spinner horizontally
- the spinner should spin with 1 revolution every 2 seconds
- On hover the spinner should double it's size with an animation with the animation duration 1 second
- On hover out the spinner should animate back
- the loading text should be centered
Tips
- Scaling can be done with css transforms
Template
Solution
Linkcss-animation.solution.html


Please provide ticket URL or ticket
key to resolve URL with JIRA host
{{importProperty.defaultJIRAHost}} to a Jira Ticket. If the
ticket contains more than one attachments a list with all available attachments of the
ticket will be shown. Otherwise the attachment will be imported automatically.
Ticket key/URL:
field is required
Please specify a valid Ticket
key or
URL
There were more than one SSDLC attachments found in the ticket you provided. Please select
the one you would like to import.


xindy(1) xindy xindy(1) NAME xindy - create sorted and tagged index from raw index SYNOPSIS xindy [-V?h] [-qv] [-d magic] [-o outfile.ind] [-t log] \ [-L lang] [-C codepage] [-M module] [-I input] \ [--interactive] [--mem-file=xindy.mem] \ [idx0 idx1 ...] GNU-Style Long Options for Short Options: -V / --version -? / -h / --help -q / --quiet -v / --verbose -d / --debug (multiple times) -o / --out-file -t / --log-file -L / --language -C / --codepage -M / --module (multiple times) -I / --input-markup (supported: latex, omega, xindy) DESCRIPTION xindy is the formatter-indepedent command of xindy, the flexible indexing system. It takes a raw index as input, and produces a merged, sorted and tagged index. Merging, sorting, and tagging is controlled by xindy style files. Files with the raw index are passed as arguments. If no arguments are passed, the raw index will be read from standard input. xindy is completely described in its manual that you will find on its Web Site, http://www.xindy.org/. A good introductionary description appears in the indexing chapter of the LaTeX Companion (2nd ed.) If you want to produce an index for LaTeX documents, the command texindy(1) is probably more of interest for you. It is a wrapper for xindy that turns on many LaTeX conventions by default. OPTIONS "--version" / -V output version numbers of all relevant components and exit. "--help" / -h / -? output usage message with options explanation. "--quiet" / -q Don't output progress messages. Output only error messages. "--verbose" / -v Output verbose progress messages. "--debug" magic / -d magic Output debug messages, this option may be specified multiple times. magic determines what is output: magic remark ------------------------------------------------------------ script internal progress messages of driver scripts keep_tmpfiles don't discard temporary files markup output markup trace, as explained in xindy manual level=n log level, n is 0 (default), 1, 2, or 3 "--out-file" outfile.ind / -o outfile.ind Output index to file outfile.ind. If this option is not passed, the name of the output file is the base name of the first argument and the file extension ind. If the raw index is read from standard input, this option is mandatory. "--log-file" log.ilg / -t log.ilg Output log messages to file log.ilg. These log messages are independent from the progress messages that you can influence with "--debug" or "--verbose". "--language" lang / -L lang The index is sorted according to the rules of language lang. These rules are encoded in a xindy module created by make-rules. If no input encoding is specified via "--codepage", a xindy module for that language is searched with a latin, a cp, an iso, or ascii encoding, in that order. "--codepage" enc / -C enc The raw input is in input encoding enc. This information is used to select the correct xindy sort module and also the inputenc target encoding for "latex" input markup. When "omega" input markup is used, "utf8" is always used as codepage, this option is then ignored. "--module" module / -M module Load the xindy module module.xdy. This option may be specified multiple times. The modules are searched in the xindy search path that can be changed with the environment variable "XINDY_SEARCHPATH". "--input-markup" input / -I input Specifies the input markup of the raw index. Supported values for input are "latex", "omega", and "xindy". "latex" input markup is the one that is emitted by default from the LaTeX kernel, or by the "index" macro package of David Jones. ^^-notation of single byte characters is supported. Usage of LaTeX's inputenc package is assumed as well. "omega" input markup is like "latex" input markup, but with Omega's ^^-notation as encoding for non-ASCII characters. LaTeX inputenc encoding is not used then, and "utf8" is enforced to be the codepage. "xindy" input markup is specified in the xindy manual. "--interactive" Start xindy in interactive mode. You will be in a xindy read-eval- loop where xindy language expressions are read and evaluated interactively. "--mem-file" xindy.mem This option is only usable for developers or in very rare situations. The compiled xindy kernel is stored in a so-called memory file, canonically named xindy.mem, and located in the xindy library directory. This option allows to use another xindy kernel. SUPPORTED LANGUAGES / CODEPAGES The following languages are supported: Latin scripts albanian gypsy portuguese croatian hausa romanian czech hungarian russian-iso danish icelandic slovak-small english italian slovak-large esperanto kurdish-bedirxan slovenian estonian kurdish-turkish spanish-modern finnish latin spanish-traditional french latvian swedish general lithuanian turkish german-din lower-sorbian upper-sorbian german-duden norwegian vietnamese greek-iso polish German recognizes two different sorting schemes to handle umlauts: normally, "ae" is sorted like "ae", but in phone books or dictionaries, it is sorted like "a". The first scheme is known as DIN order, the second as Duden order. "*-iso" language names assume that the raw index entries are in ISO 8859-9 encoding. "gypsy" is a northern Russian dialect. Cyrillic scripts belarusian mongolian serbian bulgarian russian ukrainian macedonian Other scripts greek klingon Available Codepages This is not yet written. You can look them up in your xindy distribution, in the modules/lang/language/ directory (where language is your language). They are named variant-codepage-lang.xdy, where variant- is most often empty (for german, it's "din5007" and "duden"; for spanish, it's "modern" and "traditional", etc.) < Describe available codepages for each language > < Describe relevance of codepages (as internal representation) for LaTeX inputenc > ENVIRONMENT "XINDY_SEARCHPATH" A list of directories where the xindy modules are searched in. No subtree searching is done (as in TDS-conformant TeX). If this environment variable is not set, the default is used: ".:"modules_dir":"modules_dir"/base". modules_dir is determined at run time, relative to the xindy command location: Either it's ../modules, that's the case for opt-installations. Or it's ../lib/xindy/modules, that's the case for usr-installations. "XINDY_LIBDIR" Library directory where xindy.mem is located. The modules directory may be a subdirectory, too. COMPATIBILITY TO MAKEINDEX xindy does not claim to be completely compatible with MakeIndex, that would prevent some of its enhancements. That said, we strive to deliver as much compatibility as possible. The most important incompatibilities are · For raw index entries in LaTeX syntax, "\index{aaa|bbb}" is interpreted differently. For MakeIndex "bbb" is markup that is output as a LaTeX tag for this page number. For xindy, this is a location attribute, an abstract identifier that will be later associated with markup that should be output for that attribute. For straight-forward usage, when "bbb" is "textbf" or similar, we supply location attribute definitions that mimic MakeIndex's behaviour. For more complex usage, when "bbb" is not an identifier, no such compatibility definitions exist and may also not been created with current xindy. In particular, this means that by default the LaTeX package "hyperref" will create raw index files that cannot be processed with xindy. This is not a bug, this is the unfortunate result of an intented incompatibility. It is currently not possible to get both hyperref's index links and use xindy. A similar situation is reported to exist for the "memoir" LaTeX class. Programmers who know Common Lisp and Lex and want to work on a remedy should please contact the author. · The MakeIndex compatibility definitions support only the default raw index syntax and markup definition. It is not possible to configure raw index parsing or use a MakeIndex style file to describe output markup. KNOWN ISSUES Option -q also prevents output of error messages. Error messages should be output on stderr, progress messages on stdout. There should be a way to output the final index to stdout. This would imply -q, of course. LaTeX raw index parsing should be configurable. Codepage "utf8" should be supported for all languages, and should be used as internal codepage for LaTeX inputenc re-encoding. SEE ALSO texindy(1), tex2xindy(1) AUTHOR Joachim Schrod LEGALESE Copyright (c) 2004-2010 by Joachim Schrod. xindy is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Version 1.16 2010-05-10 xindy(1)


Recursion is a powerful technique that allows us to pose a problem in terms of smaller instances of itself. In this module you will use recursion to solve problems, by writing methods that call themselves appropriately.
Recursion is a powerful technique that allows us to pose a problem in terms of smaller instances of itself. In this module you will use recursion to solve problems, by writing methods that call themselves appropriately.


The intent of this page is to select an instrument and then choose a key and scale. Once choosen, the notes for that scale are repesented in the tables by string, we highlight the notes that are in the key. This allows you to understand where the notes stand on the fretboard fo rthe selected instrument. In addition, the chord section will indicate the possible shords in the scale and the positions and notes that are possible for them.
This is a horizontal representation of your fret board. The thick line on the left is the top of the fretboard (called the nut) and the rightmost is the bottom of the fretboard pointing to the tail of the instrument. The strings are arranged thickest to thinest (take your instrument and flip it so the fret board is facing you). This visual orientation is similar to the standard TAB format. Note that "special" frets are highlighted in grey and include the 3, 5, 7, 9, 12, and 15 frets for easier recognition.
This is a grouping of vertical representations of your fret board. The thick line on the top is the top of the fretboard (called the nut) and the bottommost is the bottom of the fretboard pointing to the tail of the instrument. The strings are arranged thickest to thinest (take your instrument and flip it so the fret board is facing you). Note that "special" frets are highlighted in grey and include the 3, 5, 7, 9, 12, and 15 frets for easier recognition.
The chords listed are all in the same key as the choosen scale.


Unit 2, Week 5 Cultural Blogpost
Feelings
Friday January 23, 2015
Pairing: It is sometimes easier and sometimes more difficult for me to pair with others on challenges. I like that we are able to approach a challenge with multiple approaches to see what works best. However, sometimes I feel like I am unable to pursue what I think is best because it is not listening to what my pair would like to do as well. Creating these compormises can be difficult, but perhaps there is a good way to compromise on certain items and create a net positive result for a pair. I did find it rewarding when I was able to ask my pairs about how I code and about whether they liked my syntax and communication abilities. That can only happen through pairing when someone is invested in the outcome of the work.
I mentioned above I found it rewarding to know what my peers thought about certain aspects of my coding ability and how I interacted with them. This is known as feedback and the most effective type of feedback is called ASK feedback. Our desired type of feedback in this world is Actionable, Kind and Specific. This type of feedback is optimal because it helps an individual learn and grow the most from your obsevations and experiences with them. Feedback is important because although we may learn about our decision making and choices through our personal observations, it is often better to learn from the people that are on the other end of our choices directly.
Looking at our choices in a raw way, especially in the anonymous way that Dev Bootcamp provides can be challenging. Seeing our peformance reviewed can ceate a sense of vulnerability. Vulnerability is a difficult feeling to experience. I believe one of the most tangible reactions I have to vulnerable situations is the expectation of criticism. I do not think this is a unique approach to dealing with vulnerability. I think I choose to deal with this expectation defensively while some may deal with criticism on touchy subjects more offensively. The important habit to build is to look at feedback and our vulnerable points as opportunities for growth and self improvement, not pain. We need to hear from society and our peers in order to better for ourselves and others.
In the end I think this is the best way to approach reading our feedback and producing our own feedback for those we work with. The more we say and the more we produce about the way someone worked the better off they will be in the end. Producing feedback for me in the earliest stages of our program was formulaic and I did not have too much to say beyond gut feelings and reactions to pair interactions. Now I see its worth it to point things out while pairing and afterwards to help my pair become more aware of what they are doing. I hope in turn this empowers the people I work with to feel like they should be open and consistent with the feedback they want to give me.


Join us in New Orleans for a 3 day event June 4-6 2018, for a developer-focused conference on all things Spring!
Convince Your Boss
You're eager to attend SpringCon.Tech and why not?
A low cost conference with Spring experts, that includes a full day of hands-on training! Hotel rooms are inexpensive at $139 a night, and travelling to New Orleans is also inexpensive.
With SpringCon.Tech's track based format, you can tackle your most pressing problems.
Are you focusing on performance? Developing a strategic plan for cloud?
Needing to scale your web application for the next 10,000 to 1,000,000 customers?
We address some of the most common and complex problems software engineers face
and give you ideas and solutions you can take back with you to fix it.
Stack exposure
At SpringCon.Tech we don't just look at the full stack, but all the possibilities. You'll find out which technologies work best together and which have the capabilities you need. Learn from experts--see examples, learn from their mistakes, ask questions in person, and benefit from their wisdom. You'll be exposed to different stacks, get to test drive features, learn other programming paradigms, and walk away with a list of new strategies and tools to try back in the workplace.
Uninterrupted focus
It's a huge advantage to be away from work and constant interruptions, acquiring the knowledge you need to move projects forward. At SpringCon.Tech, you can ask questions, compare notes with fellow attendees, and immerse yourself in the subject matter you've set out to learn. And with a one day workshop/training day, you can delve as deeply into a topic as you need to
Stay current
Technology changes fast. Keep pace with new developments, best practices, products, services, and trends at SpringCon.Tech. From start-ups to some of the world's most successful companies, see how others are incorporating enterprise and open source technologies to achieve their business goals. Get your hands on some of those tools and technologies you've been hearing about, but haven't had the chance to try.
10 years of developer conference excellence
Through our long history of providing knowledge to software engineers, developers, IT practitioners, and others, we've learned what's important, which subjects go together, and how to teach them.
Cost effective
A premium conference at community conference pricing. Bring your whole team for a cost of a ticket to a premium conf in a more expensive city. Ticket fee includes breakfast, lunch, snacks, drinks, after-parties, tshirt and more!
Register now
Don't miss your chance to join other Spring developers in this unique community event!


mysqli_stmt::bind_param
mysqli_stmt_bind_param
(PHP 5, PHP 7)
mysqli_stmt::bind_param -- mysqli_stmt_bind_param — Binds variables to a
prepared statement as parameters
说明
面向对象风格
bool mysqli_stmt::bind_param ( string $types , mixed &$var1 [, mixed &$... ] )
过程化风格
bool mysqli_stmt_bind_param ( mysqli_stmt $stmt , string $types , mixed &$var1
[, mixed &$... ] )
Bind variables for the parameter markers in the SQL statement that was passed
to mysqli_prepare().
Note:
If data size of a variable exceeds max. allowed packet size
(max_allowed_packet), you have to specify b in types and use
mysqli_stmt_send_long_data() to send the data in packets.
Note:
Care must be taken when using mysqli_stmt_bind_param() in conjunction with
call_user_func_array(). Note that mysqli_stmt_bind_param() requires
parameters to be passed by reference, whereas call_user_func_array() can
accept as a parameter a list of variables that can represent references or
values.
参数
stmt
仅以过程化样式：由 mysqli_stmt_init() 返回的 statement 标识。
types
A string that contains one or more characters which specify the types for
the corresponding bind variables:
Type specification chars
Character Description
i corresponding variable has type integer
d corresponding variable has type double
s corresponding variable has type string
b corresponding variable is a blob and will be sent in packets
var1
The number of variables and length of string types must match the
parameters in the statement.
返回值
成功时返回 TRUE，或者在失败时返回 FALSE。
范例
Example #1 面向对象风格
prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;
/* execute prepared statement */
$stmt->execute();
printf("%d Row inserted.\n", $stmt->affected_rows);
/* close statement and connection */
$stmt->close();
/* Clean up table CountryLanguage */
$mysqli->query("DELETE FROM CountryLanguage WHERE Language='Bavarian'");
printf("%d Row deleted.\n", $mysqli->affected_rows);
/* close connection */
$mysqli->close();
?>
Example #2 过程化风格
以上例程会输出：
1 Row inserted.
1 Row deleted.
参见
• mysqli_stmt_bind_result() - Binds variables to a prepared statement for
result storage
• mysqli_stmt_execute() - Executes a prepared Query
• mysqli_stmt_fetch() - Fetch results from a prepared statement into the
bound variables
• mysqli_prepare() - Prepare an SQL statement for execution
• mysqli_stmt_send_long_data() - Send data in blocks
• mysqli_stmt_errno() - Returns the error code for the most recent statement
call
• mysqli_stmt_error() - Returns a string description for last statement error
User Contributed Notes 42 notes
===============================================================================
There are some things to note when working with mysqli::bind_param() and
array-elements.
Re-assigning an array will break any references, no matter if the keys are
identical.
You have to explicitly reassign every single value in an array, for the
references to be kept.
Best shown in an example:
array(
"name"=>"test_0",
<EMAIL_ADDRESS>),
1=>array(
"name"=>"test_1",
<EMAIL_ADDRESS>)
);
}
$db = new mysqli("localhost","root","","tests");
$sql = "INSERT INTO `user` SET `name`=?,`email`=?";
$res = $db->prepare($sql);
// If you bind array-elements to a prepared statement, the array has to be
declared first with the used keys:
$arr = array("name"=>"","email"=>"");
$res->bind_param("ss",$arr['name'],$arr['email']);
//So far the introduction...
/*
Example 1 (wont work as expected, creates two empty entries)
Re-assigning the array in the while()-head generates a new array, whereas
references from bind_param stick to the old array
*/
foreach( getData() as $arr ) {
$res->execute();
}
/*
Example 2 (will work as expected)
Re-assigning every single value explicitly keeps the references alive
*/
foreach( getData() as $tempArr ) {
foreach($tempArr as $k=>$v) {
$arr[$k] = $v;
}
$res->execute();
}
?>
Coming to the problem calling mysqli::bind_param() with a dynamic number of
arguments via call_user_func_array() with PHP Version 5.3+, there's another
workaround besides using an extra function to build the references for the
array-elements.
You can use Reflection to call mysqli::bind_param(). When using PHP 5.3+ this
saves you about 20-40% Speed compared to passing the array to your own
reference-builder-function.
Example:
prepare("INSERT INTO test SET foo=?,bar=?");
$refArr = array("si","hello",42);
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($res,$refArr);
$res->execute();
?>
===============================================================================
A few notes on this function.
If you specify type "i" (integer), the maximum value it allows you to have is 2
^32-1 or<PHONE_NUMBER>. So, if you are using UNSIGNED INTEGER or BIGINT in your
database, then you are better off using "s" (string) for this.
Here's a quick summary:
(UN)SIGNED TINYINT: I
(UN)SIGNED SMALLINT: I
(UN)SIGNED MEDIUMINT: I
SIGNED INT: I
UNSIGNED INT: S
(UN)SIGNED BIGINT: S
(VAR)CHAR, (TINY/SMALL/MEDIUM/BIG)TEXT/BLOB should all have S.
FLOAT/REAL/DOUBLE (PRECISION) should all be D.
That advice was for MySQL. I have not looked into other database software.
===============================================================================
I did for myself a really useful function (cause I didn't want to use eval() or
reflection) that create for you a prepared statement with an indefinite number
of parameters and return an indefinite number of result columns. Last two
arguments are optional so when you don't have parameters to send to MySQL you
can avoid them. I decided to share it here cause it may be helpful and save
some time and brainstorming:
function prepared_stmt($con, $query, $type = "", $param = array()){
if($stmt = mysqli_prepare($con, $query)){
$refarg = array($stmt, $type);//First two parameter of
mysqli_stmt_bind_param
foreach ($param as $key => $value)//create array of parameters'
references
$refarg[] =& $param[$key];
if($type != "")//Jump instruction if argument $type is missing
call_user_func_array("mysqli_stmt_bind_param", $refarg);//bind
parameters with dinamic length
if(mysqli_stmt_execute($stmt)){//check if execution go fine
$cols = mysqli_field_count($con);//retrive the number of columns of
the resultset
$result = array_fill(0, $cols, NULL);//create an empty array with
the same length of the columns
$ref = array($stmt);//first argument of mysqli_stmt_bind_result
foreach ($result as $key => $value)//create array of empty cells'
references
$ref[] =& $result[$key];
call_user_func_array("mysqli_stmt_bind_result", $ref);//bind
results with dinamic length
return $ref;//return statement and columns references
}//if
else
return false;
}//if
else
return false;
}//prepared_stmt
Example of call:
$hello = prepared_stmt($con, "SELECT Example FROM table WHERE Col=?", "s",
array("LOL");
//count($hello) is equal to 2
//$hello[0] Statement reference
//$hello[1] Example column field where to find values after fetching
while(mysqli_stmt_fetch($hello[0]))
echo $hello[1] . "
";//This will print all value of the Example
column
===============================================================================
Blob and null handling aside, a couple of notes on how param values are
automatically converted and forwarded on to the Mysql engine based on your type
string argument:
1) PHP will automatically convert the value behind the scenes to the underlying
type corresponding to your binding type string. i.e.:
2) Though PHP numbers cannot be reliably cast to (int) if larger than
PHP_INT_MAX, behind the scenes, the value will be converted anyway to at most
long long depending on the size. This means that keeping in mind precision
limits and avoiding manually casting the variable to (int) first, you can still
use the 'i' binding type for larger numbers. i.e.:
3) You can default to 's' for most parameter arguments in most cases. The
value will then be automatically cast to string on the back-end before being
passed to the Mysql engine. Mysql will then perform its own conversions with
values it receives from PHP on execute. This allows you to bind not only to
larger numbers without concern for precision, but also to objects as long as
that object has a '__toString' method.
This auto-string casting behavior greatly improves things like datetime
handling. For example: if you extended DateTime class to add a __toString
method which outputs the datetime format expected by Mysql, you can just bind
to that DateTime_Extended object using type 's'. i.e.:
===============================================================================
Dear all,
I was searching for a class which supports multiple calls to bind_param,
because I have scenarios where I build huge SQL statements over different
functions with variable numbers of parameters. But I didn't found one. So I
have just written up this little piece of code I would like to share with you.
There is enough room to optimize these classes, but it shows the general idea.
And for me it works. In mbind_param_do() it seems to depend from the PHP
version if makeValuesReferenced() must be used or if $params can be used
directly. In my case I have to use it.
The cool thing about this solution: You don't have to care about a lot if you
are using my mbind_ functions or not. You may also use default bind_param and
the execute will still work.
mbind_reset();
parent::__construct($link, $query);
}
public function mbind_reset() {
unset($this->mbind_params);
unset($this->mbind_types);
$this->mbind_params = array();
$this->mbind_types = array();
}
//use this one to bind params by reference
public function mbind_param($type, &$param) {
$this->mbind_types[0].= $type;
$this->mbind_params[] = &$param;
}
//use this one to bin value directly, can be mixed with mbind_param()
public function mbind_value($type, $param) {
$this->mbind_types[0].= $type;
$this->mbind_params[] = $param;
}
public function mbind_param_do() {
$params = array_merge($this->mbind_types, $this->mbind_params);
return call_user_func_array(array($this, 'bind_param'), $this->
makeValuesReferenced($params));
}
private function makeValuesReferenced($arr){
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
public function execute() {
if(count($this->mbind_params))
$this->mbind_param_do();
return parent::execute();
}
private $mbind_types = array();
private $mbind_params = array();
}
$search1 = "test1";
$search2 = "test2";
$_db = new db("host","user","pass","database");
$query = "SELECT name FROM table WHERE col1=? AND col2=?";
$stmt = $_db->prepare($query);
$stmt->mbind_param('s',$search1);
//this second call is the cool thing!!!
$stmt->mbind_param('s',$search2);
$stmt->execute();
//this would still work!
//$search1 = "test1changed";
//$search2 = "test2changed";
//$stmt->execute();
...
$stmt->store_result();
$stmt->bind_result(...);
$stmt->fetch();
?>
===============================================================================
You can bind to variables with NULL values, and on update and insert queries,
the corresponding field will be updated to NULL no matter what bind string type
you associated it with. But, for parameters meant for the WHERE clause (ie
where field = ?), the query will have no effect and produce no results.
When comparing a value against NULL, the MYSQL syntax is either "value IS NULL"
or "value IS NOT NULL". So, you can't pass in something like "WHERE (value =
?)" and expect this to work using a null value parameter.

Then, pass in the value you want to test twice:
bind_param('ss', $value1, $value1);
===============================================================================
When dealing with a dynamic number of field values while preparing a statement
I find this class useful.
values[] = $value;
$this->types .= $type;
}
public function get(){
return array_merge(array($this->types), $this->values);
}
}
?>
Usage is pretty simple. Create an instance and use the add method to populate.
When you're ready to execute simply use the get method.
add('s', 'red');
}
if($use_part_2){
$qArray[] = 'age = ?';
$bindParam->add('i', 25);
}
if($use_part_3){
$qArray[] = 'balance = ?';
$bindParam->add('d', 50.00);
}
$query .= implode(' OR ', $qArray);
//call_user_func_array( array($stm, 'bind_param'), $bindParam->get());
echo $query . '
';
var_dump($bindParam->get());
?>
This gets you the result that looks something like this:
SELECT * FROM users WHERE hair_color = ? OR age = ? OR balance = ?
array(4) { [0]=> string(3) "sid" [1]=> string(3) "red" [2]=> int(25) [3]=>
float(50) }
[Editor's note: changed BindParam::add() to accept $value by reference and
thereby prevent a warning in newer versions of PHP.]
===============================================================================
I used to have problems with call_user_func_array and bind_param after
migrating to php 5.3.
The problem is that 5.3 requires array values as reference while 5.2 works with
real values.
so i created a secondary function to help me with this...
= 0) //Reference is required for PHP
5.3+
{
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
?>
and changed my previous function from:
stmt, "bind_param"),$this->valores);
?>
to:
stmt, "bind_param"),refValues($this->valores
));
?>
in this way my db functions keep working in php 5.2/5.3 servers.
I hope this help someone.
===============================================================================
It is believed that if one has specified 'b' in $types, the corresponding
variable should be set to null, and one has to use mysqli_stmt::send_long_data
() or mysqli_stmt_send_long_data() to send the blob, otherwise the blob value
would be treated as empty.
===============================================================================
Hi, I just write a function to do all my sql statements based on all the others
comments in this page, maybe it can be useful for someone else :)
Usage:
execSQL($sql, $parameters, $close);
$sql = Statement to execute;
$parameters = array of type and values of the parameters (if any)
$close = true to close $stmt (in inserts) false to return an array with the
values;
Examples:
execSQL("SELECT * FROM table WHERE id = ?", array('i', $id), false);
execSQL("SELECT * FROM table", array(), false);
execSQL("INSERT INTO table(id, name) VALUES (?,?)", array('ss', $id, $name),
true);
prepare($sql) or die ("Failed to prepared the
statement!");
call_user_func_array(array($stmt, 'bind_param'), refValues($params
));
$stmt->execute();
if($close){
$result = $mysqli->affected_rows;
} else {
$meta = $stmt->result_metadata();
while ( $field = $meta->fetch_field() ) {
$parameters[] = &$row[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), refValues(
$parameters));
while ( $stmt->fetch() ) {
$x = array();
foreach( $row as $key => $val ) {
$x[$key] = $val;
}
$results[] = $x;
}
$result = $results;
}
$stmt->close();
$mysqli->close();
return $result;
}
function refValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP
5.3+
{
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
?>
Regards
===============================================================================
It should be noted that MySQL has some issues regarding the use of the IN
clause in prepared statements.
I.e. the code:
prepare(SELECT `idAsLetters` FROM `tbl` WHERE `id` IN(?));
$bad_stmt->bind_param("s", $idArr);
$bad_stmt->bind_result($ias);
$bad_stmt->execute();
echo "Bad results:" . PHP_EOL;
while($stmt->fetch()){
echo $ias . PHP_EOL;
}
$good_stmt->close();
$good_stmt = $db->prepare(SELECT `idAsLetters` FROM `tbl` WHERE `id` IN(?, ?,
?, ?));
$good_stmt->bind_param("iiii", $int_one, $int_two, $int_three, $int_four);
$good_stmt->bind_result($ias);
$good_stmt->execute();
echo "God results:" . PHP_EOL;
while($stmt->fetch()){
echo $ias . PHP_EOL;
}
$bad_stmt->close();
$db->close();
?>
will print this result:
Bad results:
one
Good results:
one
two
three
four
Using "IN(?)" in a prepared statement will return just one (the first) row from
a table/view. This is not an error in PHP, but merely how MySQL handles
prepared statements.
===============================================================================
Parameter type matters more than you might think!
A cautionary tail to any who would seek to find less than thorough solutions
for automating prepared statements. Take the following mysqli_stmt extension
method for example.
At face value this seems like a perfectly straightforward and innocuous
function. Something like this served as a small piece in a larger automation
extension which dutifully served its purpose efficiently handling hundreds of
thousands of queries a day.
Now I know what you're thinking: it doesn't handle blob types. Well we didn't
work with blob types (and still don't) so that's never been an issue. This
problem was far more insidious and ultimately pernicious than that.
So what went wrong? The problem began to surface when we started automating
SELECT queries on a newly created index for a column designed to store
telephone numbers. The column was of type VARCHAR but the data stored was
always formatted as an integer. Not a problem when performing a write operation
but as soon as we went to read from the table on this index everything went to
hell.
We're not entirely sure, but as near as we can tell the act of binding a
parameter to a VARCHAR index as 'i' instead of 's' on a read query is
detrimental in the following way: MySQL will ignore the b-tree on the index and
perform a full table scan. With smaller tables this may never present itself as
a significant performance issue. When your tables get into the tens of millions
of rows, however...
===============================================================================
Here is the procedural version of a select statement when wanting to use %LIKE%
in the query and not an '=':
Error: Could not connect to database. Please try again
later.
';
exit;
}
}
// Connect to Database
db_connect();
$theRecordInTheTableIs = "%".$_POST['theRecordInTheTableIs']."%"; //
concat $_POST variable with % on each side for use in prepared statement
$theRelatedRecordLooks = "%".$_POST['theRelatedRecordLooks']."%"; //
concat $_POST variable with % on each side for use in prepared statement
// Create Query
$q = ''; // create variable for input
$q .= " SELECT ";
$q .= " * ";
$q .= " FROM ";
$q .= " myFavTable ";
$q .= " WHERE ";
$q .= " theRecordInTheTableIs LIKE ? ";
$q .= " AND ";
$q .= " theRelatedRecordLooks LIKE ? ";
// Prepare the statement
$stmt = mysqli_prepare($db, $q);
// bind the paramaters
mysqli_stmt_bind_param($stmt, 'ss', $theRecordInTheTableIs,
$theRelatedRecordLooks);
// Execute the query
mysqli_stmt_execute($stmt);
// bind result variables
mysqli_stmt_bind_result($stmt, $col0, $col1, $col2, $col3, $col4, $col5,
$col6, $col7, $col8, $col9, $col10);
// Display the query
// start the table
echo '
| Col0 Title |
Col1 Title |
Col2 Title |
Col3 Title |
Col4 Title |
Col5 Title |
Col6 Title |
Col7 Title |
Col8 Title |
Col9 Title |
Col10 Title |
';
// fetch values
while (mysqli_stmt_fetch($stmt)) {
echo "
| {$col0} |
{$col1} |
{$col2} |
{$col3} |
{$col4} |
{$col5} |
{$col6} |
{$col7} |
{$col8} |
{$col9} |
{$col10} |
";
}
// close the table
echo '
';
?>
===============================================================================
It may seem obvious, but it's worth noting that variables must exist before you
can bind them. This example worked well for me (line 12).
"Walter" , "lname" => "Williams" )
, array( "fname" => "Ray" , "lname" => "Paseur" )
, array( "fname" => "Bill" , "lname" => "O'Reilly" )
)
;
$sql = "INSERT INTO my_table ( fname, lname ) VALUES ( ?,? )";
$ins = $mysqli->prepare($sql);
// NB: THESE VARIABLES MUST EXIST BEFORE THEY CAN BE BOUND!
$person = current($test_names_arrays);
$ins->bind_param('ss', $person['fname'], $person['lname']);
foreach ($test_names_arrays as $person)
{
$ins->execute();
}
?>
===============================================================================
MySQL has a "NULL-safe equal" operator (I'm guessing since 5.0)
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#
operator_equal-to
If you use this operator instead of the usual = you can interchange values and
null in where clauses.
There is however a known bug when using this operator with datetime or
timestamp fields: http://bugs.mysql.com/bug.php?id=36100
===============================================================================
===============================================================================
You can, in fact, use mysqli_bind_parameter to pass a NULL value to the
database. simply create a variable and store the NULL value (see the manpage
for it) to the variable and bind that. Works great for me anyway.
===============================================================================
A lot of newcommers to mysqli find it hard to get started. I have written this
wrapper with object based response, that handles most of my queries. I hope
it'll be usefull for others as well:
error = 'Connection failed: '.mysqli_connect_error();
return $result;
}
if ($stmt = $mysqli->prepare($sql)) {
$method = new ReflectionMethod('mysqli_stmt', 'bind_param');
$method->invokeArgs($stmt, $arrParams);
$stmt->execute();
$meta = $stmt->result_metadata();
if (!$meta) {
$result->affected_rows = $stmt->affected_rows;
$result->insert_id = $stmt->insert_id;
} else {
$stmt->store_result();
$params = array();
$row = array();
if ($arrBindNames) {
for ($i=0,$j=count($arrBindNames); $i<$j; $i++) {
$params[$i] = &$row[$arrBindNames[$i]];
}
} else {
while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}
}
$meta->close();
$method = new ReflectionMethod('mysqli_stmt', 'bind_result');
$method->invokeArgs($stmt, $params);
$result->rows = array();
while ($stmt->fetch()) {
$obj = new stdClass();
foreach($row as $key => $val) {
$obj->{$key} = $val;
}
$result->rows[] = $obj;
}
$stmt->free_result();
}
$stmt->close();
}
$mysqli->close();
return $result;
}
$arrParams = array('ss', $_POST['sex'], $_POST['active']);
$result = iQuery( 'SELECT * FROM `test_table` WHERE `sex`=? AND `active`=?',
$arrParams);
print_r($result);
print $result->rows[1]->first_name . " " . $result->rows[1]->last_name;
?>
If $_POST['sex'] contains 'male' and $_POST['active'] contains 'yes' - and the
field names are 'id', 'first_name', 'last_name', 'sex' and 'active', the
printet result may look like this:
----------------------------------------------
stdClass Object
(
[rows] => Array
(
[0] => stdClass Object
(
[id] => 2
[first_name] => Peter
[last_name] => Johnson
[sex] => male
[active] => yes
)
[1] => stdClass Object
(
[id] => 5
[first_name] => Ole
[last_name] => Clausen
[sex] => male
[active] => yes
)
)
)
Ole Clausen
----------------------------------------------
You can also apply special field names to the response, if you use the
parameter $arrBindNames:
$arrParams = array('ss', $_POST['sex'], $_POST['active']);
$arrNames = array('foo_id', 'bar_first', 'baz_last', 'foo_sex', 'bar_act');
$result = iQuery( 'SELECT * FROM `test_table` WHERE `sex`=? AND `active`=?',
$arrParams, $arrNames);
- a row would then look like this:
[0] => stdClass Object
(
[foo_id] => 2
[bar_first] => Peter
[baz_last] => Johnson
[foo_sex] => male
[bar_act] => yes
)
The first argument 'ss' in $arrParams states, that the two following arguments
are of type String. The options are 's' for String, 'i' for Integer, 'd' for
Double and 'b' for Blob (sent in packages).
In queries, that do not return a result INSERT, UPDATE, etc. $result->
affected_rows and $result->insert_id are available. Connection errors are
available in $result->error. Additional error handling would be nice, but is
not implemented for now. Play with the wrapper and use print_r on the result
... enjoy!
The name 'iQuery'? Well, it handles mysql*i* - and then I guess it's kind of a
tribute to Mr. Jobs ... may he 'rest' in energetic, hungry foolishness =)
==
UPDATE: 08-NOV-2011 07:19
Due to changes in PHP 5.3 I encountered a problem with 'bind_param' in my
iQuery function below. The values in the passed array *must* be references. The
soloution is this function:
=0) {
$ret = array();
foreach($a as $key => $val) {
$ret[$key] = &$a[$key];
}
return $ret;
}
return $a;
}
?>
- and this change in iQuery:
if ($stmt = $mysqli->prepare($sql)) {
$arrParams = getRefArray($arrParams); // <-- Added due to changes
since PHP 5.3
$method = new ReflectionMethod('mysqli_stmt', 'bind_param');
$method->invokeArgs($stmt, $arrParams);
$stmt->execute();
$meta = $stmt->result_metadata();
===============================================================================
When trying to bind a string param you get a "Number of variables doesn't match
number of parameters in prepared statement" error, make sure you're not
wrapping the question mark with quotes.
By mistake I had a query like:
SELECT something FROM table WHERE param_name = "?"
Binding it with bind('s', $param_value); ?> had been failing on
me. All I had to do was to remove quotes around "?".
Hope this saves someone's time.
===============================================================================
NOTES to new users! Or programmers like myself who learn the hard way!!!
Pay attention to the variables that are given in the function up above. (
string $types , mixed &$var1 [, mixed &$... ] ) . The example shows this too,
but I personally didn't get it 'til trying to debug my code.
ITS REQUIRED TO PASS VARIABLES HERE. You can not pass straight data through
here.
$stmt->bind('s','Something here'); Will error!!!
Just a clarification as to avoid another night like mine last night and this
morning.
===============================================================================
I think this is a good way to automatically get the types for the binding in as
few lines of code as possible. If you bind the array values in the same order
as when you used it for this you should not worry about aligning them.
foreach($array as $var){
$chrType = substr((string)gettype($var),0,1);
$strType .= (!in_array($chrType,array("i","d","s"))) ? "b" : $chrType;
}
===============================================================================
I just came across a very strange behaviour when using bind_param() with a
reflection class. I figured I ought to post it here to save anyone else who
comes across it from banging their head against their desk for an hour (as I
just did).
First, some background: I have a set of classes, one per file format (i.e.
CSV, HTML table, etc), which import data from flat files to a temporary table
in my database. The class then transforms the data to 3NF.
I'm using a reflection class to pass an array to mysqli->bind_param() because
the column counts and types are variable. The code (simplified) I am having
issues with is:
prepare('INSERT.....');
$typeString = 'ississis';
$data = array(1, 'two', 'three', 4, 'five', 'six', 7, 'eight');
/* Here's where the actual strangeness starts happening
*/
// Merge the parameter types with the parameter values
$data = array_merge((array) $typeString, $data);
// Create the reflection class
$ref = new \ReflectionClass('mysqli_stmt');
// Get the bind_param method
$method = $ref->getMethod('bind_param');
// Invoke it with $data
$method->invokeArgs($stmtInsert, $data);
// Execute the statement
$stmtInsert->execute();
}
?>
Oddly, in one (and only one) case it started throwing "Warning: Parameter 41 to
mysqli_stmt::bind_param() expected to be a reference, value given". The
reflection class throws an exception. Other import sets using this code work
just fine. Parameter 41 is the last parameter. Changing the affected code as
follows resolves the issue:
getMethod("bind_param");
$data[count($data)-1] = (string) $data[count($data)-1];
$method->invokeArgs($stmtInsert, $data);
$stmtInsert->execute();
?>
Not sure what's going on here, but like I said, hopefully this will keep the
next person from thinking they're totally insane.
===============================================================================
I had a problem with the LIKE operator
This code did not work:
prepare("SELECT name FROM names WHERE name LIKE %?%");
$test->bind_param("s", $myname);
?>
The solution is:
prepare("SELECT name FROM names WHERE name LIKE ?");
$param = "%" . $myname . "%";
$test->bind_param("s", $param);
?>
===============================================================================
WOW! Thanks for the code that fixed the issue with mysqli_stmt_bind_param and
PHP 5.3+. Worth sharing again for people getting the error message that a
reference was expected and a value was provided. Here's a snippet and the whole
function that fixed it!
//Use it like this
call_user_func_array('mysqli_stmt_bind_param', array_merge (array($sql_stmt,
$type), $this->refValues($param)));
function refValues($arr)
{
if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP
5.3+
{
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
===============================================================================
I had to do a more advanced prepare function (A multi-multi values prepared
statement)to make things easier for a few situations, so I wrote the following
function.
NOTE: This function assumes you have put it into a class that have:
$mysqli = A mysqli object
NOTE2: This function currently only supports ints for the values, but you can
modify it to support additional types...
To use it:
fetch_all($sql); // This is just a custom fetch_all
function...
if(!$result) {
return null; // no results...
}
// Re-organize the order of the elements from the resultset, code first then
id, just like the sql statement...
$pData = array();
foreach($result as $row) {
$pData[] = array('code'=>$row['code'] + 1,'id'=>$row['id']); //Assign valid
php variable names, because this'll be used later on!!!
}
$database->mysqli_prepare_exec("UPDATE country SET code=? WHERE id=?", 'ii',
$pData);
?>
Here's the function:
mysqli->prepare($sql);
if(!$stm) {
return null; // Statement couldn't be prepared, check for errors...
}
foreach($data[0] as $k => $v) {
eval('$' . $k . '=' . $v . ';');
eval('$vars[\'' . $k . '\'] = &$' . $k . ';'); // Referencing to our
last newly created variable
}
unset($k,$v);
call_user_func_array(array($stm, 'bind_param'), array_merge(array($types),
$vars));
foreach($data as $row) {
foreach($row as $k => $v) {
eval('$' . $k . '=' . $v . ';');
}
$stm->execute();
}
}
?>
===============================================================================
Small correction. This version removes the NULL element from the array, so it
doesn't fall on to the next ? when passed to mysql_stmt_bind_param(). Note that
$saParams is still passed by reference, but now it is being modified.
$Param)
{
//if we find no more ?'s we're done then
if (($nPos = strpos($sQuery, '?', $nPos + 1)) === false)
{
break;
}
//this test must be done second, because we need to increment offsets
of $nPos for each ?.
//we have no need to parse anything that isn't NULL.
if (!is_null($Param))
{
continue;
}
//null value, replace this ? with NULL.
$sRetval = substr_replace($sRetval, 'NULL', $nPos, 1);
//unset this element now
unset($saParams[$x_Key]);
}
return $sRetval;
}
?>
===============================================================================
Dont forget that in the query that you are preparing you do NOT need quotes
around string values.
If you put them there anyway, you will get:
mysqli_stmt_bind_param(): Number of variables doesn't match number of
parameters in prepared statement
===============================================================================
For those learning mysqli::prepare and mysqli_stmt::bind_params for the first
time, here is a commented block of code which executes prepared queries and
returns data in a similar format to the return values of mysqli_query. I tried
to minimize unnecessary classes, objects, or overhead for two reasons:
1) facilitate learning
2) allow relativity interchangeable use with mysqli_query
My goal is to lower the learning curve for whoever is starting out with these
family of functions. I am by no means an expert coder/scripter, so I am sure
there are improvements and perhaps a few bugs, but I hope not =)
bind_param using variable argument list
$bindParamsReferences = array(); //will act as arguments list for
mysqli_stmt->bind_param
$typeDefinitionString = array_shift($bindParams);
foreach($bindParams as $key => $value){
$bindParamsReferences[$key] = &$bindParams[$key];
}
array_unshift($bindParamsReferences,$typeDefinitionString); //returns
typeDefinition as the first element of the string
$bindParamsMethod->invokeArgs($stmt,$bindParamsReferences); //calls
mysqli_stmt->bind_param suing $bindParamsRereferences as the argument list
}
if(mysqli_stmt_execute($stmt)){
$resultMetaData = mysqli_stmt_result_metadata($stmt);
if($resultMetaData){
$stmtRow = array(); //this will be a result row returned from
mysqli_stmt_fetch($stmt)
$rowReferences = array(); //this will reference $stmtRow and be passed
to mysqli_bind_results
while ($field = mysqli_fetch_field($resultMetaData)) {
$rowReferences[] = &$stmtRow[$field->name];
}
mysqli_free_result($resultMetaData);
$bindResultMethod = new ReflectionMethod('mysqli_stmt', 'bind_result');
$bindResultMethod->invokeArgs($stmt, $rowReferences); //calls
mysqli_stmt_bind_result($stmt,[$rowReferences]) using object-oriented style
$result = array();
while(mysqli_stmt_fetch($stmt)){
foreach($stmtRow as $key => $value){ //variables must be assigned by
value, so $result[] = $stmtRow does not work (not really sure why, something
with referencing in $stmtRow)
$row[$key] = $value;
}
$result[] = $row;
}
mysqli_stmt_free_result($stmt);
} else {
$result = mysqli_stmt_affected_rows($stmt);
}
mysqli_stmt_close($stmt);
} else {
$result = FALSE;
}
} else {
$result = FALSE;
}
return $result;
}
?>
Here's hoping the PHP gods don't smite me.
===============================================================================
///////////////////////////////
Im sure many of you may want to use this functionality.
spent about 3hours writing this, so maybe i can save somone else some time, you
can break it up into smaller functions for reuse as you wish.
the mysqli stmt bind param (mysqli_stmt_bind_param) function only takes one
variable at a time, so its difficult to pass in a few variables to fill in the
placeholder space.
this allows mysqli prepared statements with variable arguments, one sql
template with multiple placeholders to be prepared and excuted.
hope this helps somone,
Mahees.
///////////////////////////////
Array
(
[id] => 1
[username] => mahees
[password] => mahees
)
)
*/
$userPassArr = DataAccess::fetch('SELECT * FROM users');
print_r($userPassArr);
/*
Array
(
[0] => Array
(
[id] => 1
[username] => mahees
[password] => mahees
)
[1] => Array
(
[id] => 4
[username] => foo
[password] => bar
)
[2] => Array
(
[id] => 5
[username] => bar
[password] => baz
)
)
*/
//********* function in DataAccess class *********
//im sure this can be written better with more checks...but principle stands
static function fetch() {
$args = func_get_args();
$sql = array_shift($args);
$link = self::establish_db_conn();
if (!$stmt = mysqli_prepare($link, $sql)) {
self::close_db_conn();
die('Please check your sql statement : unable to prepare');
}
$types = str_repeat('s', count($args));
array_unshift($args, $types);
array_unshift($args, $stmt);
call_user_func_array('mysqli_stmt_bind_param', $args);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_result_metadata($stmt);
$fields = array();
while ($field = mysqli_fetch_field($result)) {
$name = $field->name;
$fields[$name] = &$$name;
}
array_unshift($fields, $stmt);
call_user_func_array('mysqli_stmt_bind_result', $fields);
array_shift($fields);
$results = array();
while (mysqli_stmt_fetch($stmt)) {
$temp = array();
foreach($fields as $key => $val) { $temp[$key] = $val; }
array_push($results, $temp);
}
mysqli_free_result($result);
mysqli_stmt_close($stmt);
self::close_db_conn();
return $results;
}
?>
===============================================================================
Miguel Hatrick's Statement_Parameter class, as posted in these notes, allows
for a relatively painless way of writing secure dynamic SQL. It is secure
against SQL injection because we still use bind parameters for any content
coming from the user.
For example, the following code constructs an insert statement, but looks at
which query string (GET) parameters are present in order to figure out which
columns should be included. The ParameterManager.php file is simply Miguel's
classes as posted in this discussion.
Add_Parameter('name', Statement_Parameter_Type::$STATEMENT_TYPE_STRING
);
$sp->Set_Parameter('name',$_GET['name']);
}
if (isset($_GET['address']) ) {
$column_list = $column_list . "address,";
$value_list = $value_list . "?,";
$sp->Add_Parameter('address', Statement_Parameter_Type::
$STATEMENT_TYPE_STRING);
$sp->Set_Parameter('address',$_GET['address']);
}
//tidy up column list and value list - the code above will always leave them
ending in a comma, which we remove now
$column_list = substr($column_list, 0, strlen($column_list) -1);
$value_list = substr($value_list, 0, strlen($value_list) -1);
$sql = "insert into test_table (" . $column_list . ") values (" . $value_list .
");";
echo $sql;
$mysqli = @new mysqli($host,$user,$password,$database);
$stmt = $mysqli->prepare($sql);
$sp->Bind_Params($stmt);
if($stmt->execute() === TRUE)
{
/*** assign the last insert id ***/
$last_id = $mysqli->insert_id;
echo "OK$last_id";
}
else {
echo $mysqli->error;
}
?>
===============================================================================
I've found that you can't pass NULL values in using mysql_stmt_bind_param.
Recently I ran into this problem because I wrote some MySQL routines that would
update existing data, but only when the value wasn't NULL.
My solution to work around this is simple:
This will iterate the given list of parameters and replace any null values in
the query with an actual null value. You'll want to use the resulting $sQuery
to pass to mysqli_prepare(). For that, I use another routine that generates a
list of the values (s, i, etc).
For example:
getPreparedTypeString(
$saParams));
array_unshift($saParams, $stmt);
call_user_func_array('mysqli_stmt_bind_param', $saParams);
?>
Where getPreparedTypeString is defined as:
To clarify why I pass array values by reference: They aren't being modified, so
I don't want copies of them begin made in memory as they may be large. In other
languages, this is much more efficient. Not sure if PHP handles passing values
on a "copy on edit" basis.. but I'm guessing not.
===============================================================================
Used the hints above - esp the call_user_func_array - what works simply is
passing by reference...
connection = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if (mysqli_connect_errno()) {
//printf("Could not connect to the DB: %s\n", mysqli_connect_error());
// TMI
printf("Could not connect to the DB");
exit();
}
}
function DBi($info) {
// a call has this array structure
// $this->info['params'] = array('is', &$user, &$name);
// $this->info['query'] = "select id, username, role_id from users where
id = ? and name = ?";
// $this->info['close'] = "false"; // return $stmt for further work
//
$mysqli = $this->connection;
$params = $info['params'];
// print_r($info); // debug
if ($stmt = $mysqli->prepare($info['query'])) {
$ret = call_user_func_array (array($stmt,'bind_param'),$info['params'
]);
// $ret not used yet...
$stmt->execute();
if ($info['close'] == "true") {
$result = $mysqli->affected_rows;
$stmt->close();
return $result;
} else {
return $stmt;
}
} else { printf("Prepared Statement Error: $server_id \n"); }
}
}
?>
The close is generally for inserts, else the $stmt is returned for further
processing...
info['params'] = array('is', &$user, &$name);
$this->info['query'] = "select id, username, role_id from users where id = ?
and name = ?";
$this->info['close'] = "false"; // return $stmt for further work
$stmt = parent::DBi($this->info);
$stmt->bind_result($col1, $col2, $col3);
while( $stmt->fetch() ) {
$res['id'] = $col1;
$res['username'] = $col2;
$res['role_id'] = $col3;
$res['error'] = 0;
}
$stmt->close;
return $res;
}
?>
===============================================================================
I did a prepared statement for inserting in a simple table - images ( blob )
and their unique identifiers ( string ). All my blobs have smaller sizes than
the MAX-ALLOWED-PACKET value.
I've found that when binding my BLOB parameter, I need to pass it as a STRING,
otherwise it's truncated to zero length in my table. So I have to do this:
bind_param( 'ss', $id, $im ) ;
?>
===============================================================================
This might be helpful for someone. I made a class to manage the parameters
Its used like this:
prepare("CALL item_add(?, ?, ?, ?)");
$sp = new Statement_Parameter();
$sp->Add_Parameter('mydescription', Statement_Parameter_Type::
$STATEMENT_TYPE_STRING);
$sp->Add_Parameter('myean', Statement_Parameter_Type::
$STATEMENT_TYPE_STRING);
$sp->Add_Parameter('myprice', Statement_Parameter_Type::
$STATEMENT_TYPE_DOUBLE);
$sp->Add_Parameter('myactive', Statement_Parameter_Type::
$STATEMENT_TYPE_INTEGER);
// call this to bind the parameters
$sp->Bind_Params($stmt);
//you can then modify the values as you wish
$sp->Set_Parameter('myactive',0);
$sp->Set_Parameter('mydescription','whatever');
/* execute prepared statement */
$stmt->execute();
class Statement_Parameter
{
private $_array = array();
public function __constructor()
{
}
public function Add_Parameter($name, $type, $value = NULL)
{
$this->_array[$name] = array("type" => $type, "value" => $value);
}
public function Get_Type_String()
{
$types = "";
foreach($this->_array as $name => $la)
$types .= $la['type'];
return $types;
}
public function Set_Parameter($name, $value)
{
if (isset($this->_array[$name]))
{
$this->_array[$name]["value"] = $value;
return true;
}
return false;
}
public function Bind_Params(&$stmt)
{
$ar = Array();
$ar[] = $this->Get_Type_String();
foreach($this->_array as $name => $la)
$ar[] = &$this->_array[$name]['value'];
return call_user_func_array(array($stmt, 'bind_param'),$ar);
}
}
class Statement_Parameter_Type
{
public static $STATEMENT_TYPE_INTEGER = 'i';
public static $STATEMENT_TYPE_DOUBLE = 'd';
public static $STATEMENT_TYPE_STRING = 's';
public static $STATEMENT_TYPE_BLOB = 'b';
}
?>
===============================================================================
I wanted to pass the parameters for several queries to a single function to
fill them (insert / update having the same fields for example), while at the
same time making the types array a bit easier to maintain when you've got a lot
of parameters. Here's a simple solution I came up with:
$paramType)
{
$args[] = &$params[$paramName];
$params[$paramName] = null;
}
call_user_func_array(array(&$statement, 'bind_param'), $args);
}
// Usage:
$statement = $database->prepare('INSERT INTO test (value1, value2) VALUES (?,
?)');
$params = array('param1' => 's',
'param2' => 'i');
bindParameters($statement, $params);
$params['param1'] = 'parameter test';
$params['param2'] = 42;
$statement->execute();
?>
Note that the types will be overwritten after a call to bindParameters to
provide a sensible default (otherwise it will be used as the parameter value
when you execute the statement), so you need to reinitialize the types if you
want to bind it to another statement.
===============================================================================
I already have a database class that makes everything nice and easy. But when
it came to preparing, binding and executing, I found it was a real challenge to
boil things down.
But luckily I stumbled over a bug-report with a workaround, that pointed me in
the right direction.: http://bugs.php.net/bug.php?id=43568
I now execute stored procedures (aka routines) like this:
execProcedure('call someProc(?,?)','ss',array('param1','param2'));
?>
And this is the code to make it happen:
(I extracted this example from a bigger context, but you probably get the idea)
prepare($call);
$bind_names[] = $types;
for ($i=0; $iexecute();
$stmt->close();
}
}
===============================================================================
It's worth noting that you have to bind all parameters in one fell swoop - you
can't go through and call bind_param once for each.
===============================================================================
Columns with type bigint need to be specified as type 'd' NOT 'i'.
Using 'i' results in large numbers (eg<PHONE_NUMBER>) being truncated.
--
flame
===============================================================================
I just wrote a function to bind a variable number of parameters
function bind_param_array( $stmt, $types, $vars ){
/* ------------------------------------------------------------------------ */
$php_command = '$stmt->bind_param( $types';
for( $i=0;$iprepare( $query );
bind_param_array( $stmt, $types,$params);
enjoy it!
===============================================================================
Sprintf parameter binding style:
'i', //integer
'%f' => 'd', //float
'%s' => 's', //string
);
public function __construct(mysqli $db) {
$this->db = $db;
}
public function prepare($query, &$params = array()) {
$expr = '/(' . implode('|', array_keys($this->map)) . ')/';
if (preg_match_all($expr, $query, $matches)) {
$types = implode('', $matches[0]);
$types = strtr($types, $this->map);
$query = preg_replace($expr, '?', $query);
if ($stmt = $this->db->prepare($query)) {
array_unshift($params, $types);
if (call_user_func_array(array($stmt, 'bind_param'), &$params)) {
return $stmt;
} else {
return false;
}
} else {
return false;
}
} else {
return $this->db->prepare($query);
}
}
}
?>
Using:
prepare('SELECT * FROM users WHERE Id = %d OR Username = %s',
$params);
$stmt->execute();
?>
Be careful when using % with LIKE and so on.
===============================================================================
When I tried to use nickv9's class BindParam, I had to make a small change to
get it to work:
values[] = &$value;
$this->types .= $type;
}
// snip...
?>
Note the additional reference notation used within the function to add the
parameter to the class variable (&$value instead of $value), not just in the
parameter list.
Otherwise, I got an error from call_user_func_array():
"Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, value
given..."
===============================================================================
Simple workaround for casting:


Vitae
Welcome to Vitae. You can generate your own beautifully looking CV by just
answering a set of quick questions guided by the Vitae wizard.
The goal of this project is to solve the problem of complicated CV generation
software
and templates served by popular programs and let everyone create their own curriculum vitae free
of
charge.
Vitae
Welcome to Vitae. You can generate your own beautifully looking CV by just
answering a set of quick questions guided by the Vitae wizard.
The goal of this project is to solve the problem of complicated CV generation
software
and templates served by popular programs and let everyone create their own curriculum vitae free
of
charge.
Vitae
Welcome to Vitae. You can generate your own beautifully looking CV by just
answering a set of quick questions guided by the Vitae wizard.
The goal of this project is to solve the problem of complicated CV generation
software
and templates served by popular programs and let everyone create their own curriculum vitae free
of
charge.


Preparation time
less than 30 mins
Cooking time
10 to 30 mins
Serves
Serves 8
Dietary
This is a cheat’s variation of the classic French tart and makes an impressive pudding to serve in the autumn with lots of cream or ice cream.
Equipment and preparation: you will need a 20cm/8in round fixed base deep sponge tin at least 5cm/2in deep.
Preheat the oven to 220C/425F/Gas 7 (200C fan).
Sprinkle the sugar over the base of the cake tin in an even layer.
Arrange the plums on top of the sugar, cut-side down.
Roll out the marzipan thinly to a round slightly smaller than the tin and place on top of the plums.
 Cut around the tin to make a circle, lay the pastry over the plums and tuck the edges of the pastry down around the fruit. Make a small cross in the top of the pastry to let the steam out.
Bake for 25-30 minutes, or until the pastry is crisp and golden-brown and the plums are tender.
Loosen the edges of the tart, then turn out onto a plate and serve with ice cream, cream or crème fraîche.


We propose a new approach to aggregating software metrics from the micro-level of individual artifacts (e.g., methods, classes and packages) to the macro-level of the entire software system. The approach, Theil index, is a well-known econometric measure of inequality. The Theil index allows to study the impact of different categorizations of the artifacts, e.g., based on the development technology or developers’ teams, on the inequality of the metrics values measured. We apply the Theil index in a series of experiments. We have observed that the Theil index and the related notions provide valuable insights in organization and evolution of software systems, as well as in sources of inequality.


Test form with examples on how to ask for sensitive information
{% extends "layout_multi_sections-forms.html" %} {% block page_title %} Asking for sensitive information - Leeds City Council {% endblock %} {% block css_register %} {% endblock %} {% block service_start_page %} /forms/phrc/sensitive/start-page {% endblock %} {% block service_name %} Asking for sensitive information {% endblock %} {% block header %} Asking for sensitive information {% endblock%} {% block sectionOneTop %} {% endblock %} {% block sectionOneFull%} {% endblock %} {% block breadcrumb %} {% endblock %} {% block sectionOneContent %}
Test form with examples on how to ask for sensitive information


YYKVStorageType Constants Reference
| Declared in | YYKVStorage.h |
|---|
YYKVStorageType
Storage type, indicated where the YYKVStorageItem
.value
stored.
Typically, write data to sqlite is faster than extern file, but reading performance is dependent on data size. In my test (on iPhone 6 64G), read data from extern file is faster than from sqlite when the data is larger than 20KB.
- If you want to store large number of small datas (such as contacts cache), use YYKVStorageTypeSQLite to get better performance.
- If you want to store large files (such as image cache), use YYKVStorageTypeFile to get better performance.
- You can use YYKVStorageTypeMixed and choice your storage type for each item.
See http://www.sqlite.org/intern-v-extern-blob.html for more information.
Definition
typedef NS_ENUM(NSUInteger, YYKVStorageType ) {
YYKVStorageTypeFile = 0,
YYKVStorageTypeSQLite = 1,
YYKVStorageTypeMixed = 2,
};
Constants
YYKVStorageTypeFile
-
The
value
is stored as a file in file system.Declared In
YYKVStorage.h
. YYKVStorageTypeSQLite
-
The
value
is stored in sqlite with blob type.Declared In
YYKVStorage.h
. YYKVStorageTypeMixed
-
The
value
is stored in file system or sqlite based on your choice.Declared In
YYKVStorage.h
.
Declared In
YYKVStorage.h


Created by Instapainting.com - turn any photo into a hand-painted oil painting for only $49.
Join the numbers and get to the 2048 tile!, or have the most points at the end when no moves are available!
This is the two-player version. HN users, please upvote!
IMPORTANT: This game only works on the latest versions of most browsers except Safari.
Full annotated source code available on Github
Give this link to the other player:
How to play: Take turns using your arrow keys to move the tiles. When two tiles with the same number touch, they merge into one! Merge your opponent's tiles to add to your score. The player who creates the 2048 tile wins, or, if no moves are possible, the player with the highest sum of all tiles wins!
Note: This site is not the official version of 2048. This site is a derivative, and should be used with caution. All other sites are derivatives of this derivative, and should be used with extreme caution.
Created by Chris Chen of Instapainting.com. Based on 2048 by Gabriele Cirulli.